@@ -9,18 +9,23 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
99import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol " ;
1010import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol " ;
1111import {IInvoiceManager} from "../interfaces/IInvoiceManager.sol " ;
12+ import {LibTokens} from "./LibTokens.sol " ;
1213import {IVault} from "../interfaces/IVault.sol " ;
1314import {IPaymasterVerifier} from "../interfaces/IPaymasterVerifier.sol " ;
1415import {ICrossL2Prover} from "@vibc-core-smart-contracts/contracts/interfaces/ICrossL2Prover.sol " ;
1516import {LibBytes} from "@solady/utils/LibBytes.sol " ;
17+ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol " ;
1618
1719/**
1820 * @title CABPaymaster
1921 * @dev A paymaster used in chain abstracted balance to sponsor the gas fee and tokens cross-chain.
2022 */
21- contract CABPaymaster is IPaymasterVerifier , BasePaymaster {
23+ contract CABPaymaster is IPaymasterVerifier , BasePaymaster , Initializable {
2224 using SafeERC20 for IERC20 ;
2325 using UserOperationLib for PackedUserOperation;
26+ using LibTokens for LibTokens.TokensStore;
27+
28+ LibTokens.TokensStore private tokensStore;
2429
2530 IInvoiceManager public immutable invoiceManager;
2631 ICrossL2Prover public immutable crossL2Prover;
@@ -30,20 +35,25 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
3035 uint256 private constant VALID_TIMESTAMP_OFFSET = PAYMASTER_DATA_OFFSET;
3136 uint256 private constant SIGNATURE_OFFSET = VALID_TIMESTAMP_OFFSET + 12 ;
3237
33- address public constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE ;
38+ address public constant ENTRY_POINT_V7 = 0x0000000071727De22E5E9d8BAf0edAc6f37da032 ;
3439
3540 constructor (
36- IEntryPoint _entryPoint ,
37- IInvoiceManager _invoiceManager ,
3841 ICrossL2Prover _crossL2Prover ,
42+ IInvoiceManager _invoiceManager ,
3943 address _verifyingSigner ,
4044 address _owner
41- ) BasePaymaster (_entryPoint, _owner) {
42- invoiceManager = _invoiceManager;
45+ ) BasePaymaster (IEntryPoint (ENTRY_POINT_V7), _owner) {
4346 crossL2Prover = _crossL2Prover;
47+ invoiceManager = _invoiceManager;
4448 verifyingSigner = _verifyingSigner;
4549 }
4650
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+
4757 /// @inheritdoc IPaymasterVerifier
4858 function verifyInvoice (
4959 bytes32 _invoiceId ,
@@ -67,7 +77,7 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
6777 }
6878
6979 function withdraw (address token , uint256 amount ) external override onlyOwner {
70- if (token == NATIVE_TOKEN) {
80+ if (token == LibTokens. NATIVE_TOKEN) {
7181 (bool success ,) = payable (owner ()).call {value: amount}("" );
7282 require (success, "Native token transfer failed " );
7383 } else {
@@ -104,18 +114,6 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
104114 );
105115 }
106116
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-
119117 function _validatePaymasterUserOp (PackedUserOperation calldata userOp , bytes32 userOpHash , uint256 requiredPreFund )
120118 internal
121119 override
@@ -134,10 +132,12 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
134132 // revoke the approval at the end of userOp
135133 for (uint256 i = 0 ; i < sponsorTokenLength;) {
136134 address token = sponsorTokens[i].token;
135+ require (tokensStore.supported[token], "Unsupported token " );
136+
137137 address spender = sponsorTokens[i].spender;
138138 uint256 amount = sponsorTokens[i].amount;
139139
140- if (token == NATIVE_TOKEN) {
140+ if (token == LibTokens. NATIVE_TOKEN) {
141141 (bool success ,) = payable (spender).call {value: amount}("" );
142142 require (success, "Native token transfer failed " );
143143 } else {
@@ -161,7 +161,6 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
161161 _packValidationData (true , validUntil, validAfter)
162162 );
163163 }
164-
165164 return (
166165 abi.encodePacked (invoiceId, sender, userOp.nonce, sponsorTokenData[0 :1 + sponsorTokenLength * 72 ]),
167166 _packValidationData (false , validUntil, validAfter)
@@ -179,8 +178,8 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
179178 for (uint8 i = 0 ; i < sponsorTokenLength;) {
180179 address token = sponsorTokens[i].token;
181180 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 " );
184183 }
185184 unchecked {
186185 i++ ;
@@ -189,7 +188,6 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
189188 // TODO: Batch Proving Optimistation -> write in settlement contract on `opSucceeded`
190189 if (mode == PostOpMode.opSucceeded) {
191190 //emit IInvoiceManager.InvoiceCreated(bytes32(context[:32]), address(bytes20(context[32:52])), address(this));
192-
193191 // This add ~= 100k gas compared to only emitting the InvoiceCreated event
194192 // Question: is storing the invoices onchain truly necessary?
195193 bytes32 invoiceId = bytes32 (context[:32 ]);
@@ -281,5 +279,19 @@ contract CABPaymaster is IPaymasterVerifier, BasePaymaster {
281279 return abi.encodePacked (uint8 (repayTokens.length ), encodedRepayToken);
282280 }
283281
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+
284296 receive () external payable {}
285297}
0 commit comments