1
1
// SPDX-License-Identifier: MIT
2
2
3
- pragma solidity ^ 0.8.24 ;
3
+ pragma solidity ^ 0.8.27 ;
4
4
5
5
import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol " ;
6
6
import {IERC1271 } from "@openzeppelin/contracts/interfaces/IERC1271.sol " ;
@@ -19,7 +19,7 @@ import {Account} from "../Account.sol";
19
19
* To comply with the ERC-1271 support requirement, this contract defers signature validation to
20
20
* installed validator modules by calling {IERC7579Validator-isValidSignatureWithSender}.
21
21
*
22
- * This contract does not implement validation logic for user operations since these functionality
22
+ * This contract does not implement validation logic for user operations since this functionality
23
23
* is often delegated to self-contained validation modules. Developers must install a validator module
24
24
* upon initialization (or any other mechanism to enable execution from the account):
25
25
*
@@ -40,7 +40,12 @@ import {Account} from "../Account.sol";
40
40
* internal virtual functions {_extractUserOpValidator} and {_extractSignatureValidator}. Both are implemented
41
41
* following common practices. However, this part is not standardized in ERC-7579 (or in any follow-up ERC). Some
42
42
* accounts may want to override these internal functions.
43
+ * * When combined with {ERC7739}, resolution ordering of {isValidSignature} may have an impact ({ERC7739} does not
44
+ * call super). Manual resolution might be necessary.
45
+ * * Static calls (using callType `0xfe`) are currently NOT supported.
43
46
* ====
47
+ *
48
+ * WARNING: Removing all validator modules will render the account inoperable, as no user operations can be validated thereafter.
44
49
*/
45
50
abstract contract AccountERC7579 is Account , IERC1271 , IERC7579Execution , IERC7579AccountConfig , IERC7579ModuleConfig {
46
51
using Bytes for * ;
@@ -163,8 +168,8 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
163
168
* @dev Implement ERC-1271 through IERC7579Validator modules. If module based validation fails, fallback to
164
169
* "native" validation by the abstract signer.
165
170
*
166
- * NOTE: when combined with {ERC7739} (for example through {Account}) , resolution ordering may have an impact
167
- * ({ERC7739} does not call super). Manual resolution might be necessary.
171
+ * NOTE: when combined with {ERC7739}, resolution ordering may have an impact ({ERC7739} does not call super).
172
+ * Manual resolution might be necessary.
168
173
*/
169
174
function isValidSignature (bytes32 hash , bytes calldata signature ) public view virtual returns (bytes4 ) {
170
175
// check signature length is enough for extraction
@@ -173,10 +178,10 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
173
178
// if module is not installed, skip
174
179
if (isModuleInstalled (MODULE_TYPE_VALIDATOR, module, Calldata.emptyBytes ())) {
175
180
// try validation, skip any revert
176
- try IERC7579Validator (module).isValidSignatureWithSender (address ( this ) , hash, innerSignature) returns (
181
+ try IERC7579Validator (module).isValidSignatureWithSender (msg . sender , hash, innerSignature) returns (
177
182
bytes4 magic
178
183
) {
179
- if (magic == IERC1271 .isValidSignature. selector ) return magic;
184
+ return magic;
180
185
} catch {}
181
186
}
182
187
}
@@ -220,8 +225,8 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
220
225
/**
221
226
* @dev Installs a module of the given type with the given initialization data.
222
227
*
223
- * For the fallback module type, the `initData` is expected to be a tuple of a 4-byte selector and the
224
- * rest of the data to be sent to the handler when calling {IERC7579Module-onInstall}.
228
+ * For the fallback module type, the `initData` is expected to be the (packed) concatenation of a 4-byte
229
+ * selector and the rest of the data to be sent to the handler when calling {IERC7579Module-onInstall}.
225
230
*
226
231
* Requirements:
227
232
*
@@ -259,14 +264,16 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
259
264
/**
260
265
* @dev Uninstalls a module of the given type with the given de-initialization data.
261
266
*
262
- * For the fallback module type, the `deInitData` is expected to be a tuple of a 4-byte selector and the
263
- * rest of the data to be sent to the handler when calling {IERC7579Module-onUninstall}.
267
+ * For the fallback module type, the `deInitData` is expected to be the (packed) concatenation of a 4-byte
268
+ * selector and the rest of the data to be sent to the handler when calling {IERC7579Module-onUninstall}.
264
269
*
265
270
* Requirements:
266
271
*
267
272
* * Module must be already installed. Reverts with {ERC7579UninstalledModule} otherwise.
268
273
*/
269
274
function _uninstallModule (uint256 moduleTypeId , address module , bytes memory deInitData ) internal virtual {
275
+ require (supportsModule (moduleTypeId), ERC7579Utils .ERC7579UnsupportedModuleType (moduleTypeId));
276
+
270
277
if (moduleTypeId == MODULE_TYPE_VALIDATOR) {
271
278
require (_validators.remove (module), ERC7579Utils .ERC7579UninstalledModule (moduleTypeId, module));
272
279
} else if (moduleTypeId == MODULE_TYPE_EXECUTOR) {
@@ -336,9 +343,10 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
336
343
* ```
337
344
* <module address (20 bytes)> | <key (4 bytes)> | <nonce (8 bytes)>
338
345
* ```
339
- * NOTE: The default behavior of this function replicated the behavior of
340
- * https://github.com/rhinestonewtf/safe7579/blob/bb29e8b1a66658790c4169e72608e27d220f79be/src/Safe7579.sol#L266[Safe adapter] and
341
- * https://github.com/etherspot/etherspot-prime-contracts/blob/cfcdb48c4172cea0d66038324c0bae3288aa8caa/src/modular-etherspot-wallet/wallet/ModularEtherspotWallet.sol#L227[Etherspot's Prime Account].
346
+ * NOTE: The default behavior of this function replicates the behavior of
347
+ * https://github.com/rhinestonewtf/safe7579/blob/bb29e8b1a66658790c4169e72608e27d220f79be/src/Safe7579.sol#L266[Safe adapter],
348
+ * https://github.com/etherspot/etherspot-prime-contracts/blob/cfcdb48c4172cea0d66038324c0bae3288aa8caa/src/modular-etherspot-wallet/wallet/ModularEtherspotWallet.sol#L227[Etherspot's Prime Account], and
349
+ * https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/MSAAdvanced.sol#L247[ERC7579 reference implementation].
342
350
*
343
351
* This is not standardized in ERC-7579 (or in any follow-up ERC). Some accounts may want to override these internal functions.
344
352
*
@@ -359,10 +367,11 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
359
367
* <module address (20 bytes)> | <signature data>
360
368
* ```
361
369
*
362
- * NOTE: The default behavior of this function replicated the behavior of
370
+ * NOTE: The default behavior of this function replicates the behavior of
363
371
* https://github.com/rhinestonewtf/safe7579/blob/bb29e8b1a66658790c4169e72608e27d220f79be/src/Safe7579.sol#L350[Safe adapter],
364
- * https://github.com/bcnmy/nexus/blob/54f4e19baaff96081a8843672977caf712ef19f4/contracts/Nexus.sol#L239[Biconomy's Nexus] and
365
- * https://github.com/etherspot/etherspot-prime-contracts/blob/cfcdb48c4172cea0d66038324c0bae3288aa8caa/src/modular-etherspot-wallet/wallet/ModularEtherspotWallet.sol#L252[Etherspot's Prime Account]
372
+ * https://github.com/bcnmy/nexus/blob/54f4e19baaff96081a8843672977caf712ef19f4/contracts/Nexus.sol#L239[Biconomy's Nexus],
373
+ * https://github.com/etherspot/etherspot-prime-contracts/blob/cfcdb48c4172cea0d66038324c0bae3288aa8caa/src/modular-etherspot-wallet/wallet/ModularEtherspotWallet.sol#L252[Etherspot's Prime Account], and
374
+ * https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/MSAAdvanced.sol#L296[ERC7579 reference implementation].
366
375
*
367
376
* This is not standardized in ERC-7579 (or in any follow-up ERC). Some accounts may want to override these internal functions.
368
377
*/
@@ -375,10 +384,10 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
375
384
/**
376
385
* @dev Extract the function selector from initData/deInitData for MODULE_TYPE_FALLBACK
377
386
*
378
- * NOTE: If we had calldata here, we would could use calldata slice which are cheaper to manipulate and don't
379
- * require actual copy. However, this would require `_installModule` to get a calldata bytes object instead of a
380
- * memory bytes object. This would prevent calling `_installModule` from a contract constructor and would force
381
- * the use of external initializers. That may change in the future, as most accounts will probably be deployed as
387
+ * NOTE: If we had calldata here, we could use calldata slice which are cheaper to manipulate and don't require
388
+ * actual copy. However, this would require `_installModule` to get a calldata bytes object instead of a memory
389
+ * bytes object. This would prevent calling `_installModule` from a contract constructor and would force the use
390
+ * of external initializers. That may change in the future, as most accounts will probably be deployed as
382
391
* clones/proxy/ERC-7702 delegates and therefore rely on initializers anyway.
383
392
*/
384
393
function _decodeFallbackData (
0 commit comments