Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: split IExecution out from IModule and rename vars to reflect new structure #117

Merged
merged 4 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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