@@ -21,10 +21,6 @@ contract LimitingPaymaster is BasePaymaster {
21
21
22
22
address public immutable verifyingSigner;
23
23
24
- uint256 private constant VALID_TIMESTAMP_OFFSET = 20 ;
25
- uint256 private constant SIGNATURE_OFFSET = VALID_TIMESTAMP_OFFSET + 64 ;
26
- uint256 private constant SPENT_KEY_OFFSET = SIGNATURE_OFFSET + 65 ;
27
-
28
24
mapping (uint32 => uint96 ) public spent;
29
25
mapping (address => bool ) public bundlerAllowed;
30
26
@@ -68,13 +64,16 @@ contract LimitingPaymaster is BasePaymaster {
68
64
* verify our external signer signed this request.
69
65
* the "paymasterAndData" is expected to be the paymaster and a signature over the entire request params
70
66
* paymasterAndData[:20] : address(this)
71
- * paymasterAndData[20:84] : abi.encode(validUntil, validAfter)
72
- * paymasterAndData[84:] : signature
73
- * paymasterAndData[149:213] : abi.encode(spentKey, spentMax)
67
+ * paymasterAndData[20:26] : validUntil
68
+ * paymasterAndData[26:32] : validAfter
69
+ * paymasterAndData[32:97] : signature
70
+ * paymasterAndData[97:101] : spendKey
71
+ * paymasterAndData[101:113] : spendMax
72
+ * paymasterAndData[113] : allowAnyBundler
74
73
*/
75
74
function _validatePaymasterUserOp (UserOperation calldata userOp , bytes32 /*userOpHash*/ , uint256 requiredPreFund )
76
75
internal view override returns (bytes memory context , uint256 validationData ) {
77
- (uint48 validUntil , uint48 validAfter , bytes calldata signature , uint32 spentKey , uint96 spentMax ) = parsePaymasterAndData (userOp.paymasterAndData);
76
+ (uint48 validUntil , uint48 validAfter , bytes calldata signature , uint32 spentKey , uint96 spentMax , bool allowAnyBundler ) = parsePaymasterAndData (userOp.paymasterAndData);
78
77
require (spent[spentKey] + requiredPreFund <= spentMax, "Paymaster: spender funds are depleted " );
79
78
// Only support 65-byte signatures, to avoid potential replay attacks.
80
79
require (signature.length == 65 , "Paymaster: invalid signature length in paymasterAndData " );
@@ -87,23 +86,27 @@ contract LimitingPaymaster is BasePaymaster {
87
86
88
87
// no need for other on-chain validation: entire UserOp should have been checked
89
88
// by the external service prior to signing it.
90
- return (abi.encode (spentKey), _packValidationData (false , validUntil, validAfter));
89
+ return (abi.encode (spentKey, allowAnyBundler ), _packValidationData (false , validUntil, validAfter));
91
90
}
92
91
93
92
function _postOp (PostOpMode mode , bytes calldata context , uint256 actualGasCost ) internal override {
93
+ (uint32 spentKey , bool allowAnyBundler ) = abi.decode (context, (uint32 , bool ));
94
+ // unfortunately tx.origin is not allowed in validation, so we check here
95
+ require (allowAnyBundler || bundlerAllowed[tx .origin ], "Paymaster: bundler not allowed " );
96
+
94
97
if (mode != PostOpMode.postOpReverted) {
95
- // unfortunately tx.origin is not allowed in validation, so we check here
96
- require (bundlerAllowed[tx .origin ], "Paymaster: bundler not allowed " );
97
- (uint32 spentKey ) = abi.decode (context, (uint32 ));
98
98
spent[spentKey] += uint96 (actualGasCost);
99
99
}
100
100
}
101
101
102
102
function parsePaymasterAndData (bytes calldata paymasterAndData )
103
- internal pure returns (uint48 validUntil , uint48 validAfter , bytes calldata signature , uint32 spentKey , uint96 spentMax ) {
104
- (validUntil, validAfter) = abi.decode (paymasterAndData[VALID_TIMESTAMP_OFFSET:SIGNATURE_OFFSET], (uint48 , uint48 ));
105
- signature = paymasterAndData[SIGNATURE_OFFSET:SPENT_KEY_OFFSET];
106
- (spentKey, spentMax) = abi.decode (paymasterAndData[SPENT_KEY_OFFSET:], (uint32 , uint96 ));
103
+ internal pure returns (uint48 validUntil , uint48 validAfter , bytes calldata signature , uint32 spentKey , uint96 spentMax , bool allowAnyBundler ) {
104
+ validUntil = uint48 (bytes6 (paymasterAndData[20 :26 ]));
105
+ validAfter = uint48 (bytes6 (paymasterAndData[26 :32 ]));
106
+ signature = paymasterAndData[32 :97 ];
107
+ spentKey = uint32 (bytes4 (paymasterAndData[97 :101 ]));
108
+ spentMax = uint96 (bytes12 (paymasterAndData[101 :113 ]));
109
+ allowAnyBundler = paymasterAndData.length > 113 && paymasterAndData[113 ] > 0 ;
107
110
}
108
111
109
112
function renounceOwnership () public override view onlyOwner {
0 commit comments