Skip to content

Commit

Permalink
Refactor: split IExecution out from IModule and rename vars to reflec…
Browse files Browse the repository at this point in the history
…t new structure (#117)
  • Loading branch information
fangting-alchemy authored and adamegyed committed Aug 5, 2024
1 parent 3f13725 commit 6571f29
Show file tree
Hide file tree
Showing 29 changed files with 200 additions and 199 deletions.
4 changes: 2 additions & 2 deletions src/account/AccountLoupe.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ abstract contract AccountLoupe is IAccountLoupe {
if (
selector == IStandardExecutor.execute.selector || selector == IStandardExecutor.executeBatch.selector
|| selector == UUPSUpgradeable.upgradeToAndCall.selector
|| selector == IModuleManager.installModule.selector
|| selector == IModuleManager.uninstallModule.selector
|| selector == IModuleManager.installExecution.selector
|| selector == IModuleManager.uninstallExecution.selector
) {
return address(this);
}
Expand Down
7 changes: 4 additions & 3 deletions src/account/ModuleManagerInternals.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {HookConfigLib} from "../helpers/HookConfigLib.sol";
import {KnownSelectors} from "../helpers/KnownSelectors.sol";
import {ModuleEntityLib} from "../helpers/ModuleEntityLib.sol";
import {ValidationConfigLib} from "../helpers/ValidationConfigLib.sol";
import {IModule, ManifestExecutionHook, ModuleManifest} from "../interfaces/IModule.sol";
import {ExecutionManifest, ManifestExecutionHook} from "../interfaces/IExecution.sol";
import {IModule} from "../interfaces/IModule.sol";
import {HookConfig, IModuleManager, ModuleEntity, ValidationConfig} from "../interfaces/IModuleManager.sol";
import {
AccountStorage,
Expand Down Expand Up @@ -124,7 +125,7 @@ abstract contract ModuleManagerInternals is IModuleManager {
hooks.remove(toSetValue(hookConfig));
}

function _installModule(address module, ModuleManifest calldata manifest, bytes memory moduleInstallData)
function _installExecution(address module, ExecutionManifest calldata manifest, bytes memory moduleInstallData)
internal
{
AccountStorage storage _storage = getAccountStorage();
Expand Down Expand Up @@ -176,7 +177,7 @@ abstract contract ModuleManagerInternals is IModuleManager {
emit ModuleInstalled(module);
}

function _uninstallModule(address module, ModuleManifest calldata manifest, bytes memory uninstallData)
function _uninstallExecution(address module, ExecutionManifest calldata manifest, bytes memory uninstallData)
internal
{
AccountStorage storage _storage = getAccountStorage();
Expand Down
31 changes: 16 additions & 15 deletions src/account/UpgradeableModularAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import {ValidationConfigLib} from "../helpers/ValidationConfigLib.sol";
import {_coalescePreValidation, _coalesceValidation} from "../helpers/ValidationResHelpers.sol";

import {DIRECT_CALL_VALIDATION_ENTITYID, RESERVED_VALIDATION_DATA_INDEX} from "../helpers/Constants.sol";

import {ExecutionManifest} from "../interfaces/IExecution.sol";
import {IExecutionHook} from "../interfaces/IExecutionHook.sol";
import {ModuleManifest} from "../interfaces/IModule.sol";
import {IModuleManager, ModuleEntity, ValidationConfig} from "../interfaces/IModuleManager.sol";
import {Call, IStandardExecutor} from "../interfaces/IStandardExecutor.sol";
import {IValidation} from "../interfaces/IValidation.sol";
Expand Down Expand Up @@ -89,7 +90,7 @@ contract UpgradeableModularAccount is
error SignatureSegmentOutOfOrder();

// Wraps execution of a native function with runtime validation and hooks
// Used for upgradeTo, upgradeToAndCall, execute, executeBatch, installModule, uninstallModule
// Used for upgradeTo, upgradeToAndCall, execute, executeBatch, installExecution, uninstallExecution
modifier wrapNativeFunction() {
(PostExecToRun[] memory postPermissionHooks, PostExecToRun[] memory postExecHooks) =
_checkPermittedCallerAndAssociatedHooks();
Expand Down Expand Up @@ -224,22 +225,22 @@ contract UpgradeableModularAccount is

/// @inheritdoc IModuleManager
/// @notice May be validated by a global validation.
function installModule(address module, ModuleManifest calldata manifest, bytes calldata moduleInstallData)
external
override
wrapNativeFunction
{
_installModule(module, manifest, moduleInstallData);
function installExecution(
address module,
ExecutionManifest calldata manifest,
bytes calldata moduleInstallData
) external override wrapNativeFunction {
_installExecution(module, manifest, moduleInstallData);
}

/// @inheritdoc IModuleManager
/// @notice May be validated by a global validation.
function uninstallModule(address module, ModuleManifest calldata manifest, bytes calldata moduleUninstallData)
external
override
wrapNativeFunction
{
_uninstallModule(module, manifest, moduleUninstallData);
function uninstallExecution(
address module,
ExecutionManifest calldata manifest,
bytes calldata moduleUninstallData
) external override wrapNativeFunction {
_uninstallExecution(module, manifest, moduleUninstallData);
}

/// @notice Initializes the account with a validation function added to the global pool.
Expand Down Expand Up @@ -689,7 +690,7 @@ contract UpgradeableModularAccount is
function _globalValidationAllowed(bytes4 selector) internal view returns (bool) {
if (
selector == this.execute.selector || selector == this.executeBatch.selector
|| selector == this.installModule.selector || selector == this.uninstallModule.selector
|| selector == this.installExecution.selector || selector == this.uninstallExecution.selector
|| selector == this.installValidation.selector || selector == this.uninstallValidation.selector
|| selector == this.upgradeToAndCall.selector
) {
Expand Down
7 changes: 5 additions & 2 deletions src/helpers/KnownSelectors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeab
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

import {IAccountLoupe} from "../interfaces/IAccountLoupe.sol";

import {IExecution} from "../interfaces/IExecution.sol";
import {IExecutionHook} from "../interfaces/IExecutionHook.sol";
import {IModule} from "../interfaces/IModule.sol";
import {IModuleManager} from "../interfaces/IModuleManager.sol";
Expand All @@ -23,7 +25,8 @@ library KnownSelectors {
// check against IAccount methods
selector == IAccount.validateUserOp.selector
// check against IModuleManager methods
|| selector == IModuleManager.installModule.selector || selector == IModuleManager.uninstallModule.selector
|| selector == IModuleManager.installExecution.selector
|| selector == IModuleManager.uninstallExecution.selector
// check against IERC165 methods
|| selector == IERC165.supportsInterface.selector
// check against UUPSUpgradeable methods
Expand All @@ -47,7 +50,7 @@ library KnownSelectors {

function isIModuleFunction(bytes4 selector) internal pure returns (bool) {
return selector == IModule.onInstall.selector || selector == IModule.onUninstall.selector
|| selector == IModule.moduleManifest.selector || selector == IModule.moduleMetadata.selector
|| selector == IExecution.executionManifest.selector || selector == IModule.moduleMetadata.selector
|| selector == IExecutionHook.preExecutionHook.selector
|| selector == IExecutionHook.postExecutionHook.selector || selector == IValidation.validateUserOp.selector
|| selector == IValidation.validateRuntime.selector || selector == IValidation.validateSignature.selector
Expand Down
39 changes: 39 additions & 0 deletions src/interfaces/IExecution.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.25;

import {IModule} from "./IModule.sol";

struct ManifestExecutionFunction {
// TODO(erc6900 spec): These fields can be packed into a single word
// The selector to install
bytes4 executionSelector;
// If true, the function won't need runtime validation, and can be called by anyone.
bool isPublic;
// If true, the function can be validated by a global validation function.
bool allowGlobalValidation;
}

struct ManifestExecutionHook {
// TODO(erc6900 spec): These fields can be packed into a single word
bytes4 executionSelector;
uint32 entityId;
bool isPreHook;
bool isPostHook;
}

/// @dev A struct describing how the module should be installed on a modular account.
struct ExecutionManifest {
// Execution functions defined in this module to be installed on the MSCA.
ManifestExecutionFunction[] executionFunctions;
ManifestExecutionHook[] executionHooks;
// List of ERC-165 interface IDs to add to account to support introspection checks. This MUST NOT include
// IModule's interface ID.
bytes4[] interfaceIds;
}

interface IExecution is IModule {
/// @notice Describe the contents and intended configuration of the module.
/// @dev This manifest MUST stay constant over time.
/// @return A manifest describing the contents and intended configuration of the module.
function executionManifest() external pure returns (ExecutionManifest memory);
}
37 changes: 2 additions & 35 deletions src/interfaces/IModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,6 @@ pragma solidity ^0.8.25;

import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";

struct ManifestExecutionFunction {
// TODO(erc6900 spec): These fields can be packed into a single word
// The selector to install
bytes4 executionSelector;
// If true, the function won't need runtime validation, and can be called by anyone.
bool isPublic;
// If true, the function can be validated by a global validation function.
bool allowGlobalValidation;
}

struct ManifestExecutionHook {
// TODO(erc6900 spec): These fields can be packed into a single word
bytes4 executionSelector;
uint32 entityId;
bool isPreHook;
bool isPostHook;
}

struct SelectorPermission {
bytes4 functionSelector;
string permissionDescription;
Expand All @@ -42,34 +24,19 @@ struct ModuleMetadata {
string[] permissionRequest;
}

/// @dev A struct describing how the module should be installed on a modular account.
struct ModuleManifest {
// Execution functions defined in this module to be installed on the MSCA.
ManifestExecutionFunction[] executionFunctions;
ManifestExecutionHook[] executionHooks;
// List of ERC-165 interface IDs to add to account to support introspection checks. This MUST NOT include
// IModule's interface ID.
bytes4[] interfaceIds;
}

interface IModule is IERC165 {
/// @notice Initialize module data for the modular account.
/// @dev Called by the modular account during `installModule`.
/// @dev Called by the modular account during `installExecution`.
/// @param data Optional bytes array to be decoded and used by the module to setup initial module data for the
/// modular account.
function onInstall(bytes calldata data) external;

/// @notice Clear module data for the modular account.
/// @dev Called by the modular account during `uninstallModule`.
/// @dev Called by the modular account during `uninstallExecution`.
/// @param data Optional bytes array to be decoded and used by the module to clear module data for the modular
/// account.
function onUninstall(bytes calldata data) external;

/// @notice Describe the contents and intended configuration of the module.
/// @dev This manifest MUST stay constant over time.
/// @return A manifest describing the contents and intended configuration of the module.
function moduleManifest() external pure returns (ModuleManifest memory);

/// @notice Describe the metadata of the module.
/// @dev This metadata MUST stay constant over time.
/// @return A metadata struct describing the module.
Expand Down
16 changes: 11 additions & 5 deletions src/interfaces/IModuleManager.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.25;

import {ModuleManifest} from "./IModule.sol";
import {ExecutionManifest} from "./IExecution.sol";

type ModuleEntity is bytes24;

Expand All @@ -19,8 +19,11 @@ interface IModuleManager {
/// @param manifest the manifest describing functions to install
/// @param moduleInstallData Optional data to be decoded and used by the module to setup initial module data
/// for the modular account.
function installModule(address module, ModuleManifest calldata manifest, bytes calldata moduleInstallData)
external;
function installExecution(
address module,
ExecutionManifest calldata manifest,
bytes calldata moduleInstallData
) external;

/// @notice Temporary install function - pending a different user-supplied install config & manifest validation
/// path.
Expand Down Expand Up @@ -60,6 +63,9 @@ interface IModuleManager {
/// @param manifest the manifest describing functions to uninstall.
/// @param moduleUninstallData Optional data to be decoded and used by the module to clear module data for the
/// modular account.
function uninstallModule(address module, ModuleManifest calldata manifest, bytes calldata moduleUninstallData)
external;
function uninstallExecution(
address module,
ExecutionManifest calldata manifest,
bytes calldata moduleUninstallData
) external;
}
7 changes: 1 addition & 6 deletions src/modules/ERC20TokenLimitModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import {IExecutionHook} from "../interfaces/IExecutionHook.sol";
import {ModuleManifest, ModuleMetadata} from "../interfaces/IModule.sol";
import {IModule} from "../interfaces/IModule.sol";
import {IModule, ModuleMetadata} from "../interfaces/IModule.sol";
import {Call, IStandardExecutor} from "../interfaces/IStandardExecutor.sol";

import {BaseModule, IERC165} from "./BaseModule.sol";
Expand Down Expand Up @@ -114,10 +113,6 @@ contract ERC20TokenLimitModule is BaseModule, IExecutionHook {
revert NotImplemented();
}

/// @inheritdoc IModule
// solhint-disable-next-line no-empty-blocks
function moduleManifest() external pure override returns (ModuleManifest memory) {}

/// @inheritdoc IModule
function moduleMetadata() external pure virtual override returns (ModuleMetadata memory) {
ModuleMetadata memory metadata;
Expand Down
7 changes: 1 addition & 6 deletions src/modules/NativeTokenLimitModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import {IExecutionHook} from "../interfaces/IExecutionHook.sol";
import {ModuleManifest, ModuleMetadata} from "../interfaces/IModule.sol";
import {IModule} from "../interfaces/IModule.sol";
import {IModule, ModuleMetadata} from "../interfaces/IModule.sol";
import {Call, IStandardExecutor} from "../interfaces/IStandardExecutor.sol";

import {IValidationHook} from "../interfaces/IValidationHook.sol";
Expand Down Expand Up @@ -117,10 +116,6 @@ contract NativeTokenLimitModule is BaseModule, IExecutionHook, IValidationHook {
override
{} // solhint-disable-line no-empty-blocks

/// @inheritdoc IModule
// solhint-disable-next-line no-empty-blocks
function moduleManifest() external pure override returns (ModuleManifest memory) {}

/// @inheritdoc IModule
function moduleMetadata() external pure virtual override returns (ModuleMetadata memory) {
ModuleMetadata memory metadata;
Expand Down
12 changes: 7 additions & 5 deletions src/modules/TokenReceiverModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ pragma solidity ^0.8.25;
import {IERC1155Receiver} from "@openzeppelin/contracts/interfaces/IERC1155Receiver.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";

import {IModule, ManifestExecutionFunction, ModuleManifest, ModuleMetadata} from "../interfaces/IModule.sol";
import {ExecutionManifest, ManifestExecutionFunction} from "../interfaces/IExecution.sol";
import {ExecutionManifest, IExecution} from "../interfaces/IExecution.sol";
import {IModule, ModuleMetadata} from "../interfaces/IModule.sol";
import {BaseModule} from "./BaseModule.sol";

/// @title Token Receiver Module
/// @author ERC-6900 Authors
/// @notice This module allows modular accounts to receive various types of tokens by implementing
/// required token receiver interfaces.
contract TokenReceiverModule is BaseModule, IERC721Receiver, IERC1155Receiver {
contract TokenReceiverModule is BaseModule, IExecution, IERC721Receiver, IERC1155Receiver {
string internal constant _NAME = "Token Receiver Module";
string internal constant _VERSION = "1.0.0";
string internal constant _AUTHOR = "ERC-6900 Authors";
Expand Down Expand Up @@ -54,9 +56,9 @@ contract TokenReceiverModule is BaseModule, IERC721Receiver, IERC1155Receiver {
// solhint-disable-next-line no-empty-blocks
function onUninstall(bytes calldata) external pure override {}

/// @inheritdoc IModule
function moduleManifest() external pure override returns (ModuleManifest memory) {
ModuleManifest memory manifest;
/// @inheritdoc IExecution
function executionManifest() external pure override returns (ExecutionManifest memory) {
ExecutionManifest memory manifest;

manifest.executionFunctions = new ManifestExecutionFunction[](3);
manifest.executionFunctions[0] = ManifestExecutionFunction({
Expand Down
5 changes: 1 addition & 4 deletions src/modules/permissionhooks/AllowlistModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.25;

import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";

import {ModuleManifest, ModuleMetadata} from "../../interfaces/IModule.sol";
import {ModuleMetadata} from "../../interfaces/IModule.sol";

import {Call, IStandardExecutor} from "../../interfaces/IStandardExecutor.sol";
import {IValidationHook} from "../../interfaces/IValidationHook.sol";
Expand Down Expand Up @@ -104,9 +104,6 @@ contract AllowlistModule is IValidationHook, BaseModule {
return metadata;
}

// solhint-disable-next-line no-empty-blocks
function moduleManifest() external pure override returns (ModuleManifest memory) {}

function _checkAllowlistCalldata(bytes calldata callData) internal view {
if (bytes4(callData[:4]) == IStandardExecutor.execute.selector) {
(address target,, bytes memory data) = abi.decode(callData[4:], (address, uint256, bytes));
Expand Down
8 changes: 1 addition & 7 deletions src/modules/validation/SingleSignerValidation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";

import {IModule, ModuleManifest, ModuleMetadata} from "../../interfaces/IModule.sol";
import {IModule, ModuleMetadata} from "../../interfaces/IModule.sol";
import {IValidation} from "../../interfaces/IValidation.sol";
import {BaseModule} from "../BaseModule.sol";
import {ISingleSignerValidation} from "./ISingleSignerValidation.sol";
Expand Down Expand Up @@ -118,12 +118,6 @@ contract SingleSignerValidation is ISingleSignerValidation, BaseModule {
// ┃ Module interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

/// @inheritdoc IModule
function moduleManifest() external pure override returns (ModuleManifest memory) {
ModuleManifest memory manifest;
return manifest;
}

/// @inheritdoc IModule
function moduleMetadata() external pure virtual override returns (ModuleMetadata memory) {
ModuleMetadata memory metadata;
Expand Down
Loading

0 comments on commit 6571f29

Please sign in to comment.