11// SPDX-License-Identifier: MIT
22
3- pragma solidity ^ 0.8.24 ;
3+ pragma solidity ^ 0.8.27 ;
44
55import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol " ;
66import {IERC1271 } from "@openzeppelin/contracts/interfaces/IERC1271.sol " ;
@@ -19,7 +19,7 @@ import {Account} from "../Account.sol";
1919 * To comply with the ERC-1271 support requirement, this contract defers signature validation to
2020 * installed validator modules by calling {IERC7579Validator-isValidSignatureWithSender}.
2121 *
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
2323 * is often delegated to self-contained validation modules. Developers must install a validator module
2424 * upon initialization (or any other mechanism to enable execution from the account):
2525 *
@@ -40,7 +40,12 @@ import {Account} from "../Account.sol";
4040 * internal virtual functions {_extractUserOpValidator} and {_extractSignatureValidator}. Both are implemented
4141 * following common practices. However, this part is not standardized in ERC-7579 (or in any follow-up ERC). Some
4242 * 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.
4346 * ====
47+ *
48+ * WARNING: Removing all validator modules will render the account inoperable, as no user operations can be validated thereafter.
4449 */
4550abstract contract AccountERC7579 is Account , IERC1271 , IERC7579Execution , IERC7579AccountConfig , IERC7579ModuleConfig {
4651 using Bytes for * ;
@@ -163,8 +168,8 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
163168 * @dev Implement ERC-1271 through IERC7579Validator modules. If module based validation fails, fallback to
164169 * "native" validation by the abstract signer.
165170 *
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.
168173 */
169174 function isValidSignature (bytes32 hash , bytes calldata signature ) public view virtual returns (bytes4 ) {
170175 // check signature length is enough for extraction
@@ -173,10 +178,10 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
173178 // if module is not installed, skip
174179 if (isModuleInstalled (MODULE_TYPE_VALIDATOR, module, Calldata.emptyBytes ())) {
175180 // 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 (
177182 bytes4 magic
178183 ) {
179- if (magic == IERC1271 .isValidSignature. selector ) return magic;
184+ return magic;
180185 } catch {}
181186 }
182187 }
@@ -220,8 +225,8 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
220225 /**
221226 * @dev Installs a module of the given type with the given initialization data.
222227 *
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}.
225230 *
226231 * Requirements:
227232 *
@@ -259,14 +264,16 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
259264 /**
260265 * @dev Uninstalls a module of the given type with the given de-initialization data.
261266 *
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}.
264269 *
265270 * Requirements:
266271 *
267272 * * Module must be already installed. Reverts with {ERC7579UninstalledModule} otherwise.
268273 */
269274 function _uninstallModule (uint256 moduleTypeId , address module , bytes memory deInitData ) internal virtual {
275+ require (supportsModule (moduleTypeId), ERC7579Utils .ERC7579UnsupportedModuleType (moduleTypeId));
276+
270277 if (moduleTypeId == MODULE_TYPE_VALIDATOR) {
271278 require (_validators.remove (module), ERC7579Utils .ERC7579UninstalledModule (moduleTypeId, module));
272279 } else if (moduleTypeId == MODULE_TYPE_EXECUTOR) {
@@ -336,9 +343,10 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
336343 * ```
337344 * <module address (20 bytes)> | <key (4 bytes)> | <nonce (8 bytes)>
338345 * ```
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].
342350 *
343351 * This is not standardized in ERC-7579 (or in any follow-up ERC). Some accounts may want to override these internal functions.
344352 *
@@ -359,10 +367,11 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
359367 * <module address (20 bytes)> | <signature data>
360368 * ```
361369 *
362- * NOTE: The default behavior of this function replicated the behavior of
370+ * NOTE: The default behavior of this function replicates the behavior of
363371 * 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].
366375 *
367376 * This is not standardized in ERC-7579 (or in any follow-up ERC). Some accounts may want to override these internal functions.
368377 */
@@ -375,10 +384,10 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
375384 /**
376385 * @dev Extract the function selector from initData/deInitData for MODULE_TYPE_FALLBACK
377386 *
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
382391 * clones/proxy/ERC-7702 delegates and therefore rely on initializers anyway.
383392 */
384393 function _decodeFallbackData (
0 commit comments