@@ -9,18 +9,23 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
9
9
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol " ;
10
10
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol " ;
11
11
import {IInvoiceManager} from "../interfaces/IInvoiceManager.sol " ;
12
+ import {LibTokens} from "./LibTokens.sol " ;
12
13
import {IVault} from "../interfaces/IVault.sol " ;
13
14
import {IPaymasterVerifier} from "../interfaces/IPaymasterVerifier.sol " ;
14
15
import {ICrossL2Prover} from "@vibc-core-smart-contracts/contracts/interfaces/ICrossL2Prover.sol " ;
15
16
import {LibBytes} from "@solady/utils/LibBytes.sol " ;
17
+ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol " ;
16
18
17
19
/**
18
20
* @title CABPaymaster
19
21
* @dev A paymaster used in chain abstracted balance to sponsor the gas fee and tokens cross-chain.
20
22
*/
21
- contract CABPaymaster is IPaymasterVerifier , BasePaymaster {
23
+ contract CABPaymaster is IPaymasterVerifier , BasePaymaster , Initializable {
22
24
using SafeERC20 for IERC20 ;
23
25
using UserOperationLib for PackedUserOperation;
26
+ using LibTokens for LibTokens.TokensStore;
27
+
28
+ LibTokens.TokensStore private tokensStore;
24
29
25
30
IInvoiceManager public immutable invoiceManager;
26
31
ICrossL2Prover public immutable crossL2Prover;
@@ -30,20 +35,25 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
30
35
uint256 private constant VALID_TIMESTAMP_OFFSET = PAYMASTER_DATA_OFFSET;
31
36
uint256 private constant SIGNATURE_OFFSET = VALID_TIMESTAMP_OFFSET + 12 ;
32
37
33
- address public constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE ;
38
+ address public constant ENTRY_POINT_V7 = 0x0000000071727De22E5E9d8BAf0edAc6f37da032 ;
34
39
35
40
constructor (
36
- IEntryPoint _entryPoint ,
37
- IInvoiceManager _invoiceManager ,
38
41
ICrossL2Prover _crossL2Prover ,
42
+ IInvoiceManager _invoiceManager ,
39
43
address _verifyingSigner ,
40
44
address _owner
41
- ) BasePaymaster (_entryPoint, _owner) {
42
- invoiceManager = _invoiceManager;
45
+ ) BasePaymaster (IEntryPoint (ENTRY_POINT_V7), _owner) {
43
46
crossL2Prover = _crossL2Prover;
47
+ invoiceManager = _invoiceManager;
44
48
verifyingSigner = _verifyingSigner;
45
49
}
46
50
51
+ function initialize (address [] memory _supportedTokens ) public initializer {
52
+ for (uint256 i = 0 ; i < _supportedTokens.length ; i++ ) {
53
+ tokensStore.addSupportedToken (_supportedTokens[i]);
54
+ }
55
+ }
56
+
47
57
/// @inheritdoc IPaymasterVerifier
48
58
function verifyInvoice (
49
59
bytes32 _invoiceId ,
@@ -67,7 +77,7 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
67
77
}
68
78
69
79
function withdraw (address token , uint256 amount ) external override onlyOwner {
70
- if (token == NATIVE_TOKEN) {
80
+ if (token == LibTokens. NATIVE_TOKEN) {
71
81
(bool success ,) = payable (owner ()).call {value: amount}("" );
72
82
require (success, "Native token transfer failed " );
73
83
} else {
@@ -104,18 +114,6 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
104
114
);
105
115
}
106
116
107
- function getInvoiceHash (IInvoiceManager.InvoiceWithRepayTokens calldata invoice ) public pure returns (bytes32 ) {
108
- return keccak256 (
109
- abi.encode (
110
- invoice.account,
111
- invoice.nonce,
112
- invoice.paymaster,
113
- invoice.sponsorChainId,
114
- keccak256 (abi.encode (invoice.repayTokenInfos))
115
- )
116
- );
117
- }
118
-
119
117
function _validatePaymasterUserOp (PackedUserOperation calldata userOp , bytes32 userOpHash , uint256 requiredPreFund )
120
118
internal
121
119
override
@@ -134,10 +132,12 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
134
132
// revoke the approval at the end of userOp
135
133
for (uint256 i = 0 ; i < sponsorTokenLength;) {
136
134
address token = sponsorTokens[i].token;
135
+ require (tokensStore.supported[token], "Unsupported token " );
136
+
137
137
address spender = sponsorTokens[i].spender;
138
138
uint256 amount = sponsorTokens[i].amount;
139
139
140
- if (token == NATIVE_TOKEN) {
140
+ if (token == LibTokens. NATIVE_TOKEN) {
141
141
(bool success ,) = payable (spender).call {value: amount}("" );
142
142
require (success, "Native token transfer failed " );
143
143
} else {
@@ -161,7 +161,6 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
161
161
_packValidationData (true , validUntil, validAfter)
162
162
);
163
163
}
164
-
165
164
return (
166
165
abi.encodePacked (invoiceId, sender, userOp.nonce, sponsorTokenData[0 :1 + sponsorTokenLength * 72 ]),
167
166
_packValidationData (false , validUntil, validAfter)
@@ -179,8 +178,8 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
179
178
for (uint8 i = 0 ; i < sponsorTokenLength;) {
180
179
address token = sponsorTokens[i].token;
181
180
address spender = sponsorTokens[i].spender;
182
- if (token != NATIVE_TOKEN) {
183
- require (IERC20 (token).approve (spender, 0 ), "Reset approval failed " );
181
+ if (token != LibTokens. NATIVE_TOKEN) {
182
+ require (IERC20 (token).approve (spender, 0 ), "CABPaymaster: Reset approval failed " );
184
183
}
185
184
unchecked {
186
185
i++ ;
@@ -189,7 +188,6 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
189
188
// TODO: Batch Proving Optimistation -> write in settlement contract on `opSucceeded`
190
189
if (mode == PostOpMode.opSucceeded) {
191
190
//emit IInvoiceManager.InvoiceCreated(bytes32(context[:32]), address(bytes20(context[32:52])), address(this));
192
-
193
191
// This add ~= 100k gas compared to only emitting the InvoiceCreated event
194
192
// Question: is storing the invoices onchain truly necessary?
195
193
bytes32 invoiceId = bytes32 (context[:32 ]);
@@ -281,5 +279,19 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
281
279
return abi.encodePacked (uint8 (repayTokens.length ), encodedRepayToken);
282
280
}
283
281
282
+ function addSupportedToken (address token ) public onlyOwner {
283
+ tokensStore.addSupportedToken (token);
284
+ emit LibTokens.SupportedTokenAdded (token);
285
+ }
286
+
287
+ function removeSupportedToken (address token ) public onlyOwner {
288
+ tokensStore.removeSupportedToken (token);
289
+ emit LibTokens.SupportedTokenRemoved (token);
290
+ }
291
+
292
+ function getSupportedTokens () public view returns (address [] memory ) {
293
+ return tokensStore.getSupportedTokens ();
294
+ }
295
+
284
296
receive () external payable {}
285
297
}
0 commit comments