diff --git a/README.md b/README.md
index 1c90c710..b3b625b4 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
Reference implementation for [ERC-6900](https://eips.ethereum.org/EIPS/eip-6900). It is an early draft implementation.
-The implementation includes an upgradable modular account with two plugins (`SingleSignerValidation` and `TokenReceiverPlugin`). It is compliant with ERC-6900 with the latest updates.
+The implementation includes an upgradable modular account with three modules (`SingleSignerValidation`, `TokenReceiverModule`, and `AllowlistModule`). It is compliant with ERC-6900 with the latest updates.
## Important Callouts
@@ -11,7 +11,7 @@ The implementation includes an upgradable modular account with two plugins (`Sin
## Development
-Anyone is welcome to submit feedback and/or PRs to improve code or add Plugins.
+Anyone is welcome to submit feedback and/or PRs to improve code.
### Testing
diff --git a/src/account/AccountLoupe.sol b/src/account/AccountLoupe.sol
index ef679e4e..851c9cfa 100644
--- a/src/account/AccountLoupe.sol
+++ b/src/account/AccountLoupe.sol
@@ -7,7 +7,7 @@ import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {ExecutionHook, IAccountLoupe} from "../interfaces/IAccountLoupe.sol";
-import {IPluginManager, PluginEntity} from "../interfaces/IPluginManager.sol";
+import {IModuleManager, ModuleEntity} from "../interfaces/IModuleManager.sol";
import {IStandardExecutor} from "../interfaces/IStandardExecutor.sol";
import {getAccountStorage, toExecutionHook, toSelector} from "./AccountStorage.sol";
@@ -16,21 +16,21 @@ abstract contract AccountLoupe is IAccountLoupe {
using EnumerableMap for EnumerableMap.AddressToUintMap;
/// @inheritdoc IAccountLoupe
- function getExecutionFunctionHandler(bytes4 selector) external view override returns (address plugin) {
+ function getExecutionFunctionHandler(bytes4 selector) external view override returns (address module) {
if (
selector == IStandardExecutor.execute.selector || selector == IStandardExecutor.executeBatch.selector
|| selector == UUPSUpgradeable.upgradeToAndCall.selector
- || selector == IPluginManager.installPlugin.selector
- || selector == IPluginManager.uninstallPlugin.selector
+ || selector == IModuleManager.installModule.selector
+ || selector == IModuleManager.uninstallModule.selector
) {
return address(this);
}
- return getAccountStorage().selectorData[selector].plugin;
+ return getAccountStorage().selectorData[selector].module;
}
/// @inheritdoc IAccountLoupe
- function getSelectors(PluginEntity validationFunction) external view returns (bytes4[] memory) {
+ function getSelectors(ModuleEntity validationFunction) external view returns (bytes4[] memory) {
uint256 length = getAccountStorage().validationData[validationFunction].selectors.length();
bytes4[] memory selectors = new bytes4[](length);
@@ -62,7 +62,7 @@ abstract contract AccountLoupe is IAccountLoupe {
}
/// @inheritdoc IAccountLoupe
- function getPermissionHooks(PluginEntity validationFunction)
+ function getPermissionHooks(ModuleEntity validationFunction)
external
view
override
@@ -80,17 +80,17 @@ abstract contract AccountLoupe is IAccountLoupe {
}
/// @inheritdoc IAccountLoupe
- function getPreValidationHooks(PluginEntity validationFunction)
+ function getPreValidationHooks(ModuleEntity validationFunction)
external
view
override
- returns (PluginEntity[] memory preValidationHooks)
+ returns (ModuleEntity[] memory preValidationHooks)
{
preValidationHooks = getAccountStorage().validationData[validationFunction].preValidationHooks;
}
/// @inheritdoc IAccountLoupe
- function getInstalledPlugins() external view override returns (address[] memory pluginAddresses) {
- pluginAddresses = getAccountStorage().pluginManifestHashes.keys();
+ function getInstalledModules() external view override returns (address[] memory moduleAddresses) {
+ moduleAddresses = getAccountStorage().moduleManifestHashes.keys();
}
}
diff --git a/src/account/AccountStorage.sol b/src/account/AccountStorage.sol
index dbf0d956..2c480e32 100644
--- a/src/account/AccountStorage.sol
+++ b/src/account/AccountStorage.sol
@@ -5,16 +5,16 @@ import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {ExecutionHook} from "../interfaces/IAccountLoupe.sol";
-import {PluginEntity} from "../interfaces/IPluginManager.sol";
+import {ModuleEntity} from "../interfaces/IModuleManager.sol";
// bytes = keccak256("ERC6900.UpgradeableModularAccount.Storage")
bytes32 constant _ACCOUNT_STORAGE_SLOT = 0x9f09680beaa4e5c9f38841db2460c401499164f368baef687948c315d9073e40;
// Represents data associated with a specifc function selector.
struct SelectorData {
- // The plugin that implements this execution function.
+ // The module that implements this execution function.
// If this is a native function, the address must remain address(0).
- address plugin;
+ address module;
// Whether or not the function needs runtime validation, or can be called by anyone. The function can still be
// state changing if this flag is set to true.
// Note that even if this is set to true, user op validation will still be required, otherwise anyone could
@@ -32,7 +32,7 @@ struct ValidationData {
// Whether or not this validation is a signature validator.
bool isSignatureValidation;
// The pre validation hooks for this validation function.
- PluginEntity[] preValidationHooks;
+ ModuleEntity[] preValidationHooks;
// Permission hooks for this validation function.
EnumerableSet.Bytes32Set permissionHooks;
// The set of selectors that may be validated by this validation function.
@@ -43,11 +43,10 @@ struct AccountStorage {
// AccountStorageInitializable variables
uint8 initialized;
bool initializing;
- // Plugin metadata storage
- EnumerableMap.AddressToUintMap pluginManifestHashes;
+ EnumerableMap.AddressToUintMap moduleManifestHashes;
// Execution functions and their associated functions
mapping(bytes4 => SelectorData) selectorData;
- mapping(PluginEntity validationFunction => ValidationData) validationData;
+ mapping(ModuleEntity validationFunction => ValidationData) validationData;
// For ERC165 introspection
mapping(bytes4 => uint256) supportedIfaces;
}
@@ -60,30 +59,30 @@ function getAccountStorage() pure returns (AccountStorage storage _storage) {
using EnumerableSet for EnumerableSet.Bytes32Set;
-function toSetValue(PluginEntity pluginEntity) pure returns (bytes32) {
- return bytes32(PluginEntity.unwrap(pluginEntity));
+function toSetValue(ModuleEntity moduleEntity) pure returns (bytes32) {
+ return bytes32(ModuleEntity.unwrap(moduleEntity));
}
-function toPluginEntity(bytes32 setValue) pure returns (PluginEntity) {
- return PluginEntity.wrap(bytes24(setValue));
+function toModuleEntity(bytes32 setValue) pure returns (ModuleEntity) {
+ return ModuleEntity.wrap(bytes24(setValue));
}
// ExecutionHook layout:
-// 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF______________________ Hook Plugin Entity
+// 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF______________________ Hook Module Entity
// 0x________________________________________________AA____________________ is pre hook
// 0x__________________________________________________BB__________________ is post hook
function toSetValue(ExecutionHook memory executionHook) pure returns (bytes32) {
- return bytes32(PluginEntity.unwrap(executionHook.hookFunction))
+ return bytes32(ModuleEntity.unwrap(executionHook.hookFunction))
| bytes32(executionHook.isPreHook ? uint256(1) << 56 : 0)
| bytes32(executionHook.isPostHook ? uint256(1) << 48 : 0);
}
function toExecutionHook(bytes32 setValue)
pure
- returns (PluginEntity hookFunction, bool isPreHook, bool isPostHook)
+ returns (ModuleEntity hookFunction, bool isPreHook, bool isPostHook)
{
- hookFunction = PluginEntity.wrap(bytes24(setValue));
+ hookFunction = ModuleEntity.wrap(bytes24(setValue));
isPreHook = (uint256(setValue) >> 56) & 0xFF == 1;
isPostHook = (uint256(setValue) >> 48) & 0xFF == 1;
}
@@ -97,12 +96,12 @@ function toSelector(bytes32 setValue) pure returns (bytes4) {
}
/// @dev Helper function to get all elements of a set into memory.
-function toPluginEntityArray(EnumerableSet.Bytes32Set storage set) view returns (PluginEntity[] memory) {
+function toModuleEntityArray(EnumerableSet.Bytes32Set storage set) view returns (ModuleEntity[] memory) {
uint256 length = set.length();
- PluginEntity[] memory result = new PluginEntity[](length);
+ ModuleEntity[] memory result = new ModuleEntity[](length);
for (uint256 i = 0; i < length; ++i) {
bytes32 key = set.at(i);
- result[i] = PluginEntity.wrap(bytes24(key));
+ result[i] = ModuleEntity.wrap(bytes24(key));
}
return result;
}
diff --git a/src/account/PluginManager2.sol b/src/account/ModuleManager2.sol
similarity index 75%
rename from src/account/PluginManager2.sol
rename to src/account/ModuleManager2.sol
index b77ae1bf..e1868403 100644
--- a/src/account/PluginManager2.sol
+++ b/src/account/ModuleManager2.sol
@@ -3,16 +3,16 @@ pragma solidity ^0.8.25;
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
-import {PluginEntityLib} from "../helpers/PluginEntityLib.sol";
+import {ModuleEntityLib} from "../helpers/ModuleEntityLib.sol";
import {ValidationConfigLib} from "../helpers/ValidationConfigLib.sol";
import {ExecutionHook} from "../interfaces/IAccountLoupe.sol";
-import {IPlugin} from "../interfaces/IPlugin.sol";
-import {PluginEntity, ValidationConfig} from "../interfaces/IPluginManager.sol";
+import {IModule} from "../interfaces/IModule.sol";
+import {ModuleEntity, ValidationConfig} from "../interfaces/IModuleManager.sol";
import {ValidationData, getAccountStorage, toSetValue} from "./AccountStorage.sol";
// Temporary additional functions for a user-controlled install flow for validation functions.
-abstract contract PluginManager2 {
+abstract contract ModuleManager2 {
using EnumerableSet for EnumerableSet.Bytes32Set;
using ValidationConfigLib for ValidationConfig;
@@ -20,10 +20,10 @@ abstract contract PluginManager2 {
uint8 internal constant _RESERVED_VALIDATION_DATA_INDEX = 255;
uint32 internal constant _SELF_PERMIT_VALIDATION_FUNCTIONID = type(uint32).max;
- error PreValidationAlreadySet(PluginEntity validationFunction, PluginEntity preValidationFunction);
- error ValidationAlreadySet(bytes4 selector, PluginEntity validationFunction);
- error ValidationNotSet(bytes4 selector, PluginEntity validationFunction);
- error PermissionAlreadySet(PluginEntity validationFunction, ExecutionHook hook);
+ error PreValidationAlreadySet(ModuleEntity validationFunction, ModuleEntity preValidationFunction);
+ error ValidationAlreadySet(bytes4 selector, ModuleEntity validationFunction);
+ error ValidationNotSet(bytes4 selector, ModuleEntity validationFunction);
+ error PermissionAlreadySet(ModuleEntity validationFunction, ExecutionHook hook);
error PreValidationHookLimitExceeded();
function _installValidation(
@@ -34,20 +34,20 @@ abstract contract PluginManager2 {
bytes memory permissionHooks
) internal {
ValidationData storage _validationData =
- getAccountStorage().validationData[validationConfig.pluginEntity()];
+ getAccountStorage().validationData[validationConfig.moduleEntity()];
if (preValidationHooks.length > 0) {
- (PluginEntity[] memory preValidationFunctions, bytes[] memory initDatas) =
- abi.decode(preValidationHooks, (PluginEntity[], bytes[]));
+ (ModuleEntity[] memory preValidationFunctions, bytes[] memory initDatas) =
+ abi.decode(preValidationHooks, (ModuleEntity[], bytes[]));
for (uint256 i = 0; i < preValidationFunctions.length; ++i) {
- PluginEntity preValidationFunction = preValidationFunctions[i];
+ ModuleEntity preValidationFunction = preValidationFunctions[i];
_validationData.preValidationHooks.push(preValidationFunction);
if (initDatas[i].length > 0) {
- (address preValidationPlugin,) = PluginEntityLib.unpack(preValidationFunction);
- IPlugin(preValidationPlugin).onInstall(initDatas[i]);
+ (address preValidationModule,) = ModuleEntityLib.unpack(preValidationFunction);
+ IModule(preValidationModule).onInstall(initDatas[i]);
}
}
@@ -65,12 +65,12 @@ abstract contract PluginManager2 {
ExecutionHook memory permissionFunction = permissionFunctions[i];
if (!_validationData.permissionHooks.add(toSetValue(permissionFunction))) {
- revert PermissionAlreadySet(validationConfig.pluginEntity(), permissionFunction);
+ revert PermissionAlreadySet(validationConfig.moduleEntity(), permissionFunction);
}
if (initDatas[i].length > 0) {
- (address executionPlugin,) = PluginEntityLib.unpack(permissionFunction.hookFunction);
- IPlugin(executionPlugin).onInstall(initDatas[i]);
+ (address executionModule,) = ModuleEntityLib.unpack(permissionFunction.hookFunction);
+ IModule(executionModule).onInstall(initDatas[i]);
}
}
}
@@ -78,7 +78,7 @@ abstract contract PluginManager2 {
for (uint256 i = 0; i < selectors.length; ++i) {
bytes4 selector = selectors[i];
if (!_validationData.selectors.add(toSetValue(selector))) {
- revert ValidationAlreadySet(selector, validationConfig.pluginEntity());
+ revert ValidationAlreadySet(selector, validationConfig.moduleEntity());
}
}
@@ -88,13 +88,13 @@ abstract contract PluginManager2 {
_validationData.isGlobal = validationConfig.isGlobal();
_validationData.isSignatureValidation = validationConfig.isSignatureValidation();
if (installData.length > 0) {
- IPlugin(validationConfig.plugin()).onInstall(installData);
+ IModule(validationConfig.module()).onInstall(installData);
}
}
}
function _uninstallValidation(
- PluginEntity validationFunction,
+ ModuleEntity validationFunction,
bytes calldata uninstallData,
bytes calldata preValidationHookUninstallData,
bytes calldata permissionHookUninstallData
@@ -108,12 +108,12 @@ abstract contract PluginManager2 {
bytes[] memory preValidationHookUninstallDatas = abi.decode(preValidationHookUninstallData, (bytes[]));
// Clear pre validation hooks
- PluginEntity[] storage preValidationHooks = _validationData.preValidationHooks;
+ ModuleEntity[] storage preValidationHooks = _validationData.preValidationHooks;
for (uint256 i = 0; i < preValidationHooks.length; ++i) {
- PluginEntity preValidationFunction = preValidationHooks[i];
+ ModuleEntity preValidationFunction = preValidationHooks[i];
if (preValidationHookUninstallDatas[0].length > 0) {
- (address preValidationPlugin,) = PluginEntityLib.unpack(preValidationFunction);
- IPlugin(preValidationPlugin).onUninstall(preValidationHookUninstallDatas[0]);
+ (address preValidationModule,) = ModuleEntityLib.unpack(preValidationFunction);
+ IModule(preValidationModule).onUninstall(preValidationHookUninstallDatas[0]);
}
}
delete _validationData.preValidationHooks;
@@ -128,8 +128,8 @@ abstract contract PluginManager2 {
for (uint256 i = 0; i < permissionHookLen; ++i) {
bytes32 permissionHook = permissionHooks.at(0);
permissionHooks.remove(permissionHook);
- address permissionHookPlugin = address(uint160(bytes20(permissionHook)));
- IPlugin(permissionHookPlugin).onUninstall(permissionHookUninstallDatas[i]);
+ address permissionHookModule = address(uint160(bytes20(permissionHook)));
+ IModule(permissionHookModule).onUninstall(permissionHookUninstallDatas[i]);
}
}
@@ -141,8 +141,8 @@ abstract contract PluginManager2 {
}
if (uninstallData.length > 0) {
- (address plugin,) = PluginEntityLib.unpack(validationFunction);
- IPlugin(plugin).onUninstall(uninstallData);
+ (address module,) = ModuleEntityLib.unpack(validationFunction);
+ IModule(module).onUninstall(uninstallData);
}
}
}
diff --git a/src/account/PluginManagerInternals.sol b/src/account/ModuleManagerInternals.sol
similarity index 67%
rename from src/account/PluginManagerInternals.sol
rename to src/account/ModuleManagerInternals.sol
index e473730e..68d6ea1d 100644
--- a/src/account/PluginManagerInternals.sol
+++ b/src/account/ModuleManagerInternals.sol
@@ -7,39 +7,39 @@ import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {KnownSelectors} from "../helpers/KnownSelectors.sol";
-import {PluginEntityLib} from "../helpers/PluginEntityLib.sol";
+import {ModuleEntityLib} from "../helpers/ModuleEntityLib.sol";
import {ExecutionHook} from "../interfaces/IAccountLoupe.sol";
-import {IPlugin, ManifestExecutionHook, ManifestValidation, PluginManifest} from "../interfaces/IPlugin.sol";
-import {IPluginManager, PluginEntity} from "../interfaces/IPluginManager.sol";
+import {IModule, ManifestExecutionHook, ManifestValidation, ModuleManifest} from "../interfaces/IModule.sol";
+import {IModuleManager, ModuleEntity} from "../interfaces/IModuleManager.sol";
import {AccountStorage, SelectorData, getAccountStorage, toSetValue} from "./AccountStorage.sol";
-abstract contract PluginManagerInternals is IPluginManager {
+abstract contract ModuleManagerInternals is IModuleManager {
using EnumerableSet for EnumerableSet.Bytes32Set;
using EnumerableMap for EnumerableMap.AddressToUintMap;
- using PluginEntityLib for PluginEntity;
+ using ModuleEntityLib for ModuleEntity;
error ArrayLengthMismatch();
error Erc4337FunctionNotAllowed(bytes4 selector);
error ExecutionFunctionAlreadySet(bytes4 selector);
- error InvalidPluginManifest();
- error IPluginFunctionNotAllowed(bytes4 selector);
+ error InvalidModuleManifest();
+ error IModuleFunctionNotAllowed(bytes4 selector);
error NativeFunctionNotAllowed(bytes4 selector);
- error NullPluginEntity();
- error NullPlugin();
- error PluginAlreadyInstalled(address plugin);
- error PluginInstallCallbackFailed(address plugin, bytes revertReason);
- error PluginInterfaceNotSupported(address plugin);
- error PluginNotInstalled(address plugin);
- error ValidationFunctionAlreadySet(bytes4 selector, PluginEntity validationFunction);
+ error NullModuleEntity();
+ error NullModule();
+ error ModuleAlreadyInstalled(address module);
+ error ModuleInstallCallbackFailed(address module, bytes revertReason);
+ error ModuleInterfaceNotSupported(address module);
+ error ModuleNotInstalled(address module);
+ error ValidationFunctionAlreadySet(bytes4 selector, ModuleEntity validationFunction);
// Storage update operations
- function _setExecutionFunction(bytes4 selector, bool isPublic, bool allowGlobalValidation, address plugin)
+ function _setExecutionFunction(bytes4 selector, bool isPublic, bool allowGlobalValidation, address module)
internal
{
SelectorData storage _selectorData = getAccountStorage().selectorData[selector];
- if (_selectorData.plugin != address(0)) {
+ if (_selectorData.module != address(0)) {
revert ExecutionFunctionAlreadySet(selector);
}
@@ -49,13 +49,13 @@ abstract contract PluginManagerInternals is IPluginManager {
revert NativeFunctionNotAllowed(selector);
}
- // Make sure incoming execution function is not a function in IPlugin
- if (KnownSelectors.isIPluginFunction(selector)) {
- revert IPluginFunctionNotAllowed(selector);
+ // Make sure incoming execution function is not a function in IModule
+ if (KnownSelectors.isIModuleFunction(selector)) {
+ revert IModuleFunctionNotAllowed(selector);
}
// Also make sure it doesn't collide with functions defined by ERC-4337
- // and called by the entry point. This prevents a malicious plugin from
+ // and called by the entry point. This prevents a malicious module from
// sneaking in a function with the same selector as e.g.
// `validatePaymasterUserOp` and turning the account into their own
// personal paymaster.
@@ -63,7 +63,7 @@ abstract contract PluginManagerInternals is IPluginManager {
revert Erc4337FunctionNotAllowed(selector);
}
- _selectorData.plugin = plugin;
+ _selectorData.module = module;
_selectorData.isPublic = isPublic;
_selectorData.allowGlobalValidation = allowGlobalValidation;
}
@@ -71,15 +71,15 @@ abstract contract PluginManagerInternals is IPluginManager {
function _removeExecutionFunction(bytes4 selector) internal {
SelectorData storage _selectorData = getAccountStorage().selectorData[selector];
- _selectorData.plugin = address(0);
+ _selectorData.module = address(0);
_selectorData.isPublic = false;
_selectorData.allowGlobalValidation = false;
}
- function _addValidationFunction(address plugin, ManifestValidation memory mv) internal {
+ function _addValidationFunction(address module, ManifestValidation memory mv) internal {
AccountStorage storage _storage = getAccountStorage();
- PluginEntity validationFunction = PluginEntityLib.pack(plugin, mv.entityId);
+ ModuleEntity validationFunction = ModuleEntityLib.pack(module, mv.entityId);
if (mv.isDefault) {
_storage.validationData[validationFunction].isGlobal = true;
@@ -97,10 +97,10 @@ abstract contract PluginManagerInternals is IPluginManager {
}
}
- function _removeValidationFunction(address plugin, ManifestValidation memory mv) internal {
+ function _removeValidationFunction(address module, ManifestValidation memory mv) internal {
AccountStorage storage _storage = getAccountStorage();
- PluginEntity validationFunction = PluginEntityLib.pack(plugin, mv.entityId);
+ ModuleEntity validationFunction = ModuleEntityLib.pack(module, mv.entityId);
_storage.validationData[validationFunction].isGlobal = false;
_storage.validationData[validationFunction].isSignatureValidation = false;
@@ -114,7 +114,7 @@ abstract contract PluginManagerInternals is IPluginManager {
function _addExecHooks(
EnumerableSet.Bytes32Set storage hooks,
- PluginEntity hookFunction,
+ ModuleEntity hookFunction,
bool isPreExecHook,
bool isPostExecHook
) internal {
@@ -127,7 +127,7 @@ abstract contract PluginManagerInternals is IPluginManager {
function _removeExecHooks(
EnumerableSet.Bytes32Set storage hooks,
- PluginEntity hookFunction,
+ ModuleEntity hookFunction,
bool isPreExecHook,
bool isPostExecHook
) internal {
@@ -138,31 +138,31 @@ abstract contract PluginManagerInternals is IPluginManager {
);
}
- function _installPlugin(address plugin, bytes32 manifestHash, bytes memory pluginInstallData) internal {
+ function _installModule(address module, bytes32 manifestHash, bytes memory moduleInstallData) internal {
AccountStorage storage _storage = getAccountStorage();
- if (plugin == address(0)) {
- revert NullPlugin();
+ if (module == address(0)) {
+ revert NullModule();
}
- // Check if the plugin exists.
- if (_storage.pluginManifestHashes.contains(plugin)) {
- revert PluginAlreadyInstalled(plugin);
+ // Check if the module exists.
+ if (_storage.moduleManifestHashes.contains(module)) {
+ revert ModuleAlreadyInstalled(module);
}
- // Check that the plugin supports the IPlugin interface.
- if (!ERC165Checker.supportsInterface(plugin, type(IPlugin).interfaceId)) {
- revert PluginInterfaceNotSupported(plugin);
+ // Check that the module supports the IModule interface.
+ if (!ERC165Checker.supportsInterface(module, type(IModule).interfaceId)) {
+ revert ModuleInterfaceNotSupported(module);
}
// Check manifest hash.
- PluginManifest memory manifest = IPlugin(plugin).pluginManifest();
- if (!_isValidPluginManifest(manifest, manifestHash)) {
- revert InvalidPluginManifest();
+ ModuleManifest memory manifest = IModule(module).moduleManifest();
+ if (!_isValidModuleManifest(manifest, manifestHash)) {
+ revert InvalidModuleManifest();
}
- // Add the plugin metadata to the account
- _storage.pluginManifestHashes.set(plugin, uint256(manifestHash));
+ // Add the module metadata to the account
+ _storage.moduleManifestHashes.set(module, uint256(manifestHash));
// Update components according to the manifest.
uint256 length = manifest.executionFunctions.length;
@@ -170,21 +170,21 @@ abstract contract PluginManagerInternals is IPluginManager {
bytes4 selector = manifest.executionFunctions[i].executionSelector;
bool isPublic = manifest.executionFunctions[i].isPublic;
bool allowGlobalValidation = manifest.executionFunctions[i].allowGlobalValidation;
- _setExecutionFunction(selector, isPublic, allowGlobalValidation, plugin);
+ _setExecutionFunction(selector, isPublic, allowGlobalValidation, module);
}
length = manifest.validationFunctions.length;
for (uint256 i = 0; i < length; ++i) {
// Todo: limit this to only "direct runtime call" validation path (old EFP),
// and add a way for the user to specify permission/pre-val hooks here.
- _addValidationFunction(plugin, manifest.validationFunctions[i]);
+ _addValidationFunction(module, manifest.validationFunctions[i]);
}
length = manifest.executionHooks.length;
for (uint256 i = 0; i < length; ++i) {
ManifestExecutionHook memory mh = manifest.executionHooks[i];
EnumerableSet.Bytes32Set storage execHooks = _storage.selectorData[mh.executionSelector].executionHooks;
- PluginEntity hookFunction = PluginEntityLib.pack(plugin, mh.entityId);
+ ModuleEntity hookFunction = ModuleEntityLib.pack(module, mh.entityId);
_addExecHooks(execHooks, hookFunction, mh.isPreHook, mh.isPostHook);
}
@@ -193,30 +193,30 @@ abstract contract PluginManagerInternals is IPluginManager {
_storage.supportedIfaces[manifest.interfaceIds[i]] += 1;
}
- // Initialize the plugin storage for the account.
+ // Initialize the module storage for the account.
// solhint-disable-next-line no-empty-blocks
- try IPlugin(plugin).onInstall(pluginInstallData) {}
+ try IModule(module).onInstall(moduleInstallData) {}
catch (bytes memory revertReason) {
- revert PluginInstallCallbackFailed(plugin, revertReason);
+ revert ModuleInstallCallbackFailed(module, revertReason);
}
- emit PluginInstalled(plugin, manifestHash);
+ emit ModuleInstalled(module, manifestHash);
}
- function _uninstallPlugin(address plugin, PluginManifest memory manifest, bytes memory uninstallData)
+ function _uninstallModule(address module, ModuleManifest memory manifest, bytes memory uninstallData)
internal
{
AccountStorage storage _storage = getAccountStorage();
- // Check if the plugin exists.
- if (!_storage.pluginManifestHashes.contains(plugin)) {
- revert PluginNotInstalled(plugin);
+ // Check if the module exists.
+ if (!_storage.moduleManifestHashes.contains(module)) {
+ revert ModuleNotInstalled(module);
}
// Check manifest hash.
- bytes32 manifestHash = bytes32(_storage.pluginManifestHashes.get(plugin));
- if (!_isValidPluginManifest(manifest, manifestHash)) {
- revert InvalidPluginManifest();
+ bytes32 manifestHash = bytes32(_storage.moduleManifestHashes.get(module));
+ if (!_isValidModuleManifest(manifest, manifestHash)) {
+ revert InvalidModuleManifest();
}
// Remove components according to the manifest, in reverse order (by component type) of their installation.
@@ -224,14 +224,14 @@ abstract contract PluginManagerInternals is IPluginManager {
uint256 length = manifest.executionHooks.length;
for (uint256 i = 0; i < length; ++i) {
ManifestExecutionHook memory mh = manifest.executionHooks[i];
- PluginEntity hookFunction = PluginEntityLib.pack(plugin, mh.entityId);
+ ModuleEntity hookFunction = ModuleEntityLib.pack(module, mh.entityId);
EnumerableSet.Bytes32Set storage execHooks = _storage.selectorData[mh.executionSelector].executionHooks;
_removeExecHooks(execHooks, hookFunction, mh.isPreHook, mh.isPostHook);
}
length = manifest.validationFunctions.length;
for (uint256 i = 0; i < length; ++i) {
- _removeValidationFunction(plugin, manifest.validationFunctions[i]);
+ _removeValidationFunction(module, manifest.validationFunctions[i]);
}
length = manifest.executionFunctions.length;
@@ -245,21 +245,21 @@ abstract contract PluginManagerInternals is IPluginManager {
_storage.supportedIfaces[manifest.interfaceIds[i]] -= 1;
}
- // Remove the plugin metadata from the account.
- _storage.pluginManifestHashes.remove(plugin);
+ // Remove the module metadata from the account.
+ _storage.moduleManifestHashes.remove(module);
- // Clear the plugin storage for the account.
+ // Clear the module storage for the account.
bool onUninstallSuccess = true;
// solhint-disable-next-line no-empty-blocks
- try IPlugin(plugin).onUninstall(uninstallData) {}
+ try IModule(module).onUninstall(uninstallData) {}
catch {
onUninstallSuccess = false;
}
- emit PluginUninstalled(plugin, onUninstallSuccess);
+ emit ModuleUninstalled(module, onUninstallSuccess);
}
- function _isValidPluginManifest(PluginManifest memory manifest, bytes32 manifestHash)
+ function _isValidModuleManifest(ModuleManifest memory manifest, bytes32 manifestHash)
internal
pure
returns (bool)
diff --git a/src/account/UpgradeableModularAccount.sol b/src/account/UpgradeableModularAccount.sol
index 4f64cdd3..9f102313 100644
--- a/src/account/UpgradeableModularAccount.sol
+++ b/src/account/UpgradeableModularAccount.sol
@@ -12,15 +12,15 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeab
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
-import {PluginEntityLib} from "../helpers/PluginEntityLib.sol";
+import {ModuleEntityLib} from "../helpers/ModuleEntityLib.sol";
import {SparseCalldataSegmentLib} from "../helpers/SparseCalldataSegmentLib.sol";
import {ValidationConfigLib} from "../helpers/ValidationConfigLib.sol";
import {_coalescePreValidation, _coalesceValidation} from "../helpers/ValidationResHelpers.sol";
import {IExecutionHook} from "../interfaces/IExecutionHook.sol";
-import {IPlugin, PluginManifest} from "../interfaces/IPlugin.sol";
-import {IPluginManager, PluginEntity, ValidationConfig} from "../interfaces/IPluginManager.sol";
+import {IModule, 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";
import {IValidationHook} from "../interfaces/IValidationHook.sol";
@@ -29,8 +29,8 @@ import {AccountLoupe} from "./AccountLoupe.sol";
import {AccountStorage, getAccountStorage, toExecutionHook, toSetValue} from "./AccountStorage.sol";
import {AccountStorageInitializable} from "./AccountStorageInitializable.sol";
-import {PluginManager2} from "./PluginManager2.sol";
-import {PluginManagerInternals} from "./PluginManagerInternals.sol";
+import {ModuleManager2} from "./ModuleManager2.sol";
+import {ModuleManagerInternals} from "./ModuleManagerInternals.sol";
contract UpgradeableModularAccount is
AccountExecutor,
@@ -41,18 +41,18 @@ contract UpgradeableModularAccount is
IERC1271,
IStandardExecutor,
IAccountExecute,
- PluginManagerInternals,
- PluginManager2,
+ ModuleManagerInternals,
+ ModuleManager2,
UUPSUpgradeable
{
using EnumerableSet for EnumerableSet.Bytes32Set;
- using PluginEntityLib for PluginEntity;
+ using ModuleEntityLib for ModuleEntity;
using ValidationConfigLib for ValidationConfig;
using SparseCalldataSegmentLib for bytes;
struct PostExecToRun {
bytes preExecHookReturnData;
- PluginEntity postExecHook;
+ ModuleEntity postExecHook;
}
IEntryPoint private immutable _ENTRY_POINT;
@@ -68,28 +68,28 @@ contract UpgradeableModularAccount is
event ModularAccountInitialized(IEntryPoint indexed entryPoint);
error AuthorizeUpgradeReverted(bytes revertReason);
- error ExecFromPluginNotPermitted(address plugin, bytes4 selector);
- error ExecFromPluginExternalNotPermitted(address plugin, address target, uint256 value, bytes data);
- error NativeTokenSpendingNotPermitted(address plugin);
+ error ExecFromModuleNotPermitted(address module, bytes4 selector);
+ error ExecFromModuleExternalNotPermitted(address module, address target, uint256 value, bytes data);
+ error NativeTokenSpendingNotPermitted(address module);
error NonCanonicalEncoding();
error NotEntryPoint();
- error PostExecHookReverted(address plugin, uint32 entityId, bytes revertReason);
- error PreExecHookReverted(address plugin, uint32 entityId, bytes revertReason);
- error PreRuntimeValidationHookFailed(address plugin, uint32 entityId, bytes revertReason);
+ error PostExecHookReverted(address module, uint32 entityId, bytes revertReason);
+ error PreExecHookReverted(address module, uint32 entityId, bytes revertReason);
+ error PreRuntimeValidationHookFailed(address module, uint32 entityId, bytes revertReason);
error RequireUserOperationContext();
error RuntimeValidationFunctionMissing(bytes4 selector);
- error RuntimeValidationFunctionReverted(address plugin, uint32 entityId, bytes revertReason);
+ error RuntimeValidationFunctionReverted(address module, uint32 entityId, bytes revertReason);
error SelfCallRecursionDepthExceeded();
- error SignatureValidationInvalid(address plugin, uint32 entityId);
- error UnexpectedAggregator(address plugin, uint32 entityId, address aggregator);
+ error SignatureValidationInvalid(address module, uint32 entityId);
+ error UnexpectedAggregator(address module, uint32 entityId, address aggregator);
error UnrecognizedFunction(bytes4 selector);
error ValidationFunctionMissing(bytes4 selector);
- error ValidationDoesNotApply(bytes4 selector, address plugin, uint32 entityId, bool isGlobal);
+ error ValidationDoesNotApply(bytes4 selector, address module, uint32 entityId, bool isGlobal);
error ValidationSignatureSegmentMissing();
error SignatureSegmentOutOfOrder();
// Wraps execution of a native function with runtime validation and hooks
- // Used for upgradeTo, upgradeToAndCall, execute, executeBatch, installPlugin, uninstallPlugin
+ // Used for upgradeTo, upgradeToAndCall, execute, executeBatch, installModule, uninstallModule
modifier wrapNativeFunction() {
(PostExecToRun[] memory postPermissionHooks, PostExecToRun[] memory postExecHooks) =
_checkPermittedCallerAndAssociatedHooks();
@@ -107,23 +107,23 @@ contract UpgradeableModularAccount is
// EXTERNAL FUNCTIONS
- /// @notice Initializes the account with a set of plugins
- /// @param plugins The plugins to install
- /// @param manifestHashes The manifest hashes of the plugins to install
- /// @param pluginInstallDatas The plugin install datas of the plugins to install
+ /// @notice Initializes the account with a set of modules
+ /// @param modules The modules to install
+ /// @param manifestHashes The manifest hashes of the modules to install
+ /// @param moduleInstallDatas The module install datas of the modules to install
function initialize(
- address[] memory plugins,
+ address[] memory modules,
bytes32[] memory manifestHashes,
- bytes[] memory pluginInstallDatas
+ bytes[] memory moduleInstallDatas
) external initializer {
- uint256 length = plugins.length;
+ uint256 length = modules.length;
- if (length != manifestHashes.length || length != pluginInstallDatas.length) {
+ if (length != manifestHashes.length || length != moduleInstallDatas.length) {
revert ArrayLengthMismatch();
}
for (uint256 i = 0; i < length; ++i) {
- _installPlugin(plugins[i], manifestHashes[i], pluginInstallDatas[i]);
+ _installModule(modules[i], manifestHashes[i], moduleInstallDatas[i]);
}
emit ModularAccountInitialized(_ENTRY_POINT);
@@ -133,10 +133,10 @@ contract UpgradeableModularAccount is
/// @notice Fallback function
/// @dev We route calls to execution functions based on incoming msg.sig
- /// @dev If there's no plugin associated with this function selector, revert
+ /// @dev If there's no module associated with this function selector, revert
fallback(bytes calldata) external payable returns (bytes memory) {
- address execPlugin = getAccountStorage().selectorData[msg.sig].plugin;
- if (execPlugin == address(0)) {
+ address execModule = getAccountStorage().selectorData[msg.sig].module;
+ if (execModule == address(0)) {
revert UnrecognizedFunction(msg.sig);
}
@@ -147,10 +147,10 @@ contract UpgradeableModularAccount is
postExecHooks = _doPreHooks(getAccountStorage().selectorData[msg.sig].executionHooks, msg.data);
// execute the function, bubbling up any reverts
- (bool execSuccess, bytes memory execReturnData) = execPlugin.call(msg.data);
+ (bool execSuccess, bytes memory execReturnData) = execModule.call(msg.data);
if (!execSuccess) {
- // Bubble up revert reasons from plugins
+ // Bubble up revert reasons from modules
assembly ("memory-safe") {
revert(add(execReturnData, 32), mload(execReturnData))
}
@@ -168,7 +168,7 @@ contract UpgradeableModularAccount is
revert NotEntryPoint();
}
- PluginEntity userOpValidationFunction = PluginEntity.wrap(bytes24(userOp.signature[:24]));
+ ModuleEntity userOpValidationFunction = ModuleEntity.wrap(bytes24(userOp.signature[:24]));
PostExecToRun[] memory postPermissionHooks =
_doPreHooks(getAccountStorage().validationData[userOpValidationFunction].permissionHooks, msg.data);
@@ -221,7 +221,7 @@ contract UpgradeableModularAccount is
returns (bytes memory)
{
// Revert if the provided `authorization` less than 21 bytes long, rather than right-padding.
- PluginEntity runtimeValidationFunction = PluginEntity.wrap(bytes24(authorization[:24]));
+ ModuleEntity runtimeValidationFunction = ModuleEntity.wrap(bytes24(authorization[:24]));
// Check if the runtime validation function is allowed to be called
bool isGlobalValidation = uint8(authorization[24]) == 1;
@@ -247,32 +247,32 @@ contract UpgradeableModularAccount is
return returnData;
}
- /// @inheritdoc IPluginManager
+ /// @inheritdoc IModuleManager
/// @notice May be validated by a global validation.
- function installPlugin(address plugin, bytes32 manifestHash, bytes calldata pluginInstallData)
+ function installModule(address module, bytes32 manifestHash, bytes calldata moduleInstallData)
external
override
wrapNativeFunction
{
- _installPlugin(plugin, manifestHash, pluginInstallData);
+ _installModule(module, manifestHash, moduleInstallData);
}
- /// @inheritdoc IPluginManager
+ /// @inheritdoc IModuleManager
/// @notice May be validated by a global validation.
- function uninstallPlugin(address plugin, bytes calldata config, bytes calldata pluginUninstallData)
+ function uninstallModule(address module, bytes calldata config, bytes calldata moduleUninstallData)
external
override
wrapNativeFunction
{
- PluginManifest memory manifest;
+ ModuleManifest memory manifest;
if (config.length > 0) {
- manifest = abi.decode(config, (PluginManifest));
+ manifest = abi.decode(config, (ModuleManifest));
} else {
- manifest = IPlugin(plugin).pluginManifest();
+ manifest = IModule(module).moduleManifest();
}
- _uninstallPlugin(plugin, manifest, pluginUninstallData);
+ _uninstallModule(module, manifest, moduleUninstallData);
}
/// @notice Initializes the account with a validation function added to the global pool.
@@ -290,7 +290,7 @@ contract UpgradeableModularAccount is
emit ModularAccountInitialized(_ENTRY_POINT);
}
- /// @inheritdoc IPluginManager
+ /// @inheritdoc IModuleManager
/// @notice May be validated by a global validation.
function installValidation(
ValidationConfig validationConfig,
@@ -302,10 +302,10 @@ contract UpgradeableModularAccount is
_installValidation(validationConfig, selectors, installData, preValidationHooks, permissionHooks);
}
- /// @inheritdoc IPluginManager
+ /// @inheritdoc IModuleManager
/// @notice May be validated by a global validation.
function uninstallValidation(
- PluginEntity validationFunction,
+ ModuleEntity validationFunction,
bytes calldata uninstallData,
bytes calldata preValidationHookUninstallData,
bytes calldata permissionHookUninstallData
@@ -345,15 +345,15 @@ contract UpgradeableModularAccount is
function isValidSignature(bytes32 hash, bytes calldata signature) public view override returns (bytes4) {
AccountStorage storage _storage = getAccountStorage();
- PluginEntity sigValidation = PluginEntity.wrap(bytes24(signature));
+ ModuleEntity sigValidation = ModuleEntity.wrap(bytes24(signature));
- (address plugin, uint32 entityId) = sigValidation.unpack();
+ (address module, uint32 entityId) = sigValidation.unpack();
if (!_storage.validationData[sigValidation].isSignatureValidation) {
- revert SignatureValidationInvalid(plugin, entityId);
+ revert SignatureValidationInvalid(module, entityId);
}
if (
- IValidation(plugin).validateSignature(address(this), entityId, msg.sender, hash, signature[24:])
+ IValidation(module).validateSignature(address(this), entityId, msg.sender, hash, signature[24:])
== _1271_MAGIC_VALUE
) {
return _1271_MAGIC_VALUE;
@@ -381,7 +381,7 @@ contract UpgradeableModularAccount is
}
// Revert if the provided `authorization` less than 21 bytes long, rather than right-padding.
- PluginEntity userOpValidationFunction = PluginEntity.wrap(bytes24(userOp.signature[:24]));
+ ModuleEntity userOpValidationFunction = ModuleEntity.wrap(bytes24(userOp.signature[:24]));
bool isGlobalValidation = uint8(userOp.signature[24]) == 1;
_checkIfValidationAppliesCallData(userOp.callData, userOpValidationFunction, isGlobalValidation);
@@ -402,7 +402,7 @@ contract UpgradeableModularAccount is
// To support gas estimation, we don't fail early when the failure is caused by a signature failure
function _doUserOpValidation(
- PluginEntity userOpValidationFunction,
+ ModuleEntity userOpValidationFunction,
PackedUserOperation memory userOp,
bytes calldata signature,
bytes32 userOpHash
@@ -414,7 +414,7 @@ contract UpgradeableModularAccount is
uint256 validationRes;
// Do preUserOpValidation hooks
- PluginEntity[] memory preUserOpValidationHooks =
+ ModuleEntity[] memory preUserOpValidationHooks =
getAccountStorage().validationData[userOpValidationFunction].preValidationHooks;
for (uint256 i = 0; i < preUserOpValidationHooks.length; ++i) {
@@ -438,13 +438,13 @@ contract UpgradeableModularAccount is
userOp.signature = "";
}
- (address plugin, uint32 entityId) = preUserOpValidationHooks[i].unpack();
+ (address module, uint32 entityId) = preUserOpValidationHooks[i].unpack();
uint256 currentValidationRes =
- IValidationHook(plugin).preUserOpValidationHook(entityId, userOp, userOpHash);
+ IValidationHook(module).preUserOpValidationHook(entityId, userOp, userOpHash);
if (uint160(currentValidationRes) > 1) {
// If the aggregator is not 0 or 1, it is an unexpected value
- revert UnexpectedAggregator(plugin, entityId, address(uint160(currentValidationRes)));
+ revert UnexpectedAggregator(module, entityId, address(uint160(currentValidationRes)));
}
validationRes = _coalescePreValidation(validationRes, currentValidationRes);
}
@@ -457,8 +457,8 @@ contract UpgradeableModularAccount is
userOp.signature = signatureSegment.getBody();
- (address plugin, uint32 entityId) = userOpValidationFunction.unpack();
- uint256 currentValidationRes = IValidation(plugin).validateUserOp(entityId, userOp, userOpHash);
+ (address module, uint32 entityId) = userOpValidationFunction.unpack();
+ uint256 currentValidationRes = IValidation(module).validateUserOp(entityId, userOp, userOpHash);
if (preUserOpValidationHooks.length != 0) {
// If we have other validation data we need to coalesce with
@@ -472,7 +472,7 @@ contract UpgradeableModularAccount is
}
function _doRuntimeValidation(
- PluginEntity runtimeValidationFunction,
+ ModuleEntity runtimeValidationFunction,
bytes calldata callData,
bytes calldata authorizationData
) internal {
@@ -481,7 +481,7 @@ contract UpgradeableModularAccount is
(authSegment, authorizationData) = authorizationData.getNextSegment();
// run all preRuntimeValidation hooks
- PluginEntity[] memory preRuntimeValidationHooks =
+ ModuleEntity[] memory preRuntimeValidationHooks =
getAccountStorage().validationData[runtimeValidationFunction].preValidationHooks;
for (uint256 i = 0; i < preRuntimeValidationHooks.length; ++i) {
@@ -511,16 +511,16 @@ contract UpgradeableModularAccount is
revert ValidationSignatureSegmentMissing();
}
- (address plugin, uint32 entityId) = runtimeValidationFunction.unpack();
+ (address module, uint32 entityId) = runtimeValidationFunction.unpack();
- try IValidation(plugin).validateRuntime(
+ try IValidation(module).validateRuntime(
address(this), entityId, msg.sender, msg.value, callData, authSegment.getBody()
)
// forgefmt: disable-start
// solhint-disable-next-line no-empty-blocks
{} catch (bytes memory revertReason) {
// forgefmt: disable-end
- revert RuntimeValidationFunctionReverted(plugin, entityId, revertReason);
+ revert RuntimeValidationFunctionReverted(module, entityId, revertReason);
}
}
@@ -536,7 +536,7 @@ contract UpgradeableModularAccount is
// be sure that the set of hooks to run will not be affected by state changes mid-execution.
for (uint256 i = 0; i < hooksLength; ++i) {
bytes32 key = executionHooks.at(i);
- (PluginEntity hookFunction,, bool isPostHook) = toExecutionHook(key);
+ (ModuleEntity hookFunction,, bool isPostHook) = toExecutionHook(key);
if (isPostHook) {
postHooksToRun[i].postExecHook = hookFunction;
}
@@ -546,7 +546,7 @@ contract UpgradeableModularAccount is
// exists.
for (uint256 i = 0; i < hooksLength; ++i) {
bytes32 key = executionHooks.at(i);
- (PluginEntity hookFunction, bool isPreHook, bool isPostHook) = toExecutionHook(key);
+ (ModuleEntity hookFunction, bool isPreHook, bool isPostHook) = toExecutionHook(key);
if (isPreHook) {
bytes memory preExecHookReturnData;
@@ -561,18 +561,18 @@ contract UpgradeableModularAccount is
}
}
- function _runPreExecHook(PluginEntity preExecHook, bytes memory data)
+ function _runPreExecHook(ModuleEntity preExecHook, bytes memory data)
internal
returns (bytes memory preExecHookReturnData)
{
- (address plugin, uint32 entityId) = preExecHook.unpack();
- try IExecutionHook(plugin).preExecutionHook(entityId, msg.sender, msg.value, data) returns (
+ (address module, uint32 entityId) = preExecHook.unpack();
+ try IExecutionHook(module).preExecutionHook(entityId, msg.sender, msg.value, data) returns (
bytes memory returnData
) {
preExecHookReturnData = returnData;
} catch (bytes memory revertReason) {
- // TODO: same issue with EP0.6 - we can't do bytes4 error codes in plugins
- revert PreExecHookReverted(plugin, entityId, revertReason);
+ // TODO: same issue with EP0.6 - we can't do bytes4 error codes in modules
+ revert PreExecHookReverted(module, entityId, revertReason);
}
}
@@ -590,29 +590,29 @@ contract UpgradeableModularAccount is
continue;
}
- (address plugin, uint32 entityId) = postHookToRun.postExecHook.unpack();
+ (address module, uint32 entityId) = postHookToRun.postExecHook.unpack();
// solhint-disable-next-line no-empty-blocks
- try IExecutionHook(plugin).postExecutionHook(entityId, postHookToRun.preExecHookReturnData) {}
+ try IExecutionHook(module).postExecutionHook(entityId, postHookToRun.preExecHookReturnData) {}
catch (bytes memory revertReason) {
- revert PostExecHookReverted(plugin, entityId, revertReason);
+ revert PostExecHookReverted(module, entityId, revertReason);
}
}
}
function _doPreRuntimeValidationHook(
- PluginEntity validationHook,
+ ModuleEntity validationHook,
bytes memory callData,
bytes memory currentAuthData
) internal {
- (address hookPlugin, uint32 hookEntityId) = validationHook.unpack();
- try IValidationHook(hookPlugin).preRuntimeValidationHook(
+ (address hookModule, uint32 hookEntityId) = validationHook.unpack();
+ try IValidationHook(hookModule).preRuntimeValidationHook(
hookEntityId, msg.sender, msg.value, callData, currentAuthData
)
// forgefmt: disable-start
// solhint-disable-next-line no-empty-blocks
{} catch (bytes memory revertReason) {
// forgefmt: disable-end
- revert PreRuntimeValidationHookFailed(hookPlugin, hookEntityId, revertReason);
+ revert PreRuntimeValidationHookFailed(hookModule, hookEntityId, revertReason);
}
}
@@ -645,14 +645,14 @@ contract UpgradeableModularAccount is
return (new PostExecToRun[](0), new PostExecToRun[](0));
}
- PluginEntity directCallValidationKey = PluginEntityLib.pack(msg.sender, _SELF_PERMIT_VALIDATION_FUNCTIONID);
+ ModuleEntity directCallValidationKey = ModuleEntityLib.pack(msg.sender, _SELF_PERMIT_VALIDATION_FUNCTIONID);
_checkIfValidationAppliesCallData(msg.data, directCallValidationKey, false);
// Direct call is allowed, run associated permission & validation hooks
// Validation hooks
- PluginEntity[] memory preRuntimeValidationHooks =
+ ModuleEntity[] memory preRuntimeValidationHooks =
_storage.validationData[directCallValidationKey].preValidationHooks;
uint256 hookLen = preRuntimeValidationHooks.length;
@@ -673,7 +673,7 @@ contract UpgradeableModularAccount is
function _checkIfValidationAppliesCallData(
bytes calldata callData,
- PluginEntity validationFunction,
+ ModuleEntity validationFunction,
bool isGlobal
) internal view {
bytes4 outerSelector = bytes4(callData[:4]);
@@ -712,7 +712,7 @@ contract UpgradeableModularAccount is
// To prevent arbitrarily-deep recursive checking, we limit the depth of self-calls to one
// for the purposes of batching.
// This means that all self-calls must occur at the top level of the batch.
- // Note that plugins of other contracts using `executeWithAuthorization` may still
+ // Note that modules of other contracts using `executeWithAuthorization` may still
// independently call into this account with a different validation function, allowing
// composition of multiple batches.
revert SelfCallRecursionDepthExceeded();
@@ -727,7 +727,7 @@ contract UpgradeableModularAccount is
function _globalValidationAllowed(bytes4 selector) internal view returns (bool) {
if (
selector == this.execute.selector || selector == this.executeBatch.selector
- || selector == this.installPlugin.selector || selector == this.uninstallPlugin.selector
+ || selector == this.installModule.selector || selector == this.uninstallModule.selector
|| selector == this.installValidation.selector || selector == this.uninstallValidation.selector
|| selector == this.upgradeToAndCall.selector
) {
@@ -737,7 +737,7 @@ contract UpgradeableModularAccount is
return getAccountStorage().selectorData[selector].allowGlobalValidation;
}
- function _checkIfValidationAppliesSelector(bytes4 selector, PluginEntity validationFunction, bool isGlobal)
+ function _checkIfValidationAppliesSelector(bytes4 selector, ModuleEntity validationFunction, bool isGlobal)
internal
view
{
diff --git a/src/helpers/KnownSelectors.sol b/src/helpers/KnownSelectors.sol
index ae91f3b7..811f2f5d 100644
--- a/src/helpers/KnownSelectors.sol
+++ b/src/helpers/KnownSelectors.sol
@@ -9,8 +9,8 @@ import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {IAccountLoupe} from "../interfaces/IAccountLoupe.sol";
import {IExecutionHook} from "../interfaces/IExecutionHook.sol";
-import {IPlugin} from "../interfaces/IPlugin.sol";
-import {IPluginManager} from "../interfaces/IPluginManager.sol";
+import {IModule} from "../interfaces/IModule.sol";
+import {IModuleManager} from "../interfaces/IModuleManager.sol";
import {IStandardExecutor} from "../interfaces/IStandardExecutor.sol";
import {IValidation} from "../interfaces/IValidation.sol";
import {IValidationHook} from "../interfaces/IValidationHook.sol";
@@ -22,8 +22,8 @@ library KnownSelectors {
return
// check against IAccount methods
selector == IAccount.validateUserOp.selector
- // check against IPluginManager methods
- || selector == IPluginManager.installPlugin.selector || selector == IPluginManager.uninstallPlugin.selector
+ // check against IModuleManager methods
+ || selector == IModuleManager.installModule.selector || selector == IModuleManager.uninstallModule.selector
// check against IERC165 methods
|| selector == IERC165.supportsInterface.selector
// check against UUPSUpgradeable methods
@@ -36,7 +36,7 @@ library KnownSelectors {
|| selector == IAccountLoupe.getExecutionFunctionHandler.selector
|| selector == IAccountLoupe.getSelectors.selector || selector == IAccountLoupe.getExecutionHooks.selector
|| selector == IAccountLoupe.getPreValidationHooks.selector
- || selector == IAccountLoupe.getInstalledPlugins.selector;
+ || selector == IAccountLoupe.getInstalledModules.selector;
}
function isErc4337Function(bytes4 selector) internal pure returns (bool) {
@@ -46,9 +46,9 @@ library KnownSelectors {
|| selector == IPaymaster.validatePaymasterUserOp.selector || selector == IPaymaster.postOp.selector;
}
- function isIPluginFunction(bytes4 selector) internal pure returns (bool) {
- return selector == IPlugin.onInstall.selector || selector == IPlugin.onUninstall.selector
- || selector == IPlugin.pluginManifest.selector || selector == IPlugin.pluginMetadata.selector
+ 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 == IExecutionHook.preExecutionHook.selector
|| selector == IExecutionHook.postExecutionHook.selector || selector == IValidation.validateUserOp.selector
|| selector == IValidation.validateRuntime.selector || selector == IValidation.validateSignature.selector
diff --git a/src/helpers/ModuleEntityLib.sol b/src/helpers/ModuleEntityLib.sol
new file mode 100644
index 00000000..d8473a5b
--- /dev/null
+++ b/src/helpers/ModuleEntityLib.sol
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.25;
+
+import {ModuleEntity} from "../interfaces/IModuleManager.sol";
+
+library ModuleEntityLib {
+ // Magic value for hooks that should always revert.
+ ModuleEntity internal constant _PRE_HOOK_ALWAYS_DENY = ModuleEntity.wrap(bytes24(uint192(2)));
+
+ function pack(address addr, uint32 entityId) internal pure returns (ModuleEntity) {
+ return ModuleEntity.wrap(bytes24(bytes20(addr)) | bytes24(uint192(entityId)));
+ }
+
+ function unpack(ModuleEntity fr) internal pure returns (address addr, uint32 entityId) {
+ bytes24 underlying = ModuleEntity.unwrap(fr);
+ addr = address(bytes20(underlying));
+ entityId = uint32(bytes4(underlying << 160));
+ }
+
+ function isEmpty(ModuleEntity fr) internal pure returns (bool) {
+ return ModuleEntity.unwrap(fr) == bytes24(0);
+ }
+
+ function notEmpty(ModuleEntity fr) internal pure returns (bool) {
+ return ModuleEntity.unwrap(fr) != bytes24(0);
+ }
+
+ function eq(ModuleEntity a, ModuleEntity b) internal pure returns (bool) {
+ return ModuleEntity.unwrap(a) == ModuleEntity.unwrap(b);
+ }
+
+ function notEq(ModuleEntity a, ModuleEntity b) internal pure returns (bool) {
+ return ModuleEntity.unwrap(a) != ModuleEntity.unwrap(b);
+ }
+}
diff --git a/src/helpers/PluginEntityLib.sol b/src/helpers/PluginEntityLib.sol
deleted file mode 100644
index 423b7f70..00000000
--- a/src/helpers/PluginEntityLib.sol
+++ /dev/null
@@ -1,35 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0
-pragma solidity ^0.8.25;
-
-import {PluginEntity} from "../interfaces/IPluginManager.sol";
-
-library PluginEntityLib {
- // Magic value for hooks that should always revert.
- PluginEntity internal constant _PRE_HOOK_ALWAYS_DENY = PluginEntity.wrap(bytes24(uint192(2)));
-
- function pack(address addr, uint32 entityId) internal pure returns (PluginEntity) {
- return PluginEntity.wrap(bytes24(bytes20(addr)) | bytes24(uint192(entityId)));
- }
-
- function unpack(PluginEntity fr) internal pure returns (address addr, uint32 entityId) {
- bytes24 underlying = PluginEntity.unwrap(fr);
- addr = address(bytes20(underlying));
- entityId = uint32(bytes4(underlying << 160));
- }
-
- function isEmpty(PluginEntity fr) internal pure returns (bool) {
- return PluginEntity.unwrap(fr) == bytes24(0);
- }
-
- function notEmpty(PluginEntity fr) internal pure returns (bool) {
- return PluginEntity.unwrap(fr) != bytes24(0);
- }
-
- function eq(PluginEntity a, PluginEntity b) internal pure returns (bool) {
- return PluginEntity.unwrap(a) == PluginEntity.unwrap(b);
- }
-
- function notEq(PluginEntity a, PluginEntity b) internal pure returns (bool) {
- return PluginEntity.unwrap(a) != PluginEntity.unwrap(b);
- }
-}
diff --git a/src/helpers/ValidationConfigLib.sol b/src/helpers/ValidationConfigLib.sol
index 6d27b907..1c127c3b 100644
--- a/src/helpers/ValidationConfigLib.sol
+++ b/src/helpers/ValidationConfigLib.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.25;
-import {PluginEntity, ValidationConfig} from "../interfaces/IPluginManager.sol";
+import {ModuleEntity, ValidationConfig} from "../interfaces/IModuleManager.sol";
// Validation config is a packed representation of a validation function and flags for its configuration.
// Layout:
@@ -12,14 +12,14 @@ import {PluginEntity, ValidationConfig} from "../interfaces/IPluginManager.sol";
// 0x____________________________________________________000000000000 // unused
library ValidationConfigLib {
- function pack(PluginEntity _validationFunction, bool _isGlobal, bool _isSignatureValidation)
+ function pack(ModuleEntity _validationFunction, bool _isGlobal, bool _isSignatureValidation)
internal
pure
returns (ValidationConfig)
{
return ValidationConfig.wrap(
bytes26(
- bytes26(PluginEntity.unwrap(_validationFunction))
+ bytes26(ModuleEntity.unwrap(_validationFunction))
// isGlobal flag stored in the 25th byte
| bytes26(bytes32(_isGlobal ? uint256(1) << 56 : 0))
// isSignatureValidation flag stored in the 26th byte
@@ -28,15 +28,15 @@ library ValidationConfigLib {
);
}
- function pack(address _plugin, uint32 _entityId, bool _isGlobal, bool _isSignatureValidation)
+ function pack(address _module, uint32 _entityId, bool _isGlobal, bool _isSignatureValidation)
internal
pure
returns (ValidationConfig)
{
return ValidationConfig.wrap(
bytes26(
- // plugin address stored in the first 20 bytes
- bytes26(bytes20(_plugin))
+ // module address stored in the first 20 bytes
+ bytes26(bytes20(_module))
// entityId stored in the 21st - 24th byte
| bytes26(bytes24(uint192(_entityId)))
// isGlobal flag stored in the 25th byte
@@ -50,10 +50,10 @@ library ValidationConfigLib {
function unpackUnderlying(ValidationConfig config)
internal
pure
- returns (address _plugin, uint32 _entityId, bool _isGlobal, bool _isSignatureValidation)
+ returns (address _module, uint32 _entityId, bool _isGlobal, bool _isSignatureValidation)
{
bytes26 configBytes = ValidationConfig.unwrap(config);
- _plugin = address(bytes20(configBytes));
+ _module = address(bytes20(configBytes));
_entityId = uint32(bytes4(configBytes << 160));
_isGlobal = uint8(configBytes[24]) == 1;
_isSignatureValidation = uint8(configBytes[25]) == 1;
@@ -62,15 +62,15 @@ library ValidationConfigLib {
function unpack(ValidationConfig config)
internal
pure
- returns (PluginEntity _validationFunction, bool _isGlobal, bool _isSignatureValidation)
+ returns (ModuleEntity _validationFunction, bool _isGlobal, bool _isSignatureValidation)
{
bytes26 configBytes = ValidationConfig.unwrap(config);
- _validationFunction = PluginEntity.wrap(bytes24(configBytes));
+ _validationFunction = ModuleEntity.wrap(bytes24(configBytes));
_isGlobal = uint8(configBytes[24]) == 1;
_isSignatureValidation = uint8(configBytes[25]) == 1;
}
- function plugin(ValidationConfig config) internal pure returns (address) {
+ function module(ValidationConfig config) internal pure returns (address) {
return address(bytes20(ValidationConfig.unwrap(config)));
}
@@ -78,8 +78,8 @@ library ValidationConfigLib {
return uint32(bytes4(ValidationConfig.unwrap(config) << 160));
}
- function pluginEntity(ValidationConfig config) internal pure returns (PluginEntity) {
- return PluginEntity.wrap(bytes24(ValidationConfig.unwrap(config)));
+ function moduleEntity(ValidationConfig config) internal pure returns (ModuleEntity) {
+ return ModuleEntity.wrap(bytes24(ValidationConfig.unwrap(config)));
}
function isGlobal(ValidationConfig config) internal pure returns (bool) {
diff --git a/src/interfaces/IAccountLoupe.sol b/src/interfaces/IAccountLoupe.sol
index 3e7d9f11..01cca512 100644
--- a/src/interfaces/IAccountLoupe.sol
+++ b/src/interfaces/IAccountLoupe.sol
@@ -1,27 +1,27 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.25;
-import {PluginEntity} from "../interfaces/IPluginManager.sol";
+import {ModuleEntity} from "../interfaces/IModuleManager.sol";
/// @notice Pre and post hooks for a given selector.
/// @dev It's possible for one of either `preExecHook` or `postExecHook` to be empty.
struct ExecutionHook {
- PluginEntity hookFunction;
+ ModuleEntity hookFunction;
bool isPreHook;
bool isPostHook;
}
interface IAccountLoupe {
- /// @notice Get the plugin address for a selector.
- /// @dev If the selector is a native function, the plugin address will be the address of the account.
+ /// @notice Get the module address for a selector.
+ /// @dev If the selector is a native function, the module address will be the address of the account.
/// @param selector The selector to get the configuration for.
- /// @return plugin The plugin address for this selector.
- function getExecutionFunctionHandler(bytes4 selector) external view returns (address plugin);
+ /// @return module The module address for this selector.
+ function getExecutionFunctionHandler(bytes4 selector) external view returns (address module);
/// @notice Get the selectors for a validation function.
/// @param validationFunction The validation function to get the selectors for.
/// @return The allowed selectors for this validation function.
- function getSelectors(PluginEntity validationFunction) external view returns (bytes4[] memory);
+ function getSelectors(ModuleEntity validationFunction) external view returns (bytes4[] memory);
/// @notice Get the pre and post execution hooks for a selector.
/// @param selector The selector to get the hooks for.
@@ -31,17 +31,17 @@ interface IAccountLoupe {
/// @notice Get the pre and post execution hooks for a validation function.
/// @param validationFunction The validation function to get the hooks for.
/// @return The pre and post execution hooks for this validation function.
- function getPermissionHooks(PluginEntity validationFunction) external view returns (ExecutionHook[] memory);
+ function getPermissionHooks(ModuleEntity validationFunction) external view returns (ExecutionHook[] memory);
/// @notice Get the pre user op and runtime validation hooks associated with a selector.
/// @param validationFunction The validation function to get the hooks for.
/// @return preValidationHooks The pre validation hooks for this selector.
- function getPreValidationHooks(PluginEntity validationFunction)
+ function getPreValidationHooks(ModuleEntity validationFunction)
external
view
- returns (PluginEntity[] memory preValidationHooks);
+ returns (ModuleEntity[] memory preValidationHooks);
- /// @notice Get an array of all installed plugins.
- /// @return The addresses of all installed plugins.
- function getInstalledPlugins() external view returns (address[] memory);
+ /// @notice Get an array of all installed modules.
+ /// @return The addresses of all installed modules.
+ function getInstalledModules() external view returns (address[] memory);
}
diff --git a/src/interfaces/IExecutionHook.sol b/src/interfaces/IExecutionHook.sol
index 9cb16482..ad9e52b6 100644
--- a/src/interfaces/IExecutionHook.sol
+++ b/src/interfaces/IExecutionHook.sol
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.25;
-import {IPlugin} from "./IPlugin.sol";
+import {IModule} from "./IModule.sol";
-interface IExecutionHook is IPlugin {
+interface IExecutionHook is IModule {
/// @notice Run the pre execution hook specified by the `entityId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param entityId An identifier that routes the call to different internal implementations, should there
diff --git a/src/interfaces/IPlugin.sol b/src/interfaces/IModule.sol
similarity index 66%
rename from src/interfaces/IPlugin.sol
rename to src/interfaces/IModule.sol
index 824a1ddf..8851acaf 100644
--- a/src/interfaces/IPlugin.sol
+++ b/src/interfaces/IModule.sol
@@ -34,53 +34,53 @@ struct SelectorPermission {
string permissionDescription;
}
-/// @dev A struct holding fields to describe the plugin in a purely view context. Intended for front end clients.
-struct PluginMetadata {
- // A human-readable name of the plugin.
+/// @dev A struct holding fields to describe the module in a purely view context. Intended for front end clients.
+struct ModuleMetadata {
+ // A human-readable name of the module.
string name;
- // The version of the plugin, following the semantic versioning scheme.
+ // The version of the module, following the semantic versioning scheme.
string version;
// The author field SHOULD be a username representing the identity of the user or organization
- // that created this plugin.
+ // that created this module.
string author;
// String desciptions of the relative sensitivity of specific functions. The selectors MUST be selectors for
- // functions implemented by this plugin.
+ // functions implemented by this module.
SelectorPermission[] permissionDescriptors;
- // A list of all ERC-7715 permission strings that the plugin could possibly use
+ // A list of all ERC-7715 permission strings that the module could possibly use
string[] permissionRequest;
}
-/// @dev A struct describing how the plugin should be installed on a modular account.
-struct PluginManifest {
- // Execution functions defined in this plugin to be installed on the MSCA.
+/// @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;
ManifestValidation[] validationFunctions;
ManifestExecutionHook[] executionHooks;
// List of ERC-165 interface IDs to add to account to support introspection checks. This MUST NOT include
- // IPlugin's interface ID.
+ // IModule's interface ID.
bytes4[] interfaceIds;
}
-interface IPlugin is IERC165 {
- /// @notice Initialize plugin data for the modular account.
- /// @dev Called by the modular account during `installPlugin`.
- /// @param data Optional bytes array to be decoded and used by the plugin to setup initial plugin data for the
+interface IModule is IERC165 {
+ /// @notice Initialize module data for the modular account.
+ /// @dev Called by the modular account during `installModule`.
+ /// @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 plugin data for the modular account.
- /// @dev Called by the modular account during `uninstallPlugin`.
- /// @param data Optional bytes array to be decoded and used by the plugin to clear plugin data for the modular
+ /// @notice Clear module data for the modular account.
+ /// @dev Called by the modular account during `uninstallModule`.
+ /// @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 plugin.
+ /// @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 plugin.
- function pluginManifest() external pure returns (PluginManifest memory);
+ /// @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 plugin.
+ /// @notice Describe the metadata of the module.
/// @dev This metadata MUST stay constant over time.
- /// @return A metadata struct describing the plugin.
- function pluginMetadata() external pure returns (PluginMetadata memory);
+ /// @return A metadata struct describing the module.
+ function moduleMetadata() external pure returns (ModuleMetadata memory);
}
diff --git a/src/interfaces/IPluginManager.sol b/src/interfaces/IModuleManager.sol
similarity index 63%
rename from src/interfaces/IPluginManager.sol
rename to src/interfaces/IModuleManager.sol
index d2df72b5..eb2db1ea 100644
--- a/src/interfaces/IPluginManager.sol
+++ b/src/interfaces/IModuleManager.sol
@@ -1,21 +1,21 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.25;
-type PluginEntity is bytes24;
+type ModuleEntity is bytes24;
type ValidationConfig is bytes26;
-interface IPluginManager {
- event PluginInstalled(address indexed plugin, bytes32 manifestHash);
+interface IModuleManager {
+ event ModuleInstalled(address indexed module, bytes32 manifestHash);
- event PluginUninstalled(address indexed plugin, bool indexed onUninstallSucceeded);
+ event ModuleUninstalled(address indexed module, bool indexed onUninstallSucceeded);
- /// @notice Install a plugin to the modular account.
- /// @param plugin The plugin to install.
- /// @param manifestHash The hash of the plugin manifest.
- /// @param pluginInstallData Optional data to be decoded and used by the plugin to setup initial plugin data
+ /// @notice Install a module to the modular account.
+ /// @param module The module to install.
+ /// @param manifestHash The hash of the module manifest.
+ /// @param moduleInstallData Optional data to be decoded and used by the module to setup initial module data
/// for the modular account.
- function installPlugin(address plugin, bytes32 manifestHash, bytes calldata pluginInstallData) external;
+ function installModule(address module, bytes32 manifestHash, bytes calldata moduleInstallData) external;
/// @notice Temporary install function - pending a different user-supplied install config & manifest validation
/// path.
@@ -25,7 +25,7 @@ interface IPluginManager {
/// @dev This does not validate anything against the manifest - the caller must ensure validity.
/// @param validationConfig The validation function to install, along with configuration flags.
/// @param selectors The selectors to install the validation function for.
- /// @param installData Optional data to be decoded and used by the plugin to setup initial plugin state.
+ /// @param installData Optional data to be decoded and used by the module to setup initial module state.
/// @param preValidationHooks Optional pre-validation hooks to install for the validation function.
/// @param permissionHooks Optional permission hooks to install for the validation function.
function installValidation(
@@ -39,23 +39,23 @@ interface IPluginManager {
/// @notice Uninstall a validation function from a set of execution selectors.
/// TODO: remove or update.
/// @param validationFunction The validation function to uninstall.
- /// @param uninstallData Optional data to be decoded and used by the plugin to clear plugin data for the
+ /// @param uninstallData Optional data to be decoded and used by the module to clear module data for the
/// account.
- /// @param preValidationHookUninstallData Optional data to be decoded and used by the plugin to clear account
+ /// @param preValidationHookUninstallData Optional data to be decoded and used by the module to clear account
/// data
- /// @param permissionHookUninstallData Optional data to be decoded and used by the plugin to clear account data
+ /// @param permissionHookUninstallData Optional data to be decoded and used by the module to clear account data
function uninstallValidation(
- PluginEntity validationFunction,
+ ModuleEntity validationFunction,
bytes calldata uninstallData,
bytes calldata preValidationHookUninstallData,
bytes calldata permissionHookUninstallData
) external;
- /// @notice Uninstall a plugin from the modular account.
- /// @param plugin The plugin to uninstall.
+ /// @notice Uninstall a module from the modular account.
+ /// @param module The module to uninstall.
/// @param config An optional, implementation-specific field that accounts may use to ensure consistency
/// guarantees.
- /// @param pluginUninstallData Optional data to be decoded and used by the plugin to clear plugin data for the
+ /// @param moduleUninstallData Optional data to be decoded and used by the module to clear module data for the
/// modular account.
- function uninstallPlugin(address plugin, bytes calldata config, bytes calldata pluginUninstallData) external;
+ function uninstallModule(address module, bytes calldata config, bytes calldata moduleUninstallData) external;
}
diff --git a/src/interfaces/IStandardExecutor.sol b/src/interfaces/IStandardExecutor.sol
index fbeb89c4..db9a7c19 100644
--- a/src/interfaces/IStandardExecutor.sol
+++ b/src/interfaces/IStandardExecutor.sol
@@ -12,7 +12,6 @@ struct Call {
interface IStandardExecutor {
/// @notice Standard execute method.
- /// @dev If the target is a plugin, the call SHOULD revert.
/// @param target The target address for the account to call.
/// @param value The value to send with the call.
/// @param data The calldata for the call.
@@ -20,7 +19,7 @@ interface IStandardExecutor {
function execute(address target, uint256 value, bytes calldata data) external payable returns (bytes memory);
/// @notice Standard executeBatch method.
- /// @dev If the target is a plugin, the call SHOULD revert. If any of the calls revert, the entire batch MUST
+ /// @dev If the target is a module, the call SHOULD revert. If any of the calls revert, the entire batch MUST
/// revert.
/// @param calls The array of calls.
/// @return An array containing the return data from the calls.
diff --git a/src/interfaces/IValidation.sol b/src/interfaces/IValidation.sol
index 471cd2c1..4f8fbbb8 100644
--- a/src/interfaces/IValidation.sol
+++ b/src/interfaces/IValidation.sol
@@ -3,9 +3,9 @@ pragma solidity ^0.8.25;
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
-import {IPlugin} from "./IPlugin.sol";
+import {IModule} from "./IModule.sol";
-interface IValidation is IPlugin {
+interface IValidation is IModule {
/// @notice Run the user operation validationFunction specified by the `entityId`.
/// @param entityId An identifier that routes the call to different internal implementations, should there
/// be more than one.
diff --git a/src/interfaces/IValidationHook.sol b/src/interfaces/IValidationHook.sol
index dd7e2500..1a8ee589 100644
--- a/src/interfaces/IValidationHook.sol
+++ b/src/interfaces/IValidationHook.sol
@@ -3,9 +3,9 @@ pragma solidity ^0.8.25;
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
-import {IPlugin} from "./IPlugin.sol";
+import {IModule} from "./IModule.sol";
-interface IValidationHook is IPlugin {
+interface IValidationHook is IModule {
/// @notice Run the pre user operation validation hook specified by the `entityId`.
/// @dev Pre user operation validation hooks MUST NOT return an authorizer value other than 0 or 1.
/// @param entityId An identifier that routes the call to different internal implementations, should there
diff --git a/src/plugins/BasePlugin.sol b/src/modules/BaseModule.sol
similarity index 83%
rename from src/plugins/BasePlugin.sol
rename to src/modules/BaseModule.sol
index 40dcd47b..b6d785c5 100644
--- a/src/plugins/BasePlugin.sol
+++ b/src/modules/BaseModule.sol
@@ -5,13 +5,13 @@ import {IAccountExecute} from "@eth-infinitism/account-abstraction/interfaces/IA
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
-import {IPlugin} from "../interfaces/IPlugin.sol";
+import {IModule} from "../interfaces/IModule.sol";
-/// @title Base contract for plugins
-/// @dev Implements ERC-165 to support IPlugin's interface, which is a requirement
-/// for plugin installation. This also ensures that plugin interactions cannot
+/// @title Base contract for modules
+/// @dev Implements ERC-165 to support IModule's interface, which is a requirement
+/// for module installation. This also ensures that module interactions cannot
/// happen via the standard execution funtions `execute` and `executeBatch`.
-abstract contract BasePlugin is ERC165, IPlugin {
+abstract contract BaseModule is ERC165, IModule {
error NotImplemented();
/// @dev Returns true if this contract implements the interface defined by
@@ -21,13 +21,13 @@ abstract contract BasePlugin is ERC165, IPlugin {
///
/// This function call must use less than 30 000 gas.
///
- /// Supporting the IPlugin interface is a requirement for plugin installation. This is also used
+ /// Supporting the IModule interface is a requirement for module installation. This is also used
/// by the modular account to prevent standard execution functions `execute` and `executeBatch` from
- /// making calls to plugins.
+ /// making calls to modules.
/// @param interfaceId The interface ID to check for support.
/// @return True if the contract supports `interfaceId`.
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
- return interfaceId == type(IPlugin).interfaceId || super.supportsInterface(interfaceId);
+ return interfaceId == type(IModule).interfaceId || super.supportsInterface(interfaceId);
}
function _getSelectorAndCalldata(bytes calldata data) internal pure returns (bytes4, bytes memory) {
diff --git a/src/plugins/ERC20TokenLimitPlugin.sol b/src/modules/ERC20TokenLimitModule.sol
similarity index 85%
rename from src/plugins/ERC20TokenLimitPlugin.sol
rename to src/modules/ERC20TokenLimitModule.sol
index 28ba4e04..85d90585 100644
--- a/src/plugins/ERC20TokenLimitPlugin.sol
+++ b/src/modules/ERC20TokenLimitModule.sol
@@ -13,20 +13,20 @@ 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 {PluginManifest, PluginMetadata} from "../interfaces/IPlugin.sol";
-import {IPlugin} from "../interfaces/IPlugin.sol";
+import {ModuleManifest, ModuleMetadata} from "../interfaces/IModule.sol";
+import {IModule} from "../interfaces/IModule.sol";
import {Call, IStandardExecutor} from "../interfaces/IStandardExecutor.sol";
-import {BasePlugin, IERC165} from "./BasePlugin.sol";
+import {BaseModule, IERC165} from "./BaseModule.sol";
-/// @title ERC20 Token Limit Plugin
+/// @title ERC20 Token Limit Module
/// @author ERC-6900 Authors
-/// @notice This plugin supports an ERC20 token spend limit. This should be combined with a contract whitelist
-/// plugin to make sure that token transfers not tracked by the plugin don't happen.
-/// Note: this plugin is opinionated on what selectors can be called for token contracts to guard against weird
+/// @notice This module supports an ERC20 token spend limit. This should be combined with a contract whitelist
+/// module to make sure that token transfers not tracked by the module don't happen.
+/// Note: this module is opinionated on what selectors can be called for token contracts to guard against weird
/// edge cases like DAI. You wouldn't be able to use uni v2 pairs directly as the pair contract is also the LP
/// token contract
-contract ERC20TokenLimitPlugin is BasePlugin, IExecutionHook {
+contract ERC20TokenLimitModule is BaseModule, IExecutionHook {
using UserOperationLib for PackedUserOperation;
using EnumerableSet for EnumerableSet.AddressSet;
using AssociatedLinkedListSetLib for AssociatedLinkedListSet;
@@ -36,7 +36,7 @@ contract ERC20TokenLimitPlugin is BasePlugin, IExecutionHook {
uint256[] limits;
}
- string internal constant _NAME = "ERC20 Token Limit Plugin";
+ string internal constant _NAME = "ERC20 Token Limit Module";
string internal constant _VERSION = "1.0.0";
string internal constant _AUTHOR = "ERC-6900 Authors";
@@ -77,7 +77,7 @@ contract ERC20TokenLimitPlugin is BasePlugin, IExecutionHook {
return "";
}
- /// @inheritdoc IPlugin
+ /// @inheritdoc IModule
function onInstall(bytes calldata data) external override {
(uint32 startEntityId, ERC20SpendLimit[] memory spendLimits) =
abi.decode(data, (uint32, ERC20SpendLimit[]));
@@ -94,7 +94,7 @@ contract ERC20TokenLimitPlugin is BasePlugin, IExecutionHook {
}
}
- /// @inheritdoc IPlugin
+ /// @inheritdoc IModule
function onUninstall(bytes calldata data) external override {
(address token, uint32 entityId) = abi.decode(data, (address, uint32));
delete limits[entityId][token][msg.sender];
@@ -114,13 +114,13 @@ contract ERC20TokenLimitPlugin is BasePlugin, IExecutionHook {
revert NotImplemented();
}
- /// @inheritdoc IPlugin
+ /// @inheritdoc IModule
// solhint-disable-next-line no-empty-blocks
- function pluginManifest() external pure override returns (PluginManifest memory) {}
+ function moduleManifest() external pure override returns (ModuleManifest memory) {}
- /// @inheritdoc IPlugin
- function pluginMetadata() external pure virtual override returns (PluginMetadata memory) {
- PluginMetadata memory metadata;
+ /// @inheritdoc IModule
+ function moduleMetadata() external pure virtual override returns (ModuleMetadata memory) {
+ ModuleMetadata memory metadata;
metadata.name = _NAME;
metadata.version = _VERSION;
metadata.author = _AUTHOR;
@@ -130,8 +130,8 @@ contract ERC20TokenLimitPlugin is BasePlugin, IExecutionHook {
return metadata;
}
- /// @inheritdoc BasePlugin
- function supportsInterface(bytes4 interfaceId) public view override(BasePlugin, IERC165) returns (bool) {
+ /// @inheritdoc BaseModule
+ function supportsInterface(bytes4 interfaceId) public view override(BaseModule, IERC165) returns (bool) {
return super.supportsInterface(interfaceId);
}
diff --git a/src/plugins/NativeTokenLimitPlugin.sol b/src/modules/NativeTokenLimitModule.sol
similarity index 89%
rename from src/plugins/NativeTokenLimitPlugin.sol
rename to src/modules/NativeTokenLimitModule.sol
index 37f4399e..f09994be 100644
--- a/src/plugins/NativeTokenLimitPlugin.sol
+++ b/src/modules/NativeTokenLimitModule.sol
@@ -6,20 +6,20 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {IExecutionHook} from "../interfaces/IExecutionHook.sol";
-import {PluginManifest, PluginMetadata} from "../interfaces/IPlugin.sol";
-import {IPlugin} from "../interfaces/IPlugin.sol";
+import {ModuleManifest, ModuleMetadata} from "../interfaces/IModule.sol";
+import {IModule} from "../interfaces/IModule.sol";
import {Call, IStandardExecutor} from "../interfaces/IStandardExecutor.sol";
import {IValidationHook} from "../interfaces/IValidationHook.sol";
-import {BasePlugin, IERC165} from "./BasePlugin.sol";
+import {BaseModule, IERC165} from "./BaseModule.sol";
-/// @title Native Token Limit Plugin
+/// @title Native Token Limit Module
/// @author ERC-6900 Authors
-/// @notice This plugin supports a single total native token spend limit.
+/// @notice This module supports a single total native token spend limit.
/// It tracks a total spend limit across UserOperation gas limits and native token transfers.
/// If a non whitelisted paymaster is used, UO gas would not cause the limit to decrease.
/// If a whitelisted paymaster is used, gas is still counted towards the limit
-contract NativeTokenLimitPlugin is BasePlugin, IExecutionHook, IValidationHook {
+contract NativeTokenLimitModule is BaseModule, IExecutionHook, IValidationHook {
using UserOperationLib for PackedUserOperation;
using EnumerableSet for EnumerableSet.Bytes32Set;
@@ -82,7 +82,7 @@ contract NativeTokenLimitPlugin is BasePlugin, IExecutionHook, IValidationHook {
return _checkAndDecrementLimit(entityId, data);
}
- /// @inheritdoc IPlugin
+ /// @inheritdoc IModule
function onInstall(bytes calldata data) external override {
(uint32 startEntityId, uint256[] memory spendLimits) = abi.decode(data, (uint32, uint256[]));
@@ -95,7 +95,7 @@ contract NativeTokenLimitPlugin is BasePlugin, IExecutionHook, IValidationHook {
}
}
- /// @inheritdoc IPlugin
+ /// @inheritdoc IModule
function onUninstall(bytes calldata data) external override {
// This is the highest entityId that's being used by the account
uint32 entityId = abi.decode(data, (uint32));
@@ -117,13 +117,13 @@ contract NativeTokenLimitPlugin is BasePlugin, IExecutionHook, IValidationHook {
override
{} // solhint-disable-line no-empty-blocks
- /// @inheritdoc IPlugin
+ /// @inheritdoc IModule
// solhint-disable-next-line no-empty-blocks
- function pluginManifest() external pure override returns (PluginManifest memory) {}
+ function moduleManifest() external pure override returns (ModuleManifest memory) {}
- /// @inheritdoc IPlugin
- function pluginMetadata() external pure virtual override returns (PluginMetadata memory) {
- PluginMetadata memory metadata;
+ /// @inheritdoc IModule
+ function moduleMetadata() external pure virtual override returns (ModuleMetadata memory) {
+ ModuleMetadata memory metadata;
metadata.name = _NAME;
metadata.version = _VERSION;
metadata.author = _AUTHOR;
@@ -138,8 +138,8 @@ contract NativeTokenLimitPlugin is BasePlugin, IExecutionHook, IValidationHook {
// ┃ EIP-165 ┃
// ┗━━━━━━━━━━━━━━━┛
- /// @inheritdoc BasePlugin
- function supportsInterface(bytes4 interfaceId) public view override(BasePlugin, IERC165) returns (bool) {
+ /// @inheritdoc BaseModule
+ function supportsInterface(bytes4 interfaceId) public view override(BaseModule, IERC165) returns (bool) {
return interfaceId == type(IExecutionHook).interfaceId || super.supportsInterface(interfaceId);
}
diff --git a/src/plugins/TokenReceiverPlugin.sol b/src/modules/TokenReceiverModule.sol
similarity index 78%
rename from src/plugins/TokenReceiverPlugin.sol
rename to src/modules/TokenReceiverModule.sol
index 95fbcfe0..b4cf839b 100644
--- a/src/plugins/TokenReceiverPlugin.sol
+++ b/src/modules/TokenReceiverModule.sol
@@ -4,15 +4,15 @@ pragma solidity ^0.8.25;
import {IERC1155Receiver} from "@openzeppelin/contracts/interfaces/IERC1155Receiver.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
-import {IPlugin, ManifestExecutionFunction, PluginManifest, PluginMetadata} from "../interfaces/IPlugin.sol";
-import {BasePlugin} from "./BasePlugin.sol";
+import {IModule, ManifestExecutionFunction, ModuleManifest, ModuleMetadata} from "../interfaces/IModule.sol";
+import {BaseModule} from "./BaseModule.sol";
-/// @title Token Receiver Plugin
+/// @title Token Receiver Module
/// @author ERC-6900 Authors
-/// @notice This plugin allows modular accounts to receive various types of tokens by implementing
+/// @notice This module allows modular accounts to receive various types of tokens by implementing
/// required token receiver interfaces.
-contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC1155Receiver {
- string internal constant _NAME = "Token Receiver Plugin";
+contract TokenReceiverModule is BaseModule, IERC721Receiver, IERC1155Receiver {
+ string internal constant _NAME = "Token Receiver Module";
string internal constant _VERSION = "1.0.0";
string internal constant _AUTHOR = "ERC-6900 Authors";
@@ -43,20 +43,20 @@ contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC1155Receiver {
}
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
- // ┃ Plugin interface functions ┃
+ // ┃ Module interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
- /// @inheritdoc IPlugin
+ /// @inheritdoc IModule
// solhint-disable-next-line no-empty-blocks
function onInstall(bytes calldata) external pure override {}
- /// @inheritdoc IPlugin
+ /// @inheritdoc IModule
// solhint-disable-next-line no-empty-blocks
function onUninstall(bytes calldata) external pure override {}
- /// @inheritdoc IPlugin
- function pluginManifest() external pure override returns (PluginManifest memory) {
- PluginManifest memory manifest;
+ /// @inheritdoc IModule
+ function moduleManifest() external pure override returns (ModuleManifest memory) {
+ ModuleManifest memory manifest;
manifest.executionFunctions = new ManifestExecutionFunction[](3);
manifest.executionFunctions[0] = ManifestExecutionFunction({
@@ -82,9 +82,9 @@ contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC1155Receiver {
return manifest;
}
- /// @inheritdoc IPlugin
- function pluginMetadata() external pure virtual override returns (PluginMetadata memory) {
- PluginMetadata memory metadata;
+ /// @inheritdoc IModule
+ function moduleMetadata() external pure virtual override returns (ModuleMetadata memory) {
+ ModuleMetadata memory metadata;
metadata.name = _NAME;
metadata.version = _VERSION;
metadata.author = _AUTHOR;
diff --git a/src/plugins/validation/ISingleSignerValidation.sol b/src/modules/validation/ISingleSignerValidation.sol
similarity index 100%
rename from src/plugins/validation/ISingleSignerValidation.sol
rename to src/modules/validation/ISingleSignerValidation.sol
diff --git a/src/plugins/validation/SingleSignerValidation.sol b/src/modules/validation/SingleSignerValidation.sol
similarity index 91%
rename from src/plugins/validation/SingleSignerValidation.sol
rename to src/modules/validation/SingleSignerValidation.sol
index 6699cb58..a384cda7 100644
--- a/src/plugins/validation/SingleSignerValidation.sol
+++ b/src/modules/validation/SingleSignerValidation.sol
@@ -6,9 +6,9 @@ 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 {IPlugin, PluginManifest, PluginMetadata} from "../../interfaces/IPlugin.sol";
+import {IModule, ModuleManifest, ModuleMetadata} from "../../interfaces/IModule.sol";
import {IValidation} from "../../interfaces/IValidation.sol";
-import {BasePlugin} from "../BasePlugin.sol";
+import {BaseModule} from "../BaseModule.sol";
import {ISingleSignerValidation} from "./ISingleSignerValidation.sol";
/// @title ECSDA Validation
@@ -24,7 +24,7 @@ import {ISingleSignerValidation} from "./ISingleSignerValidation.sol";
///
/// - This validation supports composition that other validation can relay on entities in this validation
/// to validate partially or fully.
-contract SingleSignerValidation is ISingleSignerValidation, BasePlugin {
+contract SingleSignerValidation is ISingleSignerValidation, BaseModule {
using ECDSA for bytes32;
using MessageHashUtils for bytes32;
@@ -46,13 +46,13 @@ contract SingleSignerValidation is ISingleSignerValidation, BasePlugin {
_transferSigner(entityId, newSigner);
}
- /// @inheritdoc IPlugin
+ /// @inheritdoc IModule
function onInstall(bytes calldata data) external override {
(uint32 entityId, address newSigner) = abi.decode(data, (uint32, address));
_transferSigner(entityId, newSigner);
}
- /// @inheritdoc IPlugin
+ /// @inheritdoc IModule
function onUninstall(bytes calldata data) external override {
// ToDo: what does it mean in the world of composable validation world to uninstall one type of validation
// We can either get rid of all SingleSigner signers. What about the nested ones?
@@ -115,18 +115,18 @@ contract SingleSignerValidation is ISingleSignerValidation, BasePlugin {
}
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
- // ┃ Plugin interface functions ┃
+ // ┃ Module interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
- /// @inheritdoc IPlugin
- function pluginManifest() external pure override returns (PluginManifest memory) {
- PluginManifest memory manifest;
+ /// @inheritdoc IModule
+ function moduleManifest() external pure override returns (ModuleManifest memory) {
+ ModuleManifest memory manifest;
return manifest;
}
- /// @inheritdoc IPlugin
- function pluginMetadata() external pure virtual override returns (PluginMetadata memory) {
- PluginMetadata memory metadata;
+ /// @inheritdoc IModule
+ function moduleMetadata() external pure virtual override returns (ModuleMetadata memory) {
+ ModuleMetadata memory metadata;
metadata.name = _NAME;
metadata.version = _VERSION;
metadata.author = _AUTHOR;
diff --git a/src/samples/permissionhooks/AllowlistPlugin.sol b/src/samples/permissionhooks/AllowlistModule.sol
similarity index 91%
rename from src/samples/permissionhooks/AllowlistPlugin.sol
rename to src/samples/permissionhooks/AllowlistModule.sol
index bb468ae8..b90fd6c2 100644
--- a/src/samples/permissionhooks/AllowlistPlugin.sol
+++ b/src/samples/permissionhooks/AllowlistModule.sol
@@ -3,13 +3,13 @@ pragma solidity ^0.8.25;
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
-import {PluginManifest, PluginMetadata} from "../../interfaces/IPlugin.sol";
+import {ModuleManifest, ModuleMetadata} from "../../interfaces/IModule.sol";
import {Call, IStandardExecutor} from "../../interfaces/IStandardExecutor.sol";
import {IValidationHook} from "../../interfaces/IValidationHook.sol";
-import {BasePlugin} from "../../plugins/BasePlugin.sol";
+import {BaseModule} from "../../modules/BaseModule.sol";
-contract AllowlistPlugin is IValidationHook, BasePlugin {
+contract AllowlistModule is IValidationHook, BaseModule {
enum EntityId {
PRE_VALIDATION_HOOK
}
@@ -95,9 +95,9 @@ contract AllowlistPlugin is IValidationHook, BasePlugin {
revert NotImplemented();
}
- function pluginMetadata() external pure override returns (PluginMetadata memory) {
- PluginMetadata memory metadata;
- metadata.name = "Allowlist Plugin";
+ function moduleMetadata() external pure override returns (ModuleMetadata memory) {
+ ModuleMetadata memory metadata;
+ metadata.name = "Allowlist Module";
metadata.version = "v0.0.1";
metadata.author = "ERC-6900 Working Group";
@@ -105,7 +105,7 @@ contract AllowlistPlugin is IValidationHook, BasePlugin {
}
// solhint-disable-next-line no-empty-blocks
- function pluginManifest() external pure override returns (PluginManifest memory) {}
+ function moduleManifest() external pure override returns (ModuleManifest memory) {}
function _checkAllowlistCalldata(bytes calldata callData) internal view {
if (bytes4(callData[:4]) == IStandardExecutor.execute.selector) {
diff --git a/standard/ERCs/ERC6900Diagrams.excalidraw b/standard/ERCs/ERC6900Diagrams.excalidraw
index aeef2f91..0b37d0b4 100644
--- a/standard/ERCs/ERC6900Diagrams.excalidraw
+++ b/standard/ERCs/ERC6900Diagrams.excalidraw
@@ -734,11 +734,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Native Function / (Plugin) Execution Function",
+ "text": "Native Function / (Module) Execution Function",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "FSqrJM9FRySWN10YDIFuH",
- "originalText": "Native Function / (Plugin) Execution Function",
+ "originalText": "Native Function / (Module) Execution Function",
"lineHeight": 1.15,
"baseline": 24
},
@@ -1274,11 +1274,11 @@
"locked": false,
"fontSize": 20,
"fontFamily": 3,
- "text": "\n executeFromPlugin",
+ "text": "\n executeFromModule",
"textAlign": "left",
"verticalAlign": "top",
"containerId": "V64RYeLbqd8REancwGi30",
- "originalText": "\n executeFromPlugin",
+ "originalText": "\n executeFromModule",
"lineHeight": 1.2,
"baseline": 44
},
@@ -1513,11 +1513,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Permitted Plugin Execution Function",
+ "text": "Permitted Module Execution Function",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "3HJCra6w4bVr0zNxhwPIg",
- "originalText": "Permitted Plugin Execution Function",
+ "originalText": "Permitted Module Execution Function",
"lineHeight": 1.15,
"baseline": 24
},
@@ -1681,11 +1681,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Plugins",
+ "text": "Modules",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "owBW-NHsmLmREuOjDCv06",
- "originalText": "Plugins",
+ "originalText": "Modules",
"lineHeight": 1.15,
"baseline": 24
},
@@ -1720,11 +1720,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Plugin Permission Check",
+ "text": "Module Permission Check",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "wBFdRyQG4wrtwbKkyNsa-",
- "originalText": "Plugin Permission Check",
+ "originalText": "Module Permission Check",
"lineHeight": 1.15,
"baseline": 24
},
@@ -1796,11 +1796,11 @@
"locked": false,
"fontSize": 20,
"fontFamily": 3,
- "text": "\n executeFromPluginExternal",
+ "text": "\n executeFromModuleExternal",
"textAlign": "left",
"verticalAlign": "top",
"containerId": "dgC4KV1DfhkMlJgqA9-10",
- "originalText": "\n executeFromPluginExternal",
+ "originalText": "\n executeFromModuleExternal",
"lineHeight": 1.2,
"baseline": 44
},
@@ -1876,11 +1876,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "(Plugin) Execution Function",
+ "text": "(Module) Execution Function",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "j7kk61t1I6enSnhuaVZHW",
- "originalText": "(Plugin) Execution Function",
+ "originalText": "(Module) Execution Function",
"lineHeight": 1.15,
"baseline": 24
},
@@ -1977,11 +1977,11 @@
"locked": false,
"fontSize": 20,
"fontFamily": 2,
- "text": "1 calls plugin ",
+ "text": "1 calls module ",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "71sd7fDDpQnB-DSlvQqP_",
- "originalText": "1 calls plugin ",
+ "originalText": "1 calls module ",
"lineHeight": 1.15,
"baseline": 19
},
@@ -2133,11 +2133,11 @@
"locked": false,
"fontSize": 20,
"fontFamily": 2,
- "text": "2.2 calls external contracts \nthrough\n executeFromPluginExternal",
+ "text": "2.2 calls external contracts \nthrough\n executeFromModuleExternal",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "W_TcvUOGvsHsXmj31qq0O",
- "originalText": "2.2 calls external contracts through\n executeFromPluginExternal",
+ "originalText": "2.2 calls external contracts through\n executeFromModuleExternal",
"lineHeight": 1.15,
"baseline": 65
},
@@ -2259,11 +2259,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Plugin Permission Check",
+ "text": "Module Permission Check",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "K34YWjpoqir9H5g1FHSe1",
- "originalText": "Plugin Permission Check",
+ "originalText": "Module Permission Check",
"lineHeight": 1.15,
"baseline": 24
},
@@ -2517,11 +2517,11 @@
"locked": false,
"fontSize": 36,
"fontFamily": 2,
- "text": "Plugin Execution Flow",
+ "text": "Module Execution Flow",
"textAlign": "left",
"verticalAlign": "top",
"containerId": null,
- "originalText": "Plugin Execution Flow",
+ "originalText": "Module Execution Flow",
"lineHeight": 1.15,
"baseline": 33
},
@@ -2555,11 +2555,11 @@
"locked": false,
"fontSize": 20,
"fontFamily": 2,
- "text": "2.1 calls other installed \nplugin through\n executeFromPlugin",
+ "text": "2.1 calls other installed \nmodule through\n executeFromModule",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "fA1p68GcpvI-X1krxkJ29",
- "originalText": "2.1 calls other installed plugin through\n executeFromPlugin",
+ "originalText": "2.1 calls other installed module through\n executeFromModule",
"lineHeight": 1.15,
"baseline": 65
},
@@ -2643,11 +2643,11 @@
"locked": false,
"fontSize": 25.68325562404122,
"fontFamily": 2,
- "text": "Pre executeFromPluginExternal Hook(s)",
+ "text": "Pre executeFromModuleExternal Hook(s)",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "emDobd4D91UDt1c8oZ0Iu",
- "originalText": "Pre executeFromPluginExternal Hook(s)",
+ "originalText": "Pre executeFromModuleExternal Hook(s)",
"lineHeight": 1.15,
"baseline": 24
},
@@ -2727,11 +2727,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Post executeFromPluginExternal Hook(s)",
+ "text": "Post executeFromModuleExternal Hook(s)",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "Hx9p9aaBWogvW3Z9zujgf",
- "originalText": "Post executeFromPluginExternal Hook(s)",
+ "originalText": "Post executeFromModuleExternal Hook(s)",
"lineHeight": 1.15,
"baseline": 24
},
@@ -3325,11 +3325,11 @@
"locked": false,
"fontSize": 20,
"fontFamily": 3,
- "text": "\n executeFromPlugin/executeFromPluginExternal",
+ "text": "\n executeFromModule/executeFromModuleExternal",
"textAlign": "left",
"verticalAlign": "top",
"containerId": "2JLeKLisTh-Vc4SuDVk5b",
- "originalText": "\n executeFromPlugin/executeFromPluginExternal",
+ "originalText": "\n executeFromModule/executeFromModuleExternal",
"lineHeight": 1.2,
"baseline": 44
},
@@ -3715,11 +3715,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Pre Plugin Execution Hook(s)",
+ "text": "Pre Module Execution Hook(s)",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "uJ0egPTKleB3Aut1HFd2K",
- "originalText": "Pre Plugin Execution Hook(s)",
+ "originalText": "Pre Module Execution Hook(s)",
"lineHeight": 1.15,
"baseline": 24
},
@@ -3793,11 +3793,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Post Plugin Execution Hook(s)",
+ "text": "Post Module Execution Hook(s)",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "7Klv-GWoFcKLlBdaExqzT",
- "originalText": "Post Plugin Execution Hook(s)",
+ "originalText": "Post Module Execution Hook(s)",
"lineHeight": 1.15,
"baseline": 24
},
@@ -4183,11 +4183,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Plugins",
+ "text": "Modules",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "qLT39tSOFDyxvMCmG5W1h",
- "originalText": "Plugins",
+ "originalText": "Modules",
"lineHeight": 1.15,
"baseline": 24
},
@@ -4781,11 +4781,11 @@
"locked": false,
"fontSize": 20,
"fontFamily": 3,
- "text": "\n executeFromPlugin",
+ "text": "\n executeFromModule",
"textAlign": "left",
"verticalAlign": "top",
"containerId": "h4-dGWuBPeBT6vEznfNUa",
- "originalText": "\n executeFromPlugin",
+ "originalText": "\n executeFromModule",
"lineHeight": 1.2,
"baseline": 44
},
@@ -5171,11 +5171,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Pre Plugin Execution Hook(s)",
+ "text": "Pre Module Execution Hook(s)",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "2tiy_HH9LYxsFnORyo1QN",
- "originalText": "Pre Plugin Execution Hook(s)",
+ "originalText": "Pre Module Execution Hook(s)",
"lineHeight": 1.15,
"baseline": 24
},
@@ -5249,11 +5249,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Post Plugin Execution Hook(s)",
+ "text": "Post Module Execution Hook(s)",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "T7fYn-6m0AnnYUsZ7Vu-6",
- "originalText": "Post Plugin Execution Hook(s)",
+ "originalText": "Post Module Execution Hook(s)",
"lineHeight": 1.15,
"baseline": 24
},
@@ -5323,11 +5323,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Account-Native Function / Plugin Execution Function",
+ "text": "Account-Native Function / Module Execution Function",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "Sj8y2LMf6pefmYIQqny_R",
- "originalText": "Account-Native Function / Plugin Execution Function",
+ "originalText": "Account-Native Function / Module Execution Function",
"lineHeight": 1.15,
"baseline": 24
},
@@ -5639,11 +5639,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Plugins",
+ "text": "Modules",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "UIOBlFmO5FdF3hqajkL-P",
- "originalText": "Plugins",
+ "originalText": "Modules",
"lineHeight": 1.15,
"baseline": 24
},
@@ -6517,11 +6517,11 @@
"locked": false,
"fontSize": 20,
"fontFamily": 3,
- "text": "\n executeFromPlugin",
+ "text": "\n executeFromModule",
"textAlign": "left",
"verticalAlign": "top",
"containerId": "ejh1h99xkb4w1wuTImtiK",
- "originalText": "\n executeFromPlugin",
+ "originalText": "\n executeFromModule",
"lineHeight": 1.2,
"baseline": 44
},
@@ -7207,11 +7207,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Plugins",
+ "text": "Modules",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "9PEiLoAhsOByWsJZ9OKS9",
- "originalText": "Plugins",
+ "originalText": "Modules",
"lineHeight": 1.15,
"baseline": 24
},
@@ -7339,11 +7339,11 @@
"locked": false,
"fontSize": 25.664343526865803,
"fontFamily": 2,
- "text": "Plugin Permission Check",
+ "text": "Module Permission Check",
"textAlign": "center",
"verticalAlign": "middle",
"containerId": "S3jaS7lY7njUd4iFC2CvV",
- "originalText": "Plugin Permission Check",
+ "originalText": "Module Permission Check",
"lineHeight": 1.15,
"baseline": 24
}
diff --git a/standard/ERCs/erc-6900.md b/standard/ERCs/erc-6900.md
index fed6a625..d5d15744 100644
--- a/standard/ERCs/erc-6900.md
+++ b/standard/ERCs/erc-6900.md
@@ -1,6 +1,6 @@
---
eip: 6900
-title: Modular Smart Contract Accounts and Plugins
+title: Modular Smart Contract Accounts and Modules
description: Interfaces for composable contract accounts optionally supporting upgradability and introspection
author: Adam Egyed (@adamegyed), Fangting Liu (@trinity-0111), Jay Paik (@jaypaik), Yoav Weiss (@yoavw)
discussions-to: https://ethereum-magicians.org/t/eip-modular-smart-contract-accounts-and-plugins/13885
@@ -13,7 +13,7 @@ requires: 165, 4337
## Abstract
-This proposal standardizes smart contract accounts and account plugins, which are smart contract interfaces that allow for composable logic within smart contract accounts. This proposal is compliant with [ERC-4337](./eip-4337.md), and takes inspiration from [ERC-2535](./eip-2535.md) when defining interfaces for updating and querying modular function implementations.
+This proposal standardizes smart contract accounts and account modules, which are smart contract interfaces that allow for composable logic within smart contract accounts. This proposal is compliant with [ERC-4337](./eip-4337.md), and takes inspiration from [ERC-2535](./eip-2535.md) when defining interfaces for updating and querying modular function implementations.
This modular approach splits account functionality into three categories, implements them in external contracts, and defines an expected execution flow from accounts.
@@ -21,24 +21,24 @@ This modular approach splits account functionality into three categories, implem
One of the goals that ERC-4337 accomplishes is abstracting the logic for execution and validation to each smart contract account.
-Many new features of accounts can be built by customizing the logic that goes into the validation and execution steps. Examples of such features include session keys, subscriptions, spending limits, and role-based access control. Currently, some of these features are implemented natively by specific smart contract accounts, and others are able to be implemented by plugin systems. Examples of proprietary plugin systems include Safe modules and ZeroDev plugins.
+Many new features of accounts can be built by customizing the logic that goes into the validation and execution steps. Examples of such features include session keys, subscriptions, spending limits, and role-based access control. Currently, some of these features are implemented natively by specific smart contract accounts, and others are able to be implemented by module systems. Examples of proprietary module systems include Safe modules and ZeroDev modules.
-However, managing multiple account instances provides a worse user experience, fragmenting accounts across supported features and security configurations. Additionally, it requires plugin developers to choose which platforms to support, causing either platform lock-in or duplicated development effort.
+However, managing multiple account instances provides a worse user experience, fragmenting accounts across supported features and security configurations. Additionally, it requires module developers to choose which platforms to support, causing either platform lock-in or duplicated development effort.
-We propose a standard that coordinates the implementation work between plugin developers and wallet developers. This standard defines a modular smart contract account capable of supporting all standard-conformant plugins. This allows users to have greater portability of their data, and for plugin developers to not have to choose specific account implementations to support.
+We propose a standard that coordinates the implementation work between module developers and wallet developers. This standard defines a modular smart contract account capable of supporting all standard-conformant modules. This allows users to have greater portability of their data, and for module developers to not have to choose specific account implementations to support.
-
+
We take inspiration from ERC-2535's diamond pattern for routing execution based on function selectors, and create a similarly composable account. However, the standard does not require the multi-facet proxy pattern.
-These plugins can contain execution logic, validation schemes, and hooks. Validation schemes define the circumstances under which the smart contract account will approve actions taken on its behalf, while hooks allow for pre- and post-execution controls.
+These modules can contain execution logic, validation schemes, and hooks. Validation schemes define the circumstances under which the smart contract account will approve actions taken on its behalf, while hooks allow for pre- and post-execution controls.
-Accounts adopting this standard will support modular, upgradable execution and validation logic. Defining this as a standard for smart contract accounts will make plugins easier to develop securely and will allow for greater interoperability.
+Accounts adopting this standard will support modular, upgradable execution and validation logic. Defining this as a standard for smart contract accounts will make modules easier to develop securely and will allow for greater interoperability.
Goals:
- Provide standards for how validation, execution, and hook functions for smart contract accounts should be written.
-- Provide standards for how compliant accounts should add, update, remove, and inspect plugins.
+- Provide standards for how compliant accounts should add, update, remove, and inspect modules.
## Specification
@@ -55,16 +55,16 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S
- **User Operation Validation** functions handle calls to `validateUserOp` and check the validity of an ERC-4337 user operation.
- **Runtime Validation** functions run before an execution function when not called via a user operation, and enforce checks. Common checks include allowing execution only by an owner.
- An **execution function** is a smart contract function that defines the main execution step of a function for a modular account.
-- The **standard execute** functions are two specific execute functions that are implemented natively by the modular account, and not on a plugin. These allow for open-ended execution.
+- The **standard execute** functions are two specific execute functions that are implemented natively by the modular account, and not on a module. These allow for open-ended execution.
- A **hook** is a smart contract function executed before or after another function, with the ability to modify state or cause the entire call to revert. There are four types of hooks:
- **Pre User Operation Validation Hook** functions run before user operation validation functions. These can enforce permissions on what actions a validation function may perform via user operations.
- **Pre Runtime Validation Hook** functions run before runtime validation functions. These can enforce permissions on what actions a validation function may perform via direct calls.
- **Pre Execution Hook** functions run before an execution function. They may optionally return data to be consumed by their related post execution hook functions.
- **Post Execution Hook** functions run after an execution function. They may optionally take returned data from their related pre execution hook functions.
- An **associated function** refers to either a validation function or a hook.
-- A **native function** refers to a function implemented natively by the modular account, as opposed to a function added by a plugin.
-- A **plugin** is a deployed smart contract that hosts any amount of the above three kinds of modular functions: execution functions, validation functions, or hooks.
-- A plugin **manifest** is responsible for describing the execution functions, validation functions, and hooks that will be configured on the MSCA during installation, as well as the plugin’s metadata, dependency requirements, and permissions.
+- A **native function** refers to a function implemented natively by the modular account, as opposed to a function added by a module.
+- A **module** is a deployed smart contract that hosts any amount of the above three kinds of modular functions: execution functions, validation functions, or hooks.
+- A module **manifest** is responsible for describing the execution functions, validation functions, and hooks that will be configured on the MSCA during installation, as well as the module’s metadata, dependency requirements, and permissions.
### Overview
@@ -74,12 +74,12 @@ A call to the smart contract account can be broken down into the steps as shown

-The following diagram shows permitted plugin execution flows. During a plugin's execution step from the above diagram, the plugin may perform a "Plugin Execution Function", using either `executeFromPlugin` or `executeFromPluginExternal`. These can be used by plugins to execute using the account's context.
+The following diagram shows permitted module execution flows. During a module's execution step from the above diagram, the module may perform a "Module Execution Function", using either `executeFromModule` or `executeFromModuleExternal`. These can be used by modules to execute using the account's context.
-- `executeFromPlugin` handles calls to other installed plugin's execution function on the modular account.
-- `executeFromPluginExternal` handles calls to external addresses.
+- `executeFromModule` handles calls to other installed module's execution function on the modular account.
+- `executeFromModuleExternal` handles calls to external addresses.
-
+
Each step is modular, supporting different implementations for each execution function, and composable, supporting multiple steps through hooks. Combined, these allow for open-ended programmable accounts.
@@ -88,52 +88,52 @@ Each step is modular, supporting different implementations for each execution fu
**Modular Smart Contract Accounts** **MUST** implement
- `IAccount.sol` from [ERC-4337](./eip-4337.md).
-- `IPluginManager.sol` to support installing and uninstalling plugins.
-- `IStandardExecutor.sol` to support open-ended execution. **Calls to plugins through this SHOULD revert.**
-- `IPluginExecutor.sol` to support execution from plugins. **Calls to plugins through `executeFromPluginExternal` SHOULD revert.**
+- `IModuleManager.sol` to support installing and uninstalling modules.
+- `IStandardExecutor.sol` to support open-ended execution. **Calls to modules through this SHOULD revert.**
+- `IModuleExecutor.sol` to support execution from modules. **Calls to modules through `executeFromModuleExternal` SHOULD revert.**
**Modular Smart Contract Accounts** **MAY** implement
-- `IAccountLoupe.sol` to support visibility in plugin configuration on-chain.
+- `IAccountLoupe.sol` to support visibility in module configuration on-chain.
-**Plugins** **MUST** implement
+**Modules** **MUST** implement
-- `IPlugin.sol` described below and implement [ERC-165](./eip-165.md) for `IPlugin`.
+- `IModule.sol` described below and implement [ERC-165](./eip-165.md) for `IModule`.
-#### `IPluginManager.sol`
+#### `IModuleManager.sol`
-Plugin manager interface. Modular Smart Contract Accounts **MUST** implement this interface to support installing and uninstalling plugins.
+Module manager interface. Modular Smart Contract Accounts **MUST** implement this interface to support installing and uninstalling modules.
```solidity
// Treats the first 20 bytes as an address, and the last byte as a function identifier.
-type PluginEntity is bytes21;
+type ModuleEntity is bytes21;
-interface IPluginManager {
- event PluginInstalled(address indexed plugin, bytes32 manifestHash, PluginEntity[] dependencies);
+interface IModuleManager {
+ event ModuleInstalled(address indexed module, bytes32 manifestHash, ModuleEntity[] dependencies);
- event PluginUninstalled(address indexed plugin, bool indexed onUninstallSucceeded);
+ event ModuleUninstalled(address indexed module, bool indexed onUninstallSucceeded);
- /// @notice Install a plugin to the modular account.
- /// @param plugin The plugin to install.
- /// @param manifestHash The hash of the plugin manifest.
- /// @param pluginInstallData Optional data to be decoded and used by the plugin to setup initial plugin data
+ /// @notice Install a module to the modular account.
+ /// @param module The module to install.
+ /// @param manifestHash The hash of the module manifest.
+ /// @param moduleInstallData Optional data to be decoded and used by the module to setup initial module data
/// for the modular account.
- /// @param dependencies The dependencies of the plugin, as described in the manifest. Each PluginEntity
- /// MUST be composed of an installed plugin's address and a function ID of its validation function.
- function installPlugin(
- address plugin,
+ /// @param dependencies The dependencies of the module, as described in the manifest. Each ModuleEntity
+ /// MUST be composed of an installed module's address and a function ID of its validation function.
+ function installModule(
+ address module,
bytes32 manifestHash,
- bytes calldata pluginInstallData,
- PluginEntity[] calldata dependencies
+ bytes calldata moduleInstallData,
+ ModuleEntity[] calldata dependencies
) external;
- /// @notice Uninstall a plugin from the modular account.
- /// @param plugin The plugin to uninstall.
+ /// @notice Uninstall a module from the modular account.
+ /// @param module The module to uninstall.
/// @param config An optional, implementation-specific field that accounts may use to ensure consistency
/// guarantees.
- /// @param pluginUninstallData Optional data to be decoded and used by the plugin to clear plugin data for the
+ /// @param moduleUninstallData Optional data to be decoded and used by the module to clear module data for the
/// modular account.
- function uninstallPlugin(address plugin, bytes calldata config, bytes calldata pluginUninstallData) external;
+ function uninstallModule(address module, bytes calldata config, bytes calldata moduleUninstallData) external;
}
```
@@ -142,9 +142,9 @@ interface IPluginManager {
Standard execute interface. Modular Smart Contract Accounts **MUST** implement this interface to support open-ended execution.
-Standard execute functions SHOULD check whether the call's target implements the `IPlugin` interface via ERC-165.
+Standard execute functions SHOULD check whether the call's target implements the `IModule` interface via ERC-165.
-**If the target is a plugin, the call SHOULD revert.** This prevents accidental misconfiguration or misuse of plugins (both installed and uninstalled).
+**If the target is a module, the call SHOULD revert.** This prevents accidental misconfiguration or misuse of modules (both installed and uninstalled).
```solidity
struct Call {
@@ -158,7 +158,7 @@ struct Call {
interface IStandardExecutor {
/// @notice Standard execute method.
- /// @dev If the target is a plugin, the call SHOULD revert.
+ /// @dev If the target is a module, the call SHOULD revert.
/// @param target The target address for account to call.
/// @param value The value to send with the call.
/// @param data The calldata for the call.
@@ -166,7 +166,7 @@ interface IStandardExecutor {
function execute(address target, uint256 value, bytes calldata data) external payable returns (bytes memory);
/// @notice Standard executeBatch method.
- /// @dev If the target is a plugin, the call SHOULD revert. If any of the calls revert, the entire batch MUST
+ /// @dev If the target is a module, the call SHOULD revert. If any of the calls revert, the entire batch MUST
/// revert.
/// @param calls The array of calls.
/// @return An array containing the return data from the calls.
@@ -174,32 +174,32 @@ interface IStandardExecutor {
}
```
-#### `IPluginExecutor.sol`
+#### `IModuleExecutor.sol`
-Execution interface for calls made from plugins. Modular Smart Contract Accounts **MUST** implement this interface to support execution from plugins.
+Execution interface for calls made from modules. Modular Smart Contract Accounts **MUST** implement this interface to support execution from modules.
-The `executeFromPluginExternal` function SHOULD check whether the call's target implements the `IPlugin` interface via ERC-165.
+The `executeFromModuleExternal` function SHOULD check whether the call's target implements the `IModule` interface via ERC-165.
-**If the target of `executeFromPluginExternal` function is a plugin, the call SHOULD revert.**
+**If the target of `executeFromModuleExternal` function is a module, the call SHOULD revert.**
-This prevents accidental misconfiguration or misuse of plugins (both installed and uninstalled). Installed plugins MAY interact with other installed plugins via the `executeFromPlugin` function.
+This prevents accidental misconfiguration or misuse of modules (both installed and uninstalled). Installed modules MAY interact with other installed modules via the `executeFromModule` function.
```solidity
-interface IPluginExecutor {
- /// @notice Execute a call from a plugin through the account.
- /// @dev Permissions must be granted to the calling plugin for the call to go through.
+interface IModuleExecutor {
+ /// @notice Execute a call from a module through the account.
+ /// @dev Permissions must be granted to the calling module for the call to go through.
/// @param data The calldata to send to the account.
/// @return The return data from the call.
- function executeFromPlugin(bytes calldata data) external payable returns (bytes memory);
+ function executeFromModule(bytes calldata data) external payable returns (bytes memory);
- /// @notice Execute a call from a plugin to a non-plugin address.
- /// @dev If the target is a plugin, the call SHOULD revert. Permissions must be granted to the calling plugin
+ /// @notice Execute a call from a module to a non-module address.
+ /// @dev If the target is a module, the call SHOULD revert. Permissions must be granted to the calling module
/// for the call to go through.
/// @param target The address to be called.
/// @param value The value to send with the call.
/// @param data The calldata to send to the target.
/// @return The return data from the call.
- function executeFromPluginExternal(address target, uint256 value, bytes calldata data)
+ function executeFromModuleExternal(address target, uint256 value, bytes calldata data)
external
payable
returns (bytes memory);
@@ -208,26 +208,26 @@ interface IPluginExecutor {
#### `IAccountLoupe.sol`
-Plugin inspection interface. Modular Smart Contract Accounts **MAY** implement this interface to support visibility in plugin configuration on-chain.
+Module inspection interface. Modular Smart Contract Accounts **MAY** implement this interface to support visibility in module configuration on-chain.
```solidity
interface IAccountLoupe {
/// @notice Config for an execution function, given a selector.
struct ExecutionFunctionConfig {
- address plugin;
- PluginEntity validationFunction;
+ address module;
+ ModuleEntity validationFunction;
}
/// @notice Pre and post hooks for a given selector.
/// @dev It's possible for one of either `preExecHook` or `postExecHook` to be empty.
struct ExecutionHooks {
- PluginEntity hookFunction;
+ ModuleEntity hookFunction;
bool isPreHook;
bool isPostHook;
}
- /// @notice Get the validation functions and plugin address for a selector.
- /// @dev If the selector is a native function, the plugin address will be the address of the account.
+ /// @notice Get the validation functions and module address for a selector.
+ /// @dev If the selector is a native function, the module address will be the address of the account.
/// @param selector The selector to get the configuration for.
/// @return The configuration for this selector.
function getExecutionFunctionConfig(bytes4 selector) external view returns (ExecutionFunctionConfig memory);
@@ -243,28 +243,28 @@ interface IAccountLoupe {
function getPreValidationHooks(bytes4 selector)
external
view
- returns (PluginEntity[] memory preValidationHooks);
+ returns (ModuleEntity[] memory preValidationHooks);
- /// @notice Get an array of all installed plugins.
- /// @return The addresses of all installed plugins.
- function getInstalledPlugins() external view returns (address[] memory);
+ /// @notice Get an array of all installed modules.
+ /// @return The addresses of all installed modules.
+ function getInstalledModules() external view returns (address[] memory);
}
```
-#### `IPlugin.sol`
+#### `IModule.sol`
-Plugin interface. Plugins **MUST** implement this interface to support plugin management and interactions with MSCAs.
+Module interface. Modules **MUST** implement this interface to support module management and interactions with MSCAs.
```solidity
-interface IPlugin {
- /// @notice Initialize plugin data for the modular account.
- /// @dev Called by the modular account during `installPlugin`.
- /// @param data Optional bytes array to be decoded and used by the plugin to setup initial plugin data for the modular account.
+interface IModule {
+ /// @notice Initialize module data for the modular account.
+ /// @dev Called by the modular account during `installModule`.
+ /// @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 plugin data for the modular account.
- /// @dev Called by the modular account during `uninstallPlugin`.
- /// @param data Optional bytes array to be decoded and used by the plugin to clear plugin data for the modular account.
+ /// @notice Clear module data for the modular account.
+ /// @dev Called by the modular account during `uninstallModule`.
+ /// @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 Run the pre user operation validation hook specified by the `entityId`.
@@ -318,29 +318,29 @@ interface IPlugin {
/// @param preExecHookData The context returned by its associated pre execution hook.
function postExecutionHook(uint32 entityId, bytes calldata preExecHookData) external;
- /// @notice Describe the contents and intended configuration of the plugin.
+ /// @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 plugin.
- function pluginManifest() external pure returns (PluginManifest memory);
+ /// @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 plugin.
+ /// @notice Describe the metadata of the module.
/// @dev This metadata MUST stay constant over time.
- /// @return A metadata struct describing the plugin.
- function pluginMetadata() external pure returns (PluginMetadata memory);
+ /// @return A metadata struct describing the module.
+ function moduleMetadata() external pure returns (ModuleMetadata memory);
}
```
-### Plugin manifest
+### Module manifest
-The plugin manifest is responsible for describing the execution functions, validation functions, and hooks that will be configured on the MSCA during installation, as well as the plugin's metadata, dependencies, and permissions.
+The module manifest is responsible for describing the execution functions, validation functions, and hooks that will be configured on the MSCA during installation, as well as the module's metadata, dependencies, and permissions.
```solidity
enum ManifestAssociatedFunctionType {
// Function is not defined.
NONE,
- // Function belongs to this plugin.
+ // Function belongs to this module.
SELF,
- // Function belongs to an external plugin provided as a dependency during plugin installation. Plugins MAY depend
+ // Function belongs to an external module provided as a dependency during module installation. Modules MAY depend
// on external validation functions. It MUST NOT depend on external hooks, or installation will fail.
DEPENDENCY,
// Resolves to a magic value to always bypass runtime validation for a given function.
@@ -355,8 +355,8 @@ enum ManifestAssociatedFunctionType {
PRE_HOOK_ALWAYS_DENY
}
-/// @dev For functions of type `ManifestAssociatedFunctionType.DEPENDENCY`, the MSCA MUST find the plugin address
-/// of the function at `dependencies[dependencyIndex]` during the call to `installPlugin(config)`.
+/// @dev For functions of type `ManifestAssociatedFunctionType.DEPENDENCY`, the MSCA MUST find the module address
+/// of the function at `dependencies[dependencyIndex]` during the call to `installModule(config)`.
struct ManifestFunction {
ManifestAssociatedFunctionType functionType;
uint8 entityId;
@@ -387,37 +387,37 @@ struct SelectorPermission {
string permissionDescription;
}
-/// @dev A struct holding fields to describe the plugin in a purely view context. Intended for front end clients.
-struct PluginMetadata {
- // A human-readable name of the plugin.
+/// @dev A struct holding fields to describe the module in a purely view context. Intended for front end clients.
+struct ModuleMetadata {
+ // A human-readable name of the module.
string name;
- // The version of the plugin, following the semantic versioning scheme.
+ // The version of the module, following the semantic versioning scheme.
string version;
// The author field SHOULD be a username representing the identity of the user or organization
- // that created this plugin.
+ // that created this module.
string author;
// String descriptions of the relative sensitivity of specific functions. The selectors MUST be selectors for
- // functions implemented by this plugin.
+ // functions implemented by this module.
SelectorPermission[] permissionDescriptors;
}
-/// @dev A struct describing how the plugin should be installed on a modular account.
-struct PluginManifest {
+/// @dev A struct describing how the module should be installed on a modular account.
+struct ModuleManifest {
// List of ERC-165 interface IDs to add to account to support introspection checks. This MUST NOT include
- // IPlugin's interface ID.
+ // IModule's interface ID.
bytes4[] interfaceIds;
- // If this plugin depends on other plugins' validation functions, the interface IDs of those plugins MUST be
+ // If this module depends on other modules' validation functions, the interface IDs of those modules MUST be
// provided here, with its position in the array matching the `dependencyIndex` members of `ManifestFunction`
// structs used in the manifest.
bytes4[] dependencyInterfaceIds;
- // Execution functions defined in this plugin to be installed on the MSCA.
+ // Execution functions defined in this module to be installed on the MSCA.
bytes4[] executionFunctions;
- // Plugin execution functions already installed on the MSCA that this plugin will be able to call.
+ // Module execution functions already installed on the MSCA that this module will be able to call.
bytes4[] permittedExecutionSelectors;
- // Boolean to indicate whether the plugin can call any external address.
+ // Boolean to indicate whether the module can call any external address.
bool permitAnyExternalAddress;
- // Boolean to indicate whether the plugin needs access to spend native tokens of the account. If false, the
- // plugin MUST still be able to spend up to the balance that it sends to the account in the same call.
+ // Boolean to indicate whether the module needs access to spend native tokens of the account. If false, the
+ // module MUST still be able to spend up to the balance that it sends to the account in the same call.
bool canSpendNativeToken;
ManifestExternalCallPermission[] permittedExternalCalls;
ManifestAssociatedFunction[] validationFunctions;
@@ -429,34 +429,34 @@ struct PluginManifest {
### Expected behavior
-#### Responsibilties of `StandardExecutor` and `PluginExecutor`
+#### Responsibilties of `StandardExecutor` and `ModuleExecutor`
`StandardExecutor` functions are used for open-ended calls to external addresses.
-`PluginExecutor` functions are specifically used by plugins to request the account to execute with account's context. Explicit permissions are required for plugins to use `PluginExecutor`.
+`ModuleExecutor` functions are specifically used by modules to request the account to execute with account's context. Explicit permissions are required for modules to use `ModuleExecutor`.
The following behavior MUST be followed:
-- `StandardExecutor` can NOT call plugin execution functions and/or `PluginExecutor`. This is guaranteed by checking whether the call's target implements the `IPlugin` interface via ERC-165 as required.
-- `StandardExecutor` can NOT be called by plugin execution functions and/or `PluginExecutor`.
-- Plugin execution functions MUST NOT request access to `StandardExecutor`, they MAY request access to `PluginExecutor`.
+- `StandardExecutor` can NOT call module execution functions and/or `ModuleExecutor`. This is guaranteed by checking whether the call's target implements the `IModule` interface via ERC-165 as required.
+- `StandardExecutor` can NOT be called by module execution functions and/or `ModuleExecutor`.
+- Module execution functions MUST NOT request access to `StandardExecutor`, they MAY request access to `ModuleExecutor`.
-#### Calls to `installPlugin`
+#### Calls to `installModule`
-The function `installPlugin` accepts 3 parameters: the address of the plugin to install, the Keccak-256 hash of the plugin's manifest, ABI-encoded data to pass to the plugin's `onInstall` callback.
+The function `installModule` accepts 3 parameters: the address of the module to install, the Keccak-256 hash of the module's manifest, ABI-encoded data to pass to the module's `onInstall` callback.
-The function MUST retrieve the plugin's manifest by calling `pluginManifest()` using `staticcall`.
+The function MUST retrieve the module's manifest by calling `moduleManifest()` using `staticcall`.
The function MUST perform the following preliminary checks:
-- Revert if the plugin has already been installed on the modular account.
-- Revert if the plugin does not implement ERC-165 or does not support the `IPlugin` interface.
-- Revert if `manifestHash` does not match the computed Keccak-256 hash of the plugin's returned manifest. This prevents installation of plugins that attempt to install a different plugin configuration than the one that was approved by the client.
+- Revert if the module has already been installed on the modular account.
+- Revert if the module does not implement ERC-165 or does not support the `IModule` interface.
+- Revert if `manifestHash` does not match the computed Keccak-256 hash of the module's returned manifest. This prevents installation of modules that attempt to install a different module configuration than the one that was approved by the client.
- Revert if any address in `dependencies` does not support the interface at its matching index in the manifest's `dependencyInterfaceIds`, or if the two array lengths do not match, or if any of the dependencies are not already installed on the modular account.
-The function MUST record the manifest hash and dependencies that were used for the plugin's installation. Each dependency's record MUST also be updated to reflect that it has a new dependent. These records MUST be used to ensure calls to `uninstallPlugin` are comprehensive and undo all edited configuration state from installation. The mechanism by which these records are stored and validated is up to the implementation.
+The function MUST record the manifest hash and dependencies that were used for the module's installation. Each dependency's record MUST also be updated to reflect that it has a new dependent. These records MUST be used to ensure calls to `uninstallModule` are comprehensive and undo all edited configuration state from installation. The mechanism by which these records are stored and validated is up to the implementation.
-The function MUST store the plugin's permitted function selectors, permitted external calls, and whether it can spend the account's native tokens, to be able to validate calls to `executeFromPlugin` and `executeFromPluginExternal`.
+The function MUST store the module's permitted function selectors, permitted external calls, and whether it can spend the account's native tokens, to be able to validate calls to `executeFromModule` and `executeFromModuleExternal`.
The function MUST parse through the execution functions, validation functions, and hooks in the manifest and add them to the modular account after resolving each `ManifestFunction` type.
@@ -465,36 +465,36 @@ The function MUST parse through the execution functions, validation functions, a
The function MAY store the interface IDs provided in the manifest's `interfaceIds` and update its `supportsInterface` behavior accordingly.
-Next, the function MUST call the plugin's `onInstall` callback with the data provided in the `pluginInstallData` parameter. This serves to initialize the plugin state for the modular account. If `onInstall` reverts, the `installPlugin` function MUST revert.
+Next, the function MUST call the module's `onInstall` callback with the data provided in the `moduleInstallData` parameter. This serves to initialize the module state for the modular account. If `onInstall` reverts, the `installModule` function MUST revert.
-Finally, the function MUST emit the event `PluginInstalled` with the plugin's address, the hash of its manifest, and the dependencies that were used.
+Finally, the function MUST emit the event `ModuleInstalled` with the module's address, the hash of its manifest, and the dependencies that were used.
-> **⚠️ The ability to install and uninstall plugins is very powerful. The security of these functions determines the security of the account. It is critical for modular account implementers to make sure the implementation of the functions in `IPluginManager` have the proper security consideration and access control in place.**
+> **⚠️ The ability to install and uninstall modules is very powerful. The security of these functions determines the security of the account. It is critical for modular account implementers to make sure the implementation of the functions in `IModuleManager` have the proper security consideration and access control in place.**
-#### Calls to `uninstallPlugin`
+#### Calls to `uninstallModule`
-The function `uninstallPlugin` accepts 3 parameters: the address of the plugin to uninstall, a bytes field that may have custom requirements or uses by the implementing account, and ABI-encoded data to pass to the plugin's `onUninstall` callback.
+The function `uninstallModule` accepts 3 parameters: the address of the module to uninstall, a bytes field that may have custom requirements or uses by the implementing account, and ABI-encoded data to pass to the module's `onUninstall` callback.
-The function MUST revert if the plugin is not installed on the modular account.
+The function MUST revert if the module is not installed on the modular account.
The function SHOULD perform the following checks:
-- Revert if the hash of the manifest used at install time does not match the computed Keccak-256 hash of the plugin's current manifest. This prevents unclean removal of plugins that attempt to force a removal of a different plugin configuration than the one that was originally approved by the client for installation. To allow for removal of such plugins, the modular account MAY implement the capability for the manifest to be encoded in the config field as a parameter.
-- Revert if there is at least 1 other installed plugin that depends on validation functions added by this plugin. Plugins used as dependencies SHOULD NOT be uninstalled while dependent plugins exist.
+- Revert if the hash of the manifest used at install time does not match the computed Keccak-256 hash of the module's current manifest. This prevents unclean removal of modules that attempt to force a removal of a different module configuration than the one that was originally approved by the client for installation. To allow for removal of such modules, the modular account MAY implement the capability for the manifest to be encoded in the config field as a parameter.
+- Revert if there is at least 1 other installed module that depends on validation functions added by this module. Modules used as dependencies SHOULD NOT be uninstalled while dependent modules exist.
-The function SHOULD update account storage to reflect the uninstall via inspection functions, such as those defined by `IAccountLoupe`. Each dependency's record SHOULD also be updated to reflect that it has no longer has this plugin as a dependent.
+The function SHOULD update account storage to reflect the uninstall via inspection functions, such as those defined by `IAccountLoupe`. Each dependency's record SHOULD also be updated to reflect that it has no longer has this module as a dependent.
-The function MUST remove records for the plugin's manifest hash, dependencies, permitted function selectors, permitted external calls, and whether it can spend the account's native tokens.
+The function MUST remove records for the module's manifest hash, dependencies, permitted function selectors, permitted external calls, and whether it can spend the account's native tokens.
-The function MUST parse through the execution functions, validation functions, and hooks in the manifest and remove them from the modular account after resolving each `ManifestFunction` type. If multiple plugins added the same hook, it MUST persist until the last plugin is uninstalled.
+The function MUST parse through the execution functions, validation functions, and hooks in the manifest and remove them from the modular account after resolving each `ManifestFunction` type. If multiple modules added the same hook, it MUST persist until the last module is uninstalled.
-If the account stored the interface IDs provided in the manifest's `interfaceIds` during installation, it MUST remove them and update its `supportsInterface` behavior accordingly. If multiple plugins added the same interface ID, it MUST persist until the last plugin is uninstalled.
+If the account stored the interface IDs provided in the manifest's `interfaceIds` during installation, it MUST remove them and update its `supportsInterface` behavior accordingly. If multiple modules added the same interface ID, it MUST persist until the last module is uninstalled.
-Next, the function MUST call the plugin's `onUninstall` callback with the data provided in the `pluginUninstallData` parameter. This serves to clear the plugin state for the modular account. If `onUninstall` reverts, execution SHOULD continue to allow the uninstall to complete.
+Next, the function MUST call the module's `onUninstall` callback with the data provided in the `moduleUninstallData` parameter. This serves to clear the module state for the modular account. If `onUninstall` reverts, execution SHOULD continue to allow the uninstall to complete.
-Finally, the function MUST emit the event `PluginUninstalled` with the plugin's address and whether the `onUninstall` callback succeeded.
+Finally, the function MUST emit the event `ModuleUninstalled` with the module's address and whether the `onUninstall` callback succeeded.
-> **⚠️ Incorrectly uninstalled plugins can prevent uninstalls of their dependencies. Therefore, some form of validation that the uninstall step completely and correctly removes the plugin and its usage of dependencies is required.**
+> **⚠️ Incorrectly uninstalled modules can prevent uninstalls of their dependencies. Therefore, some form of validation that the uninstall step completely and correctly removes the module and its usage of dependencies is required.**
#### Calls to `validateUserOp`
@@ -506,26 +506,26 @@ Then, the modular account MUST execute the validation function with the user ope
#### Calls to execution functions
-When a function other than a native function is called on an modular account, it MUST find the plugin configuration for the corresponding selector added via plugin installation. If no corresponding plugin is found, the modular account MUST revert. Otherwise, the following steps MUST be performed.
+When a function other than a native function is called on an modular account, it MUST find the module configuration for the corresponding selector added via module installation. If no corresponding module is found, the modular account MUST revert. Otherwise, the following steps MUST be performed.
-Additionally, when the modular account natively implements functions in `IPluginManager` and `IStandardExecutor`, the same following steps MUST be performed for those functions. Other native functions MAY perform these steps.
+Additionally, when the modular account natively implements functions in `IModuleManager` and `IStandardExecutor`, the same following steps MUST be performed for those functions. Other native functions MAY perform these steps.
The steps to perform are:
- If the call is not from the `EntryPoint`, then find an associated runtime validation function. If one does not exist, execution MUST revert. The modular account MUST execute all pre runtime validation hooks, then the runtime validation function, with the `call` opcode. All of these functions MUST receive the caller, value, and execution function's calldata as parameters. If any of these functions revert, execution MUST revert. If any pre execution hooks are set to `PRE_HOOK_ALWAYS_DENY`, execution MUST revert. If the validation function is set to `RUNTIME_VALIDATION_ALWAYS_ALLOW`, the runtime validation function MUST be bypassed.
-- If there are pre execution hooks defined for the execution function, execute those hooks with the caller, value, and execution function's calldata as parameters. If any of these hooks returns data, it MUST be preserved until the call to the post execution hook. The operation MUST be done with the `call` opcode. If there are duplicate pre execution hooks (i.e., hooks with identical `PluginEntity`s), run the hook only once. If any of these functions revert, execution MUST revert.
+- If there are pre execution hooks defined for the execution function, execute those hooks with the caller, value, and execution function's calldata as parameters. If any of these hooks returns data, it MUST be preserved until the call to the post execution hook. The operation MUST be done with the `call` opcode. If there are duplicate pre execution hooks (i.e., hooks with identical `ModuleEntity`s), run the hook only once. If any of these functions revert, execution MUST revert.
- Run the execution function.
- If any post execution hooks are defined, run the functions. If a pre execution hook returned data to the account, that data MUST be passed as a parameter to the associated post execution hook. The operation MUST be done with the `call` opcode. If there are duplicate post execution hooks, run them once for each unique associated pre execution hook. For post execution hooks without an associated pre execution hook, run the hook only once. If any of these functions revert, execution MUST revert.
-The set of hooks run for a given execution function MUST be the hooks specified by account state at the start of the execution phase. This is relevant for functions like `installPlugin` and `uninstallPlugin`, which modify the account state, and possibly other execution or native functions as well.
+The set of hooks run for a given execution function MUST be the hooks specified by account state at the start of the execution phase. This is relevant for functions like `installModule` and `uninstallModule`, which modify the account state, and possibly other execution or native functions as well.
-#### Calls made from plugins
+#### Calls made from modules
-Plugins MAY interact with other plugins and external addresses through the modular account using the functions defined in the `IPluginExecutor` interface. These functions MAY be called without a defined validation function, but the modular account MUST enforce these checks and behaviors:
+Modules MAY interact with other modules and external addresses through the modular account using the functions defined in the `IModuleExecutor` interface. These functions MAY be called without a defined validation function, but the modular account MUST enforce these checks and behaviors:
-The `executeFromPlugin` function MUST allow plugins to call execution functions installed by plugins on the modular account. Hooks matching the function selector provided in `data` MUST be called. If the calling plugin's manifest did not include the provided function selector within `permittedExecutionSelectors` at the time of installation, execution MUST revert.
+The `executeFromModule` function MUST allow modules to call execution functions installed by modules on the modular account. Hooks matching the function selector provided in `data` MUST be called. If the calling module's manifest did not include the provided function selector within `permittedExecutionSelectors` at the time of installation, execution MUST revert.
-The `executeFromPluginExternal` function MUST allow plugins to call external addresses as specified by its parameters on behalf of the modular account. If the calling plugin's manifest did not explicitly allow the external call within `permittedExternalCalls` at the time of installation, execution MUST revert.
+The `executeFromModuleExternal` function MUST allow modules to call external addresses as specified by its parameters on behalf of the modular account. If the calling module's manifest did not explicitly allow the external call within `permittedExternalCalls` at the time of installation, execution MUST revert.
## Rationale
@@ -533,7 +533,7 @@ ERC-4337 compatible accounts must implement the `IAccount` interface, which cons
The function routing pattern of ERC-2535 is the logical starting point for achieving this extension into multi-functional accounts. It also meets our other primary design rationale of generalizing execution calls across multiple implementing contracts. However, a strict diamond pattern is constrained by its inability to customize validation schemes for specific execution functions in the context of `validateUserOp`, and its requirement of `delegatecall`.
-This proposal includes several interfaces that build on ERC-4337 and are inspired by ERC-2535. First, we standardize a set of modular functions that allow smart contract developers greater flexibility in bundling validation, execution, and hook logic. We also propose interfaces that take inspiration from the diamond standard and provide methods for querying execution functions, validation functions, and hooks on a modular account. The rest of the interfaces describe a plugin's methods for exposing its modular functions and desired configuration, and the modular account's methods for installing and removing plugins and allowing execution across plugins and external addresses.
+This proposal includes several interfaces that build on ERC-4337 and are inspired by ERC-2535. First, we standardize a set of modular functions that allow smart contract developers greater flexibility in bundling validation, execution, and hook logic. We also propose interfaces that take inspiration from the diamond standard and provide methods for querying execution functions, validation functions, and hooks on a modular account. The rest of the interfaces describe a module's methods for exposing its modular functions and desired configuration, and the modular account's methods for installing and removing modules and allowing execution across modules and external addresses.
## Backwards Compatibility
diff --git a/standard/assets/eip-6900/MSCA_Shared_Components_Diagram.svg b/standard/assets/eip-6900/MSCA_Shared_Components_Diagram.svg
index 836a8ad9..e443dd56 100644
--- a/standard/assets/eip-6900/MSCA_Shared_Components_Diagram.svg
+++ b/standard/assets/eip-6900/MSCA_Shared_Components_Diagram.svg
@@ -14,4 +14,4 @@
- Alice's MSCAUO / TxPluginHooksValidationExecutionPluginHooksValidationExecutionUO / TxBob's MSCA
\ No newline at end of file
+ Alice's MSCAUO / TxModuleHooksValidationExecutionModuleHooksValidationExecutionUO / TxBob's MSCA
\ No newline at end of file
diff --git a/standard/assets/eip-6900/Modular_Account_Call_Flow.svg b/standard/assets/eip-6900/Modular_Account_Call_Flow.svg
index c4112c33..8d7f7611 100644
--- a/standard/assets/eip-6900/Modular_Account_Call_Flow.svg
+++ b/standard/assets/eip-6900/Modular_Account_Call_Flow.svg
@@ -14,4 +14,4 @@
- Direct Call1 validation2. Execution Modular Account validateUserOpPre User Operation Validation Hook(s)User Operation Validation FunctionPre Execution Hook(s)Native Function / (Plugin) Execution FunctionPost Execution Hook(s)EntryPointEOA / SCRuntime Validation FunctionModular Account Call FlowPre Runtime Validation Hook(s)
\ No newline at end of file
+ Direct Call1 validation2. Execution Modular Account validateUserOpPre User Operation Validation Hook(s)User Operation Validation FunctionPre Execution Hook(s)Native Function / (Module) Execution FunctionPost Execution Hook(s)EntryPointEOA / SCRuntime Validation FunctionModular Account Call FlowPre Runtime Validation Hook(s)
\ No newline at end of file
diff --git a/standard/assets/eip-6900/Plugin_Execution_Flow.svg b/standard/assets/eip-6900/Plugin_Execution_Flow.svg
index 3a94b512..ed1ff580 100644
--- a/standard/assets/eip-6900/Plugin_Execution_Flow.svg
+++ b/standard/assets/eip-6900/Plugin_Execution_Flow.svg
@@ -18,4 +18,4 @@
- Permitted External Contracts & Methods executeFromPluginPre Execution Hook(s)Permitted Plugin Execution FunctionPost Execution Hook(s)PluginsPlugin Permission Check executeFromPluginExternal(Plugin) Execution Function1 calls plugin 2.2 calls external contracts through executeFromPluginExternalPlugin Permission CheckModular AccountPlugin Execution Flow2.1 calls other installed plugin through executeFromPluginPre executeFromPluginExternal Hook(s)Post executeFromPluginExternal Hook(s)
\ No newline at end of file
+ Permitted External Contracts & Methods executeFromModulePre Execution Hook(s)Permitted Module Execution FunctionPost Execution Hook(s)ModulesModule Permission Check executeFromModuleExternal(Module) Execution Function1 calls module 2.2 calls external contracts through executeFromModuleExternalModule Permission CheckModular AccountModule Execution Flow2.1 calls other installed module through executeFromModulePre executeFromModuleExternal Hook(s)Post executeFromModuleExternal Hook(s)
\ No newline at end of file
diff --git a/test/account/AccountExecHooks.t.sol b/test/account/AccountExecHooks.t.sol
index ba3a2098..052cea4e 100644
--- a/test/account/AccountExecHooks.t.sol
+++ b/test/account/AccountExecHooks.t.sol
@@ -3,17 +3,17 @@ pragma solidity ^0.8.19;
import {IExecutionHook} from "../../src/interfaces/IExecutionHook.sol";
import {
- IPlugin,
+ IModule,
ManifestExecutionFunction,
ManifestExecutionHook,
- PluginManifest
-} from "../../src/interfaces/IPlugin.sol";
+ ModuleManifest
+} from "../../src/interfaces/IModule.sol";
-import {MockPlugin} from "../mocks/MockPlugin.sol";
+import {MockModule} from "../mocks/MockModule.sol";
import {AccountTestBase} from "../utils/AccountTestBase.sol";
contract AccountExecHooksTest is AccountTestBase {
- MockPlugin public mockPlugin1;
+ MockModule public mockModule1;
bytes32 public manifestHash1;
bytes32 public manifestHash2;
@@ -22,11 +22,11 @@ contract AccountExecHooksTest is AccountTestBase {
uint32 internal constant _POST_HOOK_FUNCTION_ID_2 = 2;
uint32 internal constant _BOTH_HOOKS_FUNCTION_ID_3 = 3;
- PluginManifest internal _m1;
+ ModuleManifest internal _m1;
- event PluginInstalled(address indexed plugin, bytes32 manifestHash);
- event PluginUninstalled(address indexed plugin, bool indexed callbacksSucceeded);
- // emitted by MockPlugin
+ event ModuleInstalled(address indexed module, bytes32 manifestHash);
+ event ModuleUninstalled(address indexed module, bool indexed callbacksSucceeded);
+ // emitted by MockModule
event ReceivedCall(bytes msgData, uint256 msgValue);
function setUp() public {
@@ -42,7 +42,7 @@ contract AccountExecHooksTest is AccountTestBase {
}
function test_preExecHook_install() public {
- _installPlugin1WithHooks(
+ _installModule1WithHooks(
ManifestExecutionHook({
executionSelector: _EXEC_SELECTOR,
entityId: _PRE_HOOK_FUNCTION_ID_1,
@@ -52,7 +52,7 @@ contract AccountExecHooksTest is AccountTestBase {
);
}
- /// @dev Plugin 1 hook pair: [1, null]
+ /// @dev Module 1 hook pair: [1, null]
/// Expected execution: [1, null]
function test_preExecHook_run() public {
test_preExecHook_install();
@@ -66,7 +66,7 @@ contract AccountExecHooksTest is AccountTestBase {
uint256(0), // msg.value in call to account
abi.encodeWithSelector(_EXEC_SELECTOR)
),
- 0 // msg value in call to plugin
+ 0 // msg value in call to module
);
(bool success,) = address(account1).call(abi.encodeWithSelector(_EXEC_SELECTOR));
@@ -76,11 +76,11 @@ contract AccountExecHooksTest is AccountTestBase {
function test_preExecHook_uninstall() public {
test_preExecHook_install();
- _uninstallPlugin(mockPlugin1);
+ _uninstallModule(mockModule1);
}
function test_execHookPair_install() public {
- _installPlugin1WithHooks(
+ _installModule1WithHooks(
ManifestExecutionHook({
executionSelector: _EXEC_SELECTOR,
entityId: _BOTH_HOOKS_FUNCTION_ID_3,
@@ -90,7 +90,7 @@ contract AccountExecHooksTest is AccountTestBase {
);
}
- /// @dev Plugin 1 hook pair: [1, 2]
+ /// @dev Module 1 hook pair: [1, 2]
/// Expected execution: [1, 2]
function test_execHookPair_run() public {
test_execHookPair_install();
@@ -105,7 +105,7 @@ contract AccountExecHooksTest is AccountTestBase {
uint256(0), // msg.value in call to account
abi.encodeWithSelector(_EXEC_SELECTOR)
),
- 0 // msg value in call to plugin
+ 0 // msg value in call to module
);
vm.expectEmit(true, true, true, true);
// exec call
@@ -114,7 +114,7 @@ contract AccountExecHooksTest is AccountTestBase {
// post hook call
emit ReceivedCall(
abi.encodeCall(IExecutionHook.postExecutionHook, (_BOTH_HOOKS_FUNCTION_ID_3, "")),
- 0 // msg value in call to plugin
+ 0 // msg value in call to module
);
(bool success,) = address(account1).call(abi.encodeWithSelector(_EXEC_SELECTOR));
@@ -124,11 +124,11 @@ contract AccountExecHooksTest is AccountTestBase {
function test_execHookPair_uninstall() public {
test_execHookPair_install();
- _uninstallPlugin(mockPlugin1);
+ _uninstallModule(mockModule1);
}
function test_postOnlyExecHook_install() public {
- _installPlugin1WithHooks(
+ _installModule1WithHooks(
ManifestExecutionHook({
executionSelector: _EXEC_SELECTOR,
entityId: _POST_HOOK_FUNCTION_ID_2,
@@ -138,7 +138,7 @@ contract AccountExecHooksTest is AccountTestBase {
);
}
- /// @dev Plugin 1 hook pair: [null, 2]
+ /// @dev Module 1 hook pair: [null, 2]
/// Expected execution: [null, 2]
function test_postOnlyExecHook_run() public {
test_postOnlyExecHook_install();
@@ -146,7 +146,7 @@ contract AccountExecHooksTest is AccountTestBase {
vm.expectEmit(true, true, true, true);
emit ReceivedCall(
abi.encodeCall(IExecutionHook.postExecutionHook, (_POST_HOOK_FUNCTION_ID_2, "")),
- 0 // msg value in call to plugin
+ 0 // msg value in call to module
);
(bool success,) = address(account1).call(abi.encodeWithSelector(_EXEC_SELECTOR));
@@ -156,34 +156,34 @@ contract AccountExecHooksTest is AccountTestBase {
function test_postOnlyExecHook_uninstall() public {
test_postOnlyExecHook_install();
- _uninstallPlugin(mockPlugin1);
+ _uninstallModule(mockModule1);
}
- function _installPlugin1WithHooks(ManifestExecutionHook memory execHooks) internal {
+ function _installModule1WithHooks(ManifestExecutionHook memory execHooks) internal {
_m1.executionHooks.push(execHooks);
- mockPlugin1 = new MockPlugin(_m1);
- manifestHash1 = keccak256(abi.encode(mockPlugin1.pluginManifest()));
+ mockModule1 = new MockModule(_m1);
+ manifestHash1 = keccak256(abi.encode(mockModule1.moduleManifest()));
vm.expectEmit(true, true, true, true);
- emit ReceivedCall(abi.encodeCall(IPlugin.onInstall, (bytes(""))), 0);
+ emit ReceivedCall(abi.encodeCall(IModule.onInstall, (bytes(""))), 0);
vm.expectEmit(true, true, true, true);
- emit PluginInstalled(address(mockPlugin1), manifestHash1);
+ emit ModuleInstalled(address(mockModule1), manifestHash1);
vm.prank(address(entryPoint));
- account1.installPlugin({
- plugin: address(mockPlugin1),
+ account1.installModule({
+ module: address(mockModule1),
manifestHash: manifestHash1,
- pluginInstallData: bytes("")
+ moduleInstallData: bytes("")
});
}
- function _uninstallPlugin(MockPlugin plugin) internal {
+ function _uninstallModule(MockModule module) internal {
vm.expectEmit(true, true, true, true);
- emit ReceivedCall(abi.encodeCall(IPlugin.onUninstall, (bytes(""))), 0);
+ emit ReceivedCall(abi.encodeCall(IModule.onUninstall, (bytes(""))), 0);
vm.expectEmit(true, true, true, true);
- emit PluginUninstalled(address(plugin), true);
+ emit ModuleUninstalled(address(module), true);
vm.prank(address(entryPoint));
- account1.uninstallPlugin(address(plugin), bytes(""), bytes(""));
+ account1.uninstallModule(address(module), bytes(""), bytes(""));
}
}
diff --git a/test/account/AccountLoupe.t.sol b/test/account/AccountLoupe.t.sol
index f0670848..c4f4abc0 100644
--- a/test/account/AccountLoupe.t.sol
+++ b/test/account/AccountLoupe.t.sol
@@ -3,38 +3,38 @@ pragma solidity ^0.8.19;
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
-import {PluginEntity, PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntity, ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {ExecutionHook} from "../../src/interfaces/IAccountLoupe.sol";
-import {IPluginManager} from "../../src/interfaces/IPluginManager.sol";
+import {IModuleManager} from "../../src/interfaces/IModuleManager.sol";
import {IStandardExecutor} from "../../src/interfaces/IStandardExecutor.sol";
-import {ComprehensivePlugin} from "../mocks/plugins/ComprehensivePlugin.sol";
+import {ComprehensiveModule} from "../mocks/modules/ComprehensiveModule.sol";
import {CustomValidationTestBase} from "../utils/CustomValidationTestBase.sol";
contract AccountLoupeTest is CustomValidationTestBase {
- ComprehensivePlugin public comprehensivePlugin;
+ ComprehensiveModule public comprehensiveModule;
event ReceivedCall(bytes msgData, uint256 msgValue);
function setUp() public {
- comprehensivePlugin = new ComprehensivePlugin();
+ comprehensiveModule = new ComprehensiveModule();
_customValidationSetup();
- bytes32 manifestHash = keccak256(abi.encode(comprehensivePlugin.pluginManifest()));
+ bytes32 manifestHash = keccak256(abi.encode(comprehensiveModule.moduleManifest()));
vm.prank(address(entryPoint));
- account1.installPlugin(address(comprehensivePlugin), manifestHash, "");
+ account1.installModule(address(comprehensiveModule), manifestHash, "");
}
- function test_pluginLoupe_getInstalledPlugins_initial() public {
- address[] memory plugins = account1.getInstalledPlugins();
+ function test_moduleLoupe_getInstalledModules_initial() public {
+ address[] memory modules = account1.getInstalledModules();
- assertEq(plugins.length, 1);
+ assertEq(modules.length, 1);
- assertEq(plugins[0], address(comprehensivePlugin));
+ assertEq(modules[0], address(comprehensiveModule));
}
- function test_pluginLoupe_getExecutionFunctionHandler_native() public {
+ function test_moduleLoupe_getExecutionFunctionHandler_native() public {
bytes4[] memory selectorsToCheck = new bytes4[](5);
selectorsToCheck[0] = IStandardExecutor.execute.selector;
@@ -43,61 +43,61 @@ contract AccountLoupeTest is CustomValidationTestBase {
selectorsToCheck[2] = UUPSUpgradeable.upgradeToAndCall.selector;
- selectorsToCheck[3] = IPluginManager.installPlugin.selector;
+ selectorsToCheck[3] = IModuleManager.installModule.selector;
- selectorsToCheck[4] = IPluginManager.uninstallPlugin.selector;
+ selectorsToCheck[4] = IModuleManager.uninstallModule.selector;
for (uint256 i = 0; i < selectorsToCheck.length; i++) {
- address plugin = account1.getExecutionFunctionHandler(selectorsToCheck[i]);
+ address module = account1.getExecutionFunctionHandler(selectorsToCheck[i]);
- assertEq(plugin, address(account1));
+ assertEq(module, address(account1));
}
}
- function test_pluginLoupe_getExecutionFunctionConfig_plugin() public {
+ function test_moduleLoupe_getExecutionFunctionConfig_module() public {
bytes4[] memory selectorsToCheck = new bytes4[](1);
- address[] memory expectedPluginAddress = new address[](1);
+ address[] memory expectedModuleAddress = new address[](1);
- selectorsToCheck[0] = comprehensivePlugin.foo.selector;
- expectedPluginAddress[0] = address(comprehensivePlugin);
+ selectorsToCheck[0] = comprehensiveModule.foo.selector;
+ expectedModuleAddress[0] = address(comprehensiveModule);
for (uint256 i = 0; i < selectorsToCheck.length; i++) {
- address plugin = account1.getExecutionFunctionHandler(selectorsToCheck[i]);
+ address module = account1.getExecutionFunctionHandler(selectorsToCheck[i]);
- assertEq(plugin, expectedPluginAddress[i]);
+ assertEq(module, expectedModuleAddress[i]);
}
}
- function test_pluginLoupe_getSelectors() public {
- PluginEntity comprehensivePluginValidation =
- PluginEntityLib.pack(address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.VALIDATION));
+ function test_moduleLoupe_getSelectors() public {
+ ModuleEntity comprehensiveModuleValidation =
+ ModuleEntityLib.pack(address(comprehensiveModule), uint32(ComprehensiveModule.EntityId.VALIDATION));
- bytes4[] memory selectors = account1.getSelectors(comprehensivePluginValidation);
+ bytes4[] memory selectors = account1.getSelectors(comprehensiveModuleValidation);
assertEq(selectors.length, 1);
- assertEq(selectors[0], comprehensivePlugin.foo.selector);
+ assertEq(selectors[0], comprehensiveModule.foo.selector);
}
- function test_pluginLoupe_getExecutionHooks() public {
- ExecutionHook[] memory hooks = account1.getExecutionHooks(comprehensivePlugin.foo.selector);
+ function test_moduleLoupe_getExecutionHooks() public {
+ ExecutionHook[] memory hooks = account1.getExecutionHooks(comprehensiveModule.foo.selector);
ExecutionHook[3] memory expectedHooks = [
ExecutionHook({
- hookFunction: PluginEntityLib.pack(
- address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.BOTH_EXECUTION_HOOKS)
+ hookFunction: ModuleEntityLib.pack(
+ address(comprehensiveModule), uint32(ComprehensiveModule.EntityId.BOTH_EXECUTION_HOOKS)
),
isPreHook: true,
isPostHook: true
}),
ExecutionHook({
- hookFunction: PluginEntityLib.pack(
- address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.PRE_EXECUTION_HOOK)
+ hookFunction: ModuleEntityLib.pack(
+ address(comprehensiveModule), uint32(ComprehensiveModule.EntityId.PRE_EXECUTION_HOOK)
),
isPreHook: true,
isPostHook: false
}),
ExecutionHook({
- hookFunction: PluginEntityLib.pack(
- address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.POST_EXECUTION_HOOK)
+ hookFunction: ModuleEntityLib.pack(
+ address(comprehensiveModule), uint32(ComprehensiveModule.EntityId.POST_EXECUTION_HOOK)
),
isPreHook: false,
isPostHook: true
@@ -107,30 +107,30 @@ contract AccountLoupeTest is CustomValidationTestBase {
assertEq(hooks.length, 3);
for (uint256 i = 0; i < hooks.length; i++) {
assertEq(
- PluginEntity.unwrap(hooks[i].hookFunction), PluginEntity.unwrap(expectedHooks[i].hookFunction)
+ ModuleEntity.unwrap(hooks[i].hookFunction), ModuleEntity.unwrap(expectedHooks[i].hookFunction)
);
assertEq(hooks[i].isPreHook, expectedHooks[i].isPreHook);
assertEq(hooks[i].isPostHook, expectedHooks[i].isPostHook);
}
}
- function test_pluginLoupe_getValidationHooks() public {
- PluginEntity[] memory hooks = account1.getPreValidationHooks(_signerValidation);
+ function test_moduleLoupe_getValidationHooks() public {
+ ModuleEntity[] memory hooks = account1.getPreValidationHooks(_signerValidation);
assertEq(hooks.length, 2);
assertEq(
- PluginEntity.unwrap(hooks[0]),
- PluginEntity.unwrap(
- PluginEntityLib.pack(
- address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.PRE_VALIDATION_HOOK_1)
+ ModuleEntity.unwrap(hooks[0]),
+ ModuleEntity.unwrap(
+ ModuleEntityLib.pack(
+ address(comprehensiveModule), uint32(ComprehensiveModule.EntityId.PRE_VALIDATION_HOOK_1)
)
)
);
assertEq(
- PluginEntity.unwrap(hooks[1]),
- PluginEntity.unwrap(
- PluginEntityLib.pack(
- address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.PRE_VALIDATION_HOOK_2)
+ ModuleEntity.unwrap(hooks[1]),
+ ModuleEntity.unwrap(
+ ModuleEntityLib.pack(
+ address(comprehensiveModule), uint32(ComprehensiveModule.EntityId.PRE_VALIDATION_HOOK_2)
)
)
);
@@ -142,14 +142,14 @@ contract AccountLoupeTest is CustomValidationTestBase {
internal
virtual
override
- returns (PluginEntity, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory)
+ returns (ModuleEntity, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory)
{
- PluginEntity[] memory preValidationHooks = new PluginEntity[](2);
- preValidationHooks[0] = PluginEntityLib.pack(
- address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.PRE_VALIDATION_HOOK_1)
+ ModuleEntity[] memory preValidationHooks = new ModuleEntity[](2);
+ preValidationHooks[0] = ModuleEntityLib.pack(
+ address(comprehensiveModule), uint32(ComprehensiveModule.EntityId.PRE_VALIDATION_HOOK_1)
);
- preValidationHooks[1] = PluginEntityLib.pack(
- address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.PRE_VALIDATION_HOOK_2)
+ preValidationHooks[1] = ModuleEntityLib.pack(
+ address(comprehensiveModule), uint32(ComprehensiveModule.EntityId.PRE_VALIDATION_HOOK_2)
);
bytes[] memory installDatas = new bytes[](2);
diff --git a/test/account/AccountReturnData.t.sol b/test/account/AccountReturnData.t.sol
index fa8bdf86..febaa54b 100644
--- a/test/account/AccountReturnData.t.sol
+++ b/test/account/AccountReturnData.t.sol
@@ -1,51 +1,51 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;
-import {PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {Call} from "../../src/interfaces/IStandardExecutor.sol";
import {
RegularResultContract,
- ResultConsumerPlugin,
- ResultCreatorPlugin
-} from "../mocks/plugins/ReturnDataPluginMocks.sol";
+ ResultConsumerModule,
+ ResultCreatorModule
+} from "../mocks/modules/ReturnDataModuleMocks.sol";
import {AccountTestBase} from "../utils/AccountTestBase.sol";
import {TEST_DEFAULT_VALIDATION_ENTITY_ID} from "../utils/TestConstants.sol";
-// Tests all the different ways that return data can be read from plugins through an account
+// Tests all the different ways that return data can be read from modules through an account
contract AccountReturnDataTest is AccountTestBase {
RegularResultContract public regularResultContract;
- ResultCreatorPlugin public resultCreatorPlugin;
- ResultConsumerPlugin public resultConsumerPlugin;
+ ResultCreatorModule public resultCreatorModule;
+ ResultConsumerModule public resultConsumerModule;
function setUp() public {
_transferOwnershipToTest();
regularResultContract = new RegularResultContract();
- resultCreatorPlugin = new ResultCreatorPlugin();
- resultConsumerPlugin = new ResultConsumerPlugin(resultCreatorPlugin, regularResultContract);
+ resultCreatorModule = new ResultCreatorModule();
+ resultConsumerModule = new ResultConsumerModule(resultCreatorModule, regularResultContract);
- // Add the result creator plugin to the account
- bytes32 resultCreatorManifestHash = keccak256(abi.encode(resultCreatorPlugin.pluginManifest()));
+ // Add the result creator module to the account
+ bytes32 resultCreatorManifestHash = keccak256(abi.encode(resultCreatorModule.moduleManifest()));
vm.prank(address(entryPoint));
- account1.installPlugin({
- plugin: address(resultCreatorPlugin),
+ account1.installModule({
+ module: address(resultCreatorModule),
manifestHash: resultCreatorManifestHash,
- pluginInstallData: ""
+ moduleInstallData: ""
});
- // Add the result consumer plugin to the account
- bytes32 resultConsumerManifestHash = keccak256(abi.encode(resultConsumerPlugin.pluginManifest()));
+ // Add the result consumer module to the account
+ bytes32 resultConsumerManifestHash = keccak256(abi.encode(resultConsumerModule.moduleManifest()));
vm.prank(address(entryPoint));
- account1.installPlugin({
- plugin: address(resultConsumerPlugin),
+ account1.installModule({
+ module: address(resultConsumerModule),
manifestHash: resultConsumerManifestHash,
- pluginInstallData: ""
+ moduleInstallData: ""
});
}
- // Tests the ability to read the result of plugin execution functions via the account's fallback
+ // Tests the ability to read the result of module execution functions via the account's fallback
function test_returnData_fallback() public {
- bytes32 result = ResultCreatorPlugin(address(account1)).foo();
+ bytes32 result = ResultCreatorModule(address(account1)).foo();
assertEq(result, keccak256("bar"));
}
@@ -58,7 +58,7 @@ contract AccountReturnDataTest is AccountTestBase {
(address(regularResultContract), 0, abi.encodeCall(RegularResultContract.foo, ()))
),
_encodeSignature(
- PluginEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
+ ModuleEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
GLOBAL_VALIDATION,
""
)
@@ -86,7 +86,7 @@ contract AccountReturnDataTest is AccountTestBase {
bytes memory retData = account1.executeWithAuthorization(
abi.encodeCall(account1.executeBatch, (calls)),
_encodeSignature(
- PluginEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
+ ModuleEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
GLOBAL_VALIDATION,
""
)
@@ -102,15 +102,15 @@ contract AccountReturnDataTest is AccountTestBase {
}
// Tests the ability to read data via routing to fallback functions
- function test_returnData_execFromPlugin_fallback() public {
- bool result = ResultConsumerPlugin(address(account1)).checkResultFallback(keccak256("bar"));
+ function test_returnData_execFromModule_fallback() public {
+ bool result = ResultConsumerModule(address(account1)).checkResultFallback(keccak256("bar"));
assertTrue(result);
}
// Tests the ability to read data via executeWithAuthorization
function test_returnData_authorized_exec() public {
- bool result = ResultConsumerPlugin(address(account1)).checkResultExecuteWithAuthorization(
+ bool result = ResultConsumerModule(address(account1)).checkResultExecuteWithAuthorization(
address(regularResultContract), keccak256("bar")
);
diff --git a/test/account/DirectCallsFromPlugin.t.sol b/test/account/DirectCallsFromModule.t.sol
similarity index 59%
rename from test/account/DirectCallsFromPlugin.t.sol
rename to test/account/DirectCallsFromModule.t.sol
index 9e56739a..b8d39728 100644
--- a/test/account/DirectCallsFromPlugin.t.sol
+++ b/test/account/DirectCallsFromModule.t.sol
@@ -1,53 +1,53 @@
pragma solidity ^0.8.19;
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntity, PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntity, ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {ValidationConfig, ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol";
import {ExecutionHook} from "../../src/interfaces/IAccountLoupe.sol";
import {Call, IStandardExecutor} from "../../src/interfaces/IStandardExecutor.sol";
-import {DirectCallPlugin} from "../mocks/plugins/DirectCallPlugin.sol";
+import {DirectCallModule} from "../mocks/modules/DirectCallModule.sol";
import {AccountTestBase} from "../utils/AccountTestBase.sol";
-contract DirectCallsFromPluginTest is AccountTestBase {
+contract DirectCallsFromModuleTest is AccountTestBase {
using ValidationConfigLib for ValidationConfig;
- DirectCallPlugin internal _plugin;
- PluginEntity internal _pluginEntity;
+ DirectCallModule internal _module;
+ ModuleEntity internal _moduleEntity;
function setUp() public {
- _plugin = new DirectCallPlugin();
- assertFalse(_plugin.preHookRan());
- assertFalse(_plugin.postHookRan());
- _pluginEntity = PluginEntityLib.pack(address(_plugin), type(uint32).max);
+ _module = new DirectCallModule();
+ assertFalse(_module.preHookRan());
+ assertFalse(_module.postHookRan());
+ _moduleEntity = ModuleEntityLib.pack(address(_module), type(uint32).max);
}
/* -------------------------------------------------------------------------- */
/* Negatives */
/* -------------------------------------------------------------------------- */
- function test_Fail_DirectCallPluginNotInstalled() external {
- vm.prank(address(_plugin));
+ function test_Fail_DirectCallModuleNotInstalled() external {
+ vm.prank(address(_module));
vm.expectRevert(_buildDirectCallDisallowedError(IStandardExecutor.execute.selector));
account1.execute(address(0), 0, "");
}
- function test_Fail_DirectCallPluginUninstalled() external {
- _installPlugin();
+ function test_Fail_DirectCallModuleUninstalled() external {
+ _installModule();
- _uninstallPlugin();
+ _uninstallModule();
- vm.prank(address(_plugin));
+ vm.prank(address(_module));
vm.expectRevert(_buildDirectCallDisallowedError(IStandardExecutor.execute.selector));
account1.execute(address(0), 0, "");
}
- function test_Fail_DirectCallPluginCallOtherSelector() external {
- _installPlugin();
+ function test_Fail_DirectCallModuleCallOtherSelector() external {
+ _installModule();
Call[] memory calls = new Call[](0);
- vm.prank(address(_plugin));
+ vm.prank(address(_module));
vm.expectRevert(_buildDirectCallDisallowedError(IStandardExecutor.executeBatch.selector));
account1.executeBatch(calls);
}
@@ -56,46 +56,46 @@ contract DirectCallsFromPluginTest is AccountTestBase {
/* Positives */
/* -------------------------------------------------------------------------- */
- function test_Pass_DirectCallFromPluginPrank() external {
- _installPlugin();
+ function test_Pass_DirectCallFromModulePrank() external {
+ _installModule();
- vm.prank(address(_plugin));
+ vm.prank(address(_module));
account1.execute(address(0), 0, "");
- assertTrue(_plugin.preHookRan());
- assertTrue(_plugin.postHookRan());
+ assertTrue(_module.preHookRan());
+ assertTrue(_module.postHookRan());
}
- function test_Pass_DirectCallFromPluginCallback() external {
- _installPlugin();
+ function test_Pass_DirectCallFromModuleCallback() external {
+ _installModule();
- bytes memory encodedCall = abi.encodeCall(DirectCallPlugin.directCall, ());
+ bytes memory encodedCall = abi.encodeCall(DirectCallModule.directCall, ());
vm.prank(address(entryPoint));
- bytes memory result = account1.execute(address(_plugin), 0, encodedCall);
+ bytes memory result = account1.execute(address(_module), 0, encodedCall);
- assertTrue(_plugin.preHookRan());
- assertTrue(_plugin.postHookRan());
+ assertTrue(_module.preHookRan());
+ assertTrue(_module.postHookRan());
- // the directCall() function in the _plugin calls back into `execute()` with an encoded call back into the
- // _plugin's getData() function.
- assertEq(abi.decode(result, (bytes)), abi.encode(_plugin.getData()));
+ // the directCall() function in the _module calls back into `execute()` with an encoded call back into the
+ // _module's getData() function.
+ assertEq(abi.decode(result, (bytes)), abi.encode(_module.getData()));
}
- function test_Flow_DirectCallFromPluginSequence() external {
+ function test_Flow_DirectCallFromModuleSequence() external {
// Install => Succeesfully call => uninstall => fail to call
- _installPlugin();
+ _installModule();
- vm.prank(address(_plugin));
+ vm.prank(address(_module));
account1.execute(address(0), 0, "");
- assertTrue(_plugin.preHookRan());
- assertTrue(_plugin.postHookRan());
+ assertTrue(_module.preHookRan());
+ assertTrue(_module.postHookRan());
- _uninstallPlugin();
+ _uninstallModule();
- vm.prank(address(_plugin));
+ vm.prank(address(_module));
vm.expectRevert(_buildDirectCallDisallowedError(IStandardExecutor.execute.selector));
account1.execute(address(0), 0, "");
}
@@ -104,27 +104,27 @@ contract DirectCallsFromPluginTest is AccountTestBase {
/* Internals */
/* -------------------------------------------------------------------------- */
- function _installPlugin() internal {
+ function _installModule() internal {
bytes4[] memory selectors = new bytes4[](1);
selectors[0] = IStandardExecutor.execute.selector;
ExecutionHook[] memory permissionHooks = new ExecutionHook[](1);
bytes[] memory permissionHookInitDatas = new bytes[](1);
- permissionHooks[0] = ExecutionHook({hookFunction: _pluginEntity, isPreHook: true, isPostHook: true});
+ permissionHooks[0] = ExecutionHook({hookFunction: _moduleEntity, isPreHook: true, isPostHook: true});
bytes memory encodedPermissionHooks = abi.encode(permissionHooks, permissionHookInitDatas);
vm.prank(address(entryPoint));
- ValidationConfig validationConfig = ValidationConfigLib.pack(_pluginEntity, false, false);
+ ValidationConfig validationConfig = ValidationConfigLib.pack(_moduleEntity, false, false);
account1.installValidation(validationConfig, selectors, "", "", encodedPermissionHooks);
}
- function _uninstallPlugin() internal {
+ function _uninstallModule() internal {
vm.prank(address(entryPoint));
- account1.uninstallValidation(_pluginEntity, "", abi.encode(new bytes[](0)), abi.encode(new bytes[](1)));
+ account1.uninstallValidation(_moduleEntity, "", abi.encode(new bytes[](0)), abi.encode(new bytes[](1)));
}
function _buildDirectCallDisallowedError(bytes4 selector) internal pure returns (bytes memory) {
diff --git a/test/account/GlobalValidationTest.t.sol b/test/account/GlobalValidationTest.t.sol
index 7ef7fdc5..b22d68eb 100644
--- a/test/account/GlobalValidationTest.t.sol
+++ b/test/account/GlobalValidationTest.t.sol
@@ -5,7 +5,7 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {AccountTestBase} from "../utils/AccountTestBase.sol";
@@ -27,7 +27,7 @@ contract GlobalValidationTest is AccountTestBase {
vm.deal(address(account2), 100 ether);
_signerValidation =
- PluginEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID);
+ ModuleEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID);
ethRecipient = makeAddr("ethRecipient");
vm.deal(ethRecipient, 1 wei);
diff --git a/test/account/MultiValidation.t.sol b/test/account/MultiValidation.t.sol
index afb84f1a..772011bf 100644
--- a/test/account/MultiValidation.t.sol
+++ b/test/account/MultiValidation.t.sol
@@ -9,11 +9,11 @@ import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntry
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol";
-import {PluginEntity} from "../../src/interfaces/IPluginManager.sol";
+import {ModuleEntity} from "../../src/interfaces/IModuleManager.sol";
import {IStandardExecutor} from "../../src/interfaces/IStandardExecutor.sol";
-import {SingleSignerValidation} from "../../src/plugins/validation/SingleSignerValidation.sol";
+import {SingleSignerValidation} from "../../src/modules/validation/SingleSignerValidation.sol";
import {AccountTestBase} from "../utils/AccountTestBase.sol";
import {TEST_DEFAULT_VALIDATION_ENTITY_ID} from "../utils/TestConstants.sol";
@@ -43,9 +43,9 @@ contract MultiValidationTest is AccountTestBase {
""
);
- PluginEntity[] memory validations = new PluginEntity[](2);
- validations[0] = PluginEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID);
- validations[1] = PluginEntityLib.pack(address(validator2), TEST_DEFAULT_VALIDATION_ENTITY_ID);
+ ModuleEntity[] memory validations = new ModuleEntity[](2);
+ validations[0] = ModuleEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID);
+ validations[1] = ModuleEntityLib.pack(address(validator2), TEST_DEFAULT_VALIDATION_ENTITY_ID);
bytes4[] memory selectors0 = account1.getSelectors(validations[0]);
bytes4[] memory selectors1 = account1.getSelectors(validations[1]);
@@ -72,7 +72,7 @@ contract MultiValidationTest is AccountTestBase {
account1.executeWithAuthorization(
abi.encodeCall(IStandardExecutor.execute, (address(0), 0, "")),
_encodeSignature(
- PluginEntityLib.pack(address(validator2), TEST_DEFAULT_VALIDATION_ENTITY_ID), GLOBAL_VALIDATION, ""
+ ModuleEntityLib.pack(address(validator2), TEST_DEFAULT_VALIDATION_ENTITY_ID), GLOBAL_VALIDATION, ""
)
);
@@ -80,7 +80,7 @@ contract MultiValidationTest is AccountTestBase {
account1.executeWithAuthorization(
abi.encodeCall(IStandardExecutor.execute, (address(0), 0, "")),
_encodeSignature(
- PluginEntityLib.pack(address(validator2), TEST_DEFAULT_VALIDATION_ENTITY_ID), GLOBAL_VALIDATION, ""
+ ModuleEntityLib.pack(address(validator2), TEST_DEFAULT_VALIDATION_ENTITY_ID), GLOBAL_VALIDATION, ""
)
);
}
@@ -106,7 +106,7 @@ contract MultiValidationTest is AccountTestBase {
bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(owner2Key, userOpHash.toEthSignedMessageHash());
userOp.signature = _encodeSignature(
- PluginEntityLib.pack(address(validator2), TEST_DEFAULT_VALIDATION_ENTITY_ID),
+ ModuleEntityLib.pack(address(validator2), TEST_DEFAULT_VALIDATION_ENTITY_ID),
GLOBAL_VALIDATION,
abi.encodePacked(r, s, v)
);
@@ -121,7 +121,7 @@ contract MultiValidationTest is AccountTestBase {
userOp.nonce = 1;
(v, r, s) = vm.sign(owner1Key, userOpHash.toEthSignedMessageHash());
userOp.signature = _encodeSignature(
- PluginEntityLib.pack(address(validator2), TEST_DEFAULT_VALIDATION_ENTITY_ID),
+ ModuleEntityLib.pack(address(validator2), TEST_DEFAULT_VALIDATION_ENTITY_ID),
GLOBAL_VALIDATION,
abi.encodePacked(r, s, v)
);
diff --git a/test/account/PerHookData.t.sol b/test/account/PerHookData.t.sol
index c4405d38..15cefbd9 100644
--- a/test/account/PerHookData.t.sol
+++ b/test/account/PerHookData.t.sol
@@ -6,23 +6,23 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntity, PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntity, ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {Counter} from "../mocks/Counter.sol";
-import {MockAccessControlHookPlugin} from "../mocks/plugins/MockAccessControlHookPlugin.sol";
+import {MockAccessControlHookModule} from "../mocks/modules/MockAccessControlHookModule.sol";
import {CustomValidationTestBase} from "../utils/CustomValidationTestBase.sol";
contract PerHookDataTest is CustomValidationTestBase {
using MessageHashUtils for bytes32;
- MockAccessControlHookPlugin internal _accessControlHookPlugin;
+ MockAccessControlHookModule internal _accessControlHookModule;
Counter internal _counter;
function setUp() public {
_counter = new Counter();
- _accessControlHookPlugin = new MockAccessControlHookPlugin();
+ _accessControlHookModule = new MockAccessControlHookModule();
_customValidationSetup();
}
@@ -217,8 +217,8 @@ contract PerHookDataTest is CustomValidationTestBase {
vm.expectRevert(
abi.encodeWithSelector(
UpgradeableModularAccount.PreRuntimeValidationHookFailed.selector,
- _accessControlHookPlugin,
- uint32(MockAccessControlHookPlugin.EntityId.PRE_VALIDATION_HOOK),
+ _accessControlHookModule,
+ uint32(MockAccessControlHookModule.EntityId.PRE_VALIDATION_HOOK),
abi.encodeWithSignature("Error(string)", "Proof doesn't match target")
)
);
@@ -236,8 +236,8 @@ contract PerHookDataTest is CustomValidationTestBase {
vm.expectRevert(
abi.encodeWithSelector(
UpgradeableModularAccount.PreRuntimeValidationHookFailed.selector,
- _accessControlHookPlugin,
- uint32(MockAccessControlHookPlugin.EntityId.PRE_VALIDATION_HOOK),
+ _accessControlHookModule,
+ uint32(MockAccessControlHookModule.EntityId.PRE_VALIDATION_HOOK),
abi.encodeWithSignature("Error(string)", "Proof doesn't match target")
)
);
@@ -278,8 +278,8 @@ contract PerHookDataTest is CustomValidationTestBase {
vm.expectRevert(
abi.encodeWithSelector(
UpgradeableModularAccount.PreRuntimeValidationHookFailed.selector,
- _accessControlHookPlugin,
- uint32(MockAccessControlHookPlugin.EntityId.PRE_VALIDATION_HOOK),
+ _accessControlHookModule,
+ uint32(MockAccessControlHookModule.EntityId.PRE_VALIDATION_HOOK),
abi.encodeWithSignature("Error(string)", "Target not allowed")
)
);
@@ -330,13 +330,13 @@ contract PerHookDataTest is CustomValidationTestBase {
internal
virtual
override
- returns (PluginEntity, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory)
+ returns (ModuleEntity, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory)
{
- PluginEntity accessControlHook = PluginEntityLib.pack(
- address(_accessControlHookPlugin), uint32(MockAccessControlHookPlugin.EntityId.PRE_VALIDATION_HOOK)
+ ModuleEntity accessControlHook = ModuleEntityLib.pack(
+ address(_accessControlHookModule), uint32(MockAccessControlHookModule.EntityId.PRE_VALIDATION_HOOK)
);
- PluginEntity[] memory preValidationHooks = new PluginEntity[](1);
+ ModuleEntity[] memory preValidationHooks = new ModuleEntity[](1);
preValidationHooks[0] = accessControlHook;
bytes[] memory preValidationHookData = new bytes[](1);
diff --git a/test/account/PermittedCallPermissions.t.sol b/test/account/PermittedCallPermissions.t.sol
index 607c50b4..1c378e9e 100644
--- a/test/account/PermittedCallPermissions.t.sol
+++ b/test/account/PermittedCallPermissions.t.sol
@@ -3,43 +3,43 @@ pragma solidity ^0.8.19;
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PermittedCallerPlugin} from "../mocks/plugins/PermittedCallMocks.sol";
-import {ResultCreatorPlugin} from "../mocks/plugins/ReturnDataPluginMocks.sol";
+import {PermittedCallerModule} from "../mocks/modules/PermittedCallMocks.sol";
+import {ResultCreatorModule} from "../mocks/modules/ReturnDataModuleMocks.sol";
import {AccountTestBase} from "../utils/AccountTestBase.sol";
contract PermittedCallPermissionsTest is AccountTestBase {
- ResultCreatorPlugin public resultCreatorPlugin;
+ ResultCreatorModule public resultCreatorModule;
- PermittedCallerPlugin public permittedCallerPlugin;
+ PermittedCallerModule public permittedCallerModule;
function setUp() public {
_transferOwnershipToTest();
- resultCreatorPlugin = new ResultCreatorPlugin();
+ resultCreatorModule = new ResultCreatorModule();
- // Initialize the permitted caller plugins, which will attempt to use the permissions system to authorize
+ // Initialize the permitted caller modules, which will attempt to use the permissions system to authorize
// calls.
- permittedCallerPlugin = new PermittedCallerPlugin();
+ permittedCallerModule = new PermittedCallerModule();
- // Add the result creator plugin to the account
- bytes32 resultCreatorManifestHash = keccak256(abi.encode(resultCreatorPlugin.pluginManifest()));
+ // Add the result creator module to the account
+ bytes32 resultCreatorManifestHash = keccak256(abi.encode(resultCreatorModule.moduleManifest()));
vm.prank(address(entryPoint));
- account1.installPlugin({
- plugin: address(resultCreatorPlugin),
+ account1.installModule({
+ module: address(resultCreatorModule),
manifestHash: resultCreatorManifestHash,
- pluginInstallData: ""
+ moduleInstallData: ""
});
- // Add the permitted caller plugin to the account
- bytes32 permittedCallerManifestHash = keccak256(abi.encode(permittedCallerPlugin.pluginManifest()));
+ // Add the permitted caller module to the account
+ bytes32 permittedCallerManifestHash = keccak256(abi.encode(permittedCallerModule.moduleManifest()));
vm.prank(address(entryPoint));
- account1.installPlugin({
- plugin: address(permittedCallerPlugin),
+ account1.installModule({
+ module: address(permittedCallerModule),
manifestHash: permittedCallerManifestHash,
- pluginInstallData: ""
+ moduleInstallData: ""
});
}
function test_permittedCall_Allowed() public {
- bytes memory result = PermittedCallerPlugin(address(account1)).usePermittedCallAllowed();
+ bytes memory result = PermittedCallerModule(address(account1)).usePermittedCallAllowed();
bytes32 actual = abi.decode(result, (bytes32));
assertEq(actual, keccak256("bar"));
@@ -48,9 +48,9 @@ contract PermittedCallPermissionsTest is AccountTestBase {
function test_permittedCall_NotAllowed() public {
vm.expectRevert(
abi.encodeWithSelector(
- UpgradeableModularAccount.ValidationFunctionMissing.selector, ResultCreatorPlugin.bar.selector
+ UpgradeableModularAccount.ValidationFunctionMissing.selector, ResultCreatorModule.bar.selector
)
);
- PermittedCallerPlugin(address(account1)).usePermittedCallNotAllowed();
+ PermittedCallerModule(address(account1)).usePermittedCallNotAllowed();
}
}
diff --git a/test/account/SelfCallAuthorization.t.sol b/test/account/SelfCallAuthorization.t.sol
index 743a0241..aae886eb 100644
--- a/test/account/SelfCallAuthorization.t.sol
+++ b/test/account/SelfCallAuthorization.t.sol
@@ -7,41 +7,41 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntity, PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntity, ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol";
import {Call, IStandardExecutor} from "../../src/interfaces/IStandardExecutor.sol";
-import {ComprehensivePlugin} from "../mocks/plugins/ComprehensivePlugin.sol";
+import {ComprehensiveModule} from "../mocks/modules/ComprehensiveModule.sol";
import {AccountTestBase} from "../utils/AccountTestBase.sol";
contract SelfCallAuthorizationTest is AccountTestBase {
- ComprehensivePlugin public comprehensivePlugin;
+ ComprehensiveModule public comprehensiveModule;
- PluginEntity public comprehensivePluginValidation;
+ ModuleEntity public comprehensiveModuleValidation;
function setUp() public {
- // install the comprehensive plugin to get new exec functions with different validations configured.
+ // install the comprehensive module to get new exec functions with different validations configured.
- comprehensivePlugin = new ComprehensivePlugin();
+ comprehensiveModule = new ComprehensiveModule();
- bytes32 manifestHash = keccak256(abi.encode(comprehensivePlugin.pluginManifest()));
+ bytes32 manifestHash = keccak256(abi.encode(comprehensiveModule.moduleManifest()));
vm.prank(address(entryPoint));
- account1.installPlugin(address(comprehensivePlugin), manifestHash, "");
+ account1.installModule(address(comprehensiveModule), manifestHash, "");
- comprehensivePluginValidation =
- PluginEntityLib.pack(address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.VALIDATION));
+ comprehensiveModuleValidation =
+ ModuleEntityLib.pack(address(comprehensiveModule), uint32(ComprehensiveModule.EntityId.VALIDATION));
}
function test_selfCallFails_userOp() public {
// Uses global validation
_runUserOp(
- abi.encodeCall(ComprehensivePlugin.foo, ()),
+ abi.encodeCall(ComprehensiveModule.foo, ()),
abi.encodeWithSelector(
IEntryPoint.FailedOpWithRevert.selector,
0,
"AA23 reverted",
abi.encodeWithSelector(
- UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensivePlugin.foo.selector
+ UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensiveModule.foo.selector
)
)
);
@@ -50,13 +50,13 @@ contract SelfCallAuthorizationTest is AccountTestBase {
function test_selfCallFails_execUserOp() public {
// Uses global validation
_runUserOp(
- abi.encodePacked(IAccountExecute.executeUserOp.selector, abi.encodeCall(ComprehensivePlugin.foo, ())),
+ abi.encodePacked(IAccountExecute.executeUserOp.selector, abi.encodeCall(ComprehensiveModule.foo, ())),
abi.encodeWithSelector(
IEntryPoint.FailedOpWithRevert.selector,
0,
"AA23 reverted",
abi.encodeWithSelector(
- UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensivePlugin.foo.selector
+ UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensiveModule.foo.selector
)
)
);
@@ -65,19 +65,19 @@ contract SelfCallAuthorizationTest is AccountTestBase {
function test_selfCallFails_runtime() public {
// Uses global validation
_runtimeCall(
- abi.encodeCall(ComprehensivePlugin.foo, ()),
+ abi.encodeCall(ComprehensiveModule.foo, ()),
abi.encodeWithSelector(
- UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensivePlugin.foo.selector
+ UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensiveModule.foo.selector
)
);
}
function test_selfCallPrivilegeEscalation_prevented_userOp() public {
- // Using global validation, self-call bypasses custom validation needed for ComprehensivePlugin.foo
+ // Using global validation, self-call bypasses custom validation needed for ComprehensiveModule.foo
_runUserOp(
abi.encodeCall(
UpgradeableModularAccount.execute,
- (address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()))
+ (address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()))
),
abi.encodeWithSelector(
IEntryPoint.FailedOpWithRevert.selector,
@@ -88,7 +88,7 @@ contract SelfCallAuthorizationTest is AccountTestBase {
);
Call[] memory calls = new Call[](1);
- calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
+ calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
_runUserOp(
abi.encodeCall(IStandardExecutor.executeBatch, (calls)),
@@ -97,20 +97,20 @@ contract SelfCallAuthorizationTest is AccountTestBase {
0,
"AA23 reverted",
abi.encodeWithSelector(
- UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensivePlugin.foo.selector
+ UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensiveModule.foo.selector
)
)
);
}
function test_selfCallPrivilegeEscalation_prevented_execUserOp() public {
- // Using global validation, self-call bypasses custom validation needed for ComprehensivePlugin.foo
+ // Using global validation, self-call bypasses custom validation needed for ComprehensiveModule.foo
_runUserOp(
abi.encodePacked(
IAccountExecute.executeUserOp.selector,
abi.encodeCall(
UpgradeableModularAccount.execute,
- (address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()))
+ (address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()))
)
),
abi.encodeWithSelector(
@@ -122,7 +122,7 @@ contract SelfCallAuthorizationTest is AccountTestBase {
);
Call[] memory calls = new Call[](1);
- calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
+ calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
_runUserOp(
abi.encodePacked(
@@ -133,29 +133,29 @@ contract SelfCallAuthorizationTest is AccountTestBase {
0,
"AA23 reverted",
abi.encodeWithSelector(
- UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensivePlugin.foo.selector
+ UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensiveModule.foo.selector
)
)
);
}
function test_selfCallPrivilegeEscalation_prevented_runtime() public {
- // Using global validation, self-call bypasses custom validation needed for ComprehensivePlugin.foo
+ // Using global validation, self-call bypasses custom validation needed for ComprehensiveModule.foo
_runtimeCall(
abi.encodeCall(
UpgradeableModularAccount.execute,
- (address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()))
+ (address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()))
),
abi.encodeWithSelector(UpgradeableModularAccount.SelfCallRecursionDepthExceeded.selector)
);
Call[] memory calls = new Call[](1);
- calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
+ calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
_runtimeExecBatchExpFail(
calls,
abi.encodeWithSelector(
- UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensivePlugin.foo.selector
+ UpgradeableModularAccount.ValidationFunctionMissing.selector, ComprehensiveModule.foo.selector
)
);
}
@@ -164,17 +164,17 @@ contract SelfCallAuthorizationTest is AccountTestBase {
_enableBatchValidation();
Call[] memory calls = new Call[](2);
- calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
- calls[1] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
+ calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
+ calls[1] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
- PackedUserOperation memory userOp = _generateUserOpWithComprehensivePluginValidation(
+ PackedUserOperation memory userOp = _generateUserOpWithComprehensiveModuleValidation(
abi.encodeCall(IStandardExecutor.executeBatch, (calls))
);
PackedUserOperation[] memory userOps = new PackedUserOperation[](1);
userOps[0] = userOp;
- vm.expectCall(address(comprehensivePlugin), abi.encodeCall(ComprehensivePlugin.foo, ()), 2);
+ vm.expectCall(address(comprehensiveModule), abi.encodeCall(ComprehensiveModule.foo, ()), 2);
entryPoint.handleOps(userOps, beneficiary);
}
@@ -182,10 +182,10 @@ contract SelfCallAuthorizationTest is AccountTestBase {
_enableBatchValidation();
Call[] memory calls = new Call[](2);
- calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
- calls[1] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
+ calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
+ calls[1] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
- PackedUserOperation memory userOp = _generateUserOpWithComprehensivePluginValidation(
+ PackedUserOperation memory userOp = _generateUserOpWithComprehensiveModuleValidation(
abi.encodePacked(
IAccountExecute.executeUserOp.selector, abi.encodeCall(IStandardExecutor.executeBatch, (calls))
)
@@ -194,7 +194,7 @@ contract SelfCallAuthorizationTest is AccountTestBase {
PackedUserOperation[] memory userOps = new PackedUserOperation[](1);
userOps[0] = userOp;
- vm.expectCall(address(comprehensivePlugin), abi.encodeCall(ComprehensivePlugin.foo, ()), 2);
+ vm.expectCall(address(comprehensiveModule), abi.encodeCall(ComprehensiveModule.foo, ()), 2);
entryPoint.handleOps(userOps, beneficiary);
}
@@ -202,13 +202,13 @@ contract SelfCallAuthorizationTest is AccountTestBase {
_enableBatchValidation();
Call[] memory calls = new Call[](2);
- calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
- calls[1] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
+ calls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
+ calls[1] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
- vm.expectCall(address(comprehensivePlugin), abi.encodeCall(ComprehensivePlugin.foo, ()), 2);
+ vm.expectCall(address(comprehensiveModule), abi.encodeCall(ComprehensiveModule.foo, ()), 2);
account1.executeWithAuthorization(
abi.encodeCall(IStandardExecutor.executeBatch, (calls)),
- _encodeSignature(comprehensivePluginValidation, SELECTOR_ASSOCIATED_VALIDATION, "")
+ _encodeSignature(comprehensiveModuleValidation, SELECTOR_ASSOCIATED_VALIDATION, "")
);
}
@@ -216,12 +216,12 @@ contract SelfCallAuthorizationTest is AccountTestBase {
_enableBatchValidation();
Call[] memory innerCalls = new Call[](1);
- innerCalls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
+ innerCalls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
Call[] memory outerCalls = new Call[](1);
outerCalls[0] = Call(address(account1), 0, abi.encodeCall(IStandardExecutor.executeBatch, (innerCalls)));
- PackedUserOperation memory userOp = _generateUserOpWithComprehensivePluginValidation(
+ PackedUserOperation memory userOp = _generateUserOpWithComprehensiveModuleValidation(
abi.encodeCall(IStandardExecutor.executeBatch, (outerCalls))
);
@@ -243,12 +243,12 @@ contract SelfCallAuthorizationTest is AccountTestBase {
_enableBatchValidation();
Call[] memory innerCalls = new Call[](1);
- innerCalls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
+ innerCalls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
Call[] memory outerCalls = new Call[](1);
outerCalls[0] = Call(address(account1), 0, abi.encodeCall(IStandardExecutor.executeBatch, (innerCalls)));
- PackedUserOperation memory userOp = _generateUserOpWithComprehensivePluginValidation(
+ PackedUserOperation memory userOp = _generateUserOpWithComprehensiveModuleValidation(
abi.encodePacked(
IAccountExecute.executeUserOp.selector,
abi.encodeCall(IStandardExecutor.executeBatch, (outerCalls))
@@ -273,7 +273,7 @@ contract SelfCallAuthorizationTest is AccountTestBase {
_enableBatchValidation();
Call[] memory innerCalls = new Call[](1);
- innerCalls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensivePlugin.foo, ()));
+ innerCalls[0] = Call(address(account1), 0, abi.encodeCall(ComprehensiveModule.foo, ()));
Call[] memory outerCalls = new Call[](1);
outerCalls[0] = Call(address(account1), 0, abi.encodeCall(IStandardExecutor.executeBatch, (innerCalls)));
@@ -281,12 +281,12 @@ contract SelfCallAuthorizationTest is AccountTestBase {
vm.expectRevert(abi.encodeWithSelector(UpgradeableModularAccount.SelfCallRecursionDepthExceeded.selector));
account1.executeWithAuthorization(
abi.encodeCall(IStandardExecutor.executeBatch, (outerCalls)),
- _encodeSignature(comprehensivePluginValidation, SELECTOR_ASSOCIATED_VALIDATION, "")
+ _encodeSignature(comprehensiveModuleValidation, SELECTOR_ASSOCIATED_VALIDATION, "")
);
}
function _enableBatchValidation() internal {
- // Extend ComprehensivePlugin's validation function to also validate `executeBatch`, to allow the
+ // Extend ComprehensiveModule's validation function to also validate `executeBatch`, to allow the
// self-call.
bytes4[] memory selectors = new bytes4[](1);
@@ -296,13 +296,13 @@ contract SelfCallAuthorizationTest is AccountTestBase {
account1.executeWithAuthorization(
abi.encodeCall(
UpgradeableModularAccount.installValidation,
- (ValidationConfigLib.pack(comprehensivePluginValidation, false, false), selectors, "", "", "")
+ (ValidationConfigLib.pack(comprehensiveModuleValidation, false, false), selectors, "", "", "")
),
_encodeSignature(_signerValidation, GLOBAL_VALIDATION, "")
);
}
- function _generateUserOpWithComprehensivePluginValidation(bytes memory callData)
+ function _generateUserOpWithComprehensiveModuleValidation(bytes memory callData)
internal
view
returns (PackedUserOperation memory)
@@ -318,9 +318,9 @@ contract SelfCallAuthorizationTest is AccountTestBase {
gasFees: _encodeGas(1, 1),
paymasterAndData: hex"",
signature: _encodeSignature(
- comprehensivePluginValidation,
+ comprehensiveModuleValidation,
SELECTOR_ASSOCIATED_VALIDATION,
- // Comprehensive plugin's validation function doesn't actually check anything, so we don't need to
+ // Comprehensive module's validation function doesn't actually check anything, so we don't need to
// sign anything.
""
)
diff --git a/test/account/UpgradeableModularAccount.t.sol b/test/account/UpgradeableModularAccount.t.sol
index 8b77332f..76a1c4f0 100644
--- a/test/account/UpgradeableModularAccount.t.sol
+++ b/test/account/UpgradeableModularAccount.t.sol
@@ -9,21 +9,21 @@ import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
-import {PluginManagerInternals} from "../../src/account/PluginManagerInternals.sol";
+import {ModuleManagerInternals} from "../../src/account/ModuleManagerInternals.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
import {IAccountLoupe} from "../../src/interfaces/IAccountLoupe.sol";
-import {PluginManifest} from "../../src/interfaces/IPlugin.sol";
-import {IPluginManager} from "../../src/interfaces/IPluginManager.sol";
+import {ModuleManifest} from "../../src/interfaces/IModule.sol";
+import {IModuleManager} from "../../src/interfaces/IModuleManager.sol";
import {Call} from "../../src/interfaces/IStandardExecutor.sol";
-import {TokenReceiverPlugin} from "../../src/plugins/TokenReceiverPlugin.sol";
-import {SingleSignerValidation} from "../../src/plugins/validation/SingleSignerValidation.sol";
+import {TokenReceiverModule} from "../../src/modules/TokenReceiverModule.sol";
+import {SingleSignerValidation} from "../../src/modules/validation/SingleSignerValidation.sol";
import {Counter} from "../mocks/Counter.sol";
-import {MockPlugin} from "../mocks/MockPlugin.sol";
-import {ComprehensivePlugin} from "../mocks/plugins/ComprehensivePlugin.sol";
+import {MockModule} from "../mocks/MockModule.sol";
+import {ComprehensiveModule} from "../mocks/modules/ComprehensiveModule.sol";
import {AccountTestBase} from "../utils/AccountTestBase.sol";
import {TEST_DEFAULT_VALIDATION_ENTITY_ID} from "../utils/TestConstants.sol";
@@ -31,7 +31,7 @@ contract UpgradeableModularAccountTest is AccountTestBase {
using ECDSA for bytes32;
using MessageHashUtils for bytes32;
- TokenReceiverPlugin public tokenReceiverPlugin;
+ TokenReceiverModule public tokenReceiverModule;
// A separate account and owner that isn't deployed yet, used to test initcode
address public owner2;
@@ -40,14 +40,14 @@ contract UpgradeableModularAccountTest is AccountTestBase {
address public ethRecipient;
Counter public counter;
- PluginManifest internal _manifest;
+ ModuleManifest internal _manifest;
- event PluginInstalled(address indexed plugin, bytes32 manifestHash);
- event PluginUninstalled(address indexed plugin, bool indexed callbacksSucceeded);
+ event ModuleInstalled(address indexed module, bytes32 manifestHash);
+ event ModuleUninstalled(address indexed module, bool indexed callbacksSucceeded);
event ReceivedCall(bytes msgData, uint256 msgValue);
function setUp() public {
- tokenReceiverPlugin = _deployTokenReceiverPlugin();
+ tokenReceiverModule = _deployTokenReceiverModule();
(owner2, owner2Key) = makeAddrAndKey("owner2");
@@ -236,163 +236,163 @@ contract UpgradeableModularAccountTest is AccountTestBase {
assertEq(ethRecipient.balance, 2 wei);
}
- function test_installPlugin() public {
+ function test_installModule() public {
vm.startPrank(address(entryPoint));
- bytes32 manifestHash = keccak256(abi.encode(tokenReceiverPlugin.pluginManifest()));
+ bytes32 manifestHash = keccak256(abi.encode(tokenReceiverModule.moduleManifest()));
vm.expectEmit(true, true, true, true);
- emit PluginInstalled(address(tokenReceiverPlugin), manifestHash);
- IPluginManager(account1).installPlugin({
- plugin: address(tokenReceiverPlugin),
+ emit ModuleInstalled(address(tokenReceiverModule), manifestHash);
+ IModuleManager(account1).installModule({
+ module: address(tokenReceiverModule),
manifestHash: manifestHash,
- pluginInstallData: abi.encode(uint48(1 days))
+ moduleInstallData: abi.encode(uint48(1 days))
});
- address[] memory plugins = IAccountLoupe(account1).getInstalledPlugins();
- assertEq(plugins.length, 1);
- assertEq(plugins[0], address(tokenReceiverPlugin));
+ address[] memory modules = IAccountLoupe(account1).getInstalledModules();
+ assertEq(modules.length, 1);
+ assertEq(modules[0], address(tokenReceiverModule));
}
- function test_installPlugin_PermittedCallSelectorNotInstalled() public {
+ function test_installModule_PermittedCallSelectorNotInstalled() public {
vm.startPrank(address(entryPoint));
- PluginManifest memory m;
+ ModuleManifest memory m;
- MockPlugin mockPluginWithBadPermittedExec = new MockPlugin(m);
- bytes32 manifestHash = keccak256(abi.encode(mockPluginWithBadPermittedExec.pluginManifest()));
+ MockModule mockModuleWithBadPermittedExec = new MockModule(m);
+ bytes32 manifestHash = keccak256(abi.encode(mockModuleWithBadPermittedExec.moduleManifest()));
- IPluginManager(account1).installPlugin({
- plugin: address(mockPluginWithBadPermittedExec),
+ IModuleManager(account1).installModule({
+ module: address(mockModuleWithBadPermittedExec),
manifestHash: manifestHash,
- pluginInstallData: ""
+ moduleInstallData: ""
});
}
- function test_installPlugin_invalidManifest() public {
+ function test_installModule_invalidManifest() public {
vm.startPrank(address(entryPoint));
- vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector));
- IPluginManager(account1).installPlugin({
- plugin: address(tokenReceiverPlugin),
+ vm.expectRevert(abi.encodeWithSelector(ModuleManagerInternals.InvalidModuleManifest.selector));
+ IModuleManager(account1).installModule({
+ module: address(tokenReceiverModule),
manifestHash: bytes32(0),
- pluginInstallData: abi.encode(uint48(1 days))
+ moduleInstallData: abi.encode(uint48(1 days))
});
}
- function test_installPlugin_interfaceNotSupported() public {
+ function test_installModule_interfaceNotSupported() public {
vm.startPrank(address(entryPoint));
- address badPlugin = address(1);
+ address badModule = address(1);
vm.expectRevert(
- abi.encodeWithSelector(PluginManagerInternals.PluginInterfaceNotSupported.selector, address(badPlugin))
+ abi.encodeWithSelector(ModuleManagerInternals.ModuleInterfaceNotSupported.selector, address(badModule))
);
- IPluginManager(account1).installPlugin({
- plugin: address(badPlugin),
+ IModuleManager(account1).installModule({
+ module: address(badModule),
manifestHash: bytes32(0),
- pluginInstallData: ""
+ moduleInstallData: ""
});
}
- function test_installPlugin_alreadyInstalled() public {
+ function test_installModule_alreadyInstalled() public {
vm.startPrank(address(entryPoint));
- bytes32 manifestHash = keccak256(abi.encode(tokenReceiverPlugin.pluginManifest()));
- IPluginManager(account1).installPlugin({
- plugin: address(tokenReceiverPlugin),
+ bytes32 manifestHash = keccak256(abi.encode(tokenReceiverModule.moduleManifest()));
+ IModuleManager(account1).installModule({
+ module: address(tokenReceiverModule),
manifestHash: manifestHash,
- pluginInstallData: abi.encode(uint48(1 days))
+ moduleInstallData: abi.encode(uint48(1 days))
});
vm.expectRevert(
abi.encodeWithSelector(
- PluginManagerInternals.PluginAlreadyInstalled.selector, address(tokenReceiverPlugin)
+ ModuleManagerInternals.ModuleAlreadyInstalled.selector, address(tokenReceiverModule)
)
);
- IPluginManager(account1).installPlugin({
- plugin: address(tokenReceiverPlugin),
+ IModuleManager(account1).installModule({
+ module: address(tokenReceiverModule),
manifestHash: manifestHash,
- pluginInstallData: abi.encode(uint48(1 days))
+ moduleInstallData: abi.encode(uint48(1 days))
});
}
- function test_uninstallPlugin_default() public {
+ function test_uninstallModule_default() public {
vm.startPrank(address(entryPoint));
- ComprehensivePlugin plugin = new ComprehensivePlugin();
- bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest()));
- IPluginManager(account1).installPlugin({
- plugin: address(plugin),
+ ComprehensiveModule module = new ComprehensiveModule();
+ bytes32 manifestHash = keccak256(abi.encode(module.moduleManifest()));
+ IModuleManager(account1).installModule({
+ module: address(module),
manifestHash: manifestHash,
- pluginInstallData: ""
+ moduleInstallData: ""
});
vm.expectEmit(true, true, true, true);
- emit PluginUninstalled(address(plugin), true);
- IPluginManager(account1).uninstallPlugin({plugin: address(plugin), config: "", pluginUninstallData: ""});
- address[] memory plugins = IAccountLoupe(account1).getInstalledPlugins();
- assertEq(plugins.length, 0);
+ emit ModuleUninstalled(address(module), true);
+ IModuleManager(account1).uninstallModule({module: address(module), config: "", moduleUninstallData: ""});
+ address[] memory modules = IAccountLoupe(account1).getInstalledModules();
+ assertEq(modules.length, 0);
}
- function test_uninstallPlugin_manifestParameter() public {
+ function test_uninstallModule_manifestParameter() public {
vm.startPrank(address(entryPoint));
- ComprehensivePlugin plugin = new ComprehensivePlugin();
- bytes memory serializedManifest = abi.encode(plugin.pluginManifest());
+ ComprehensiveModule module = new ComprehensiveModule();
+ bytes memory serializedManifest = abi.encode(module.moduleManifest());
bytes32 manifestHash = keccak256(serializedManifest);
- IPluginManager(account1).installPlugin({
- plugin: address(plugin),
+ IModuleManager(account1).installModule({
+ module: address(module),
manifestHash: manifestHash,
- pluginInstallData: ""
+ moduleInstallData: ""
});
vm.expectEmit(true, true, true, true);
- emit PluginUninstalled(address(plugin), true);
- IPluginManager(account1).uninstallPlugin({
- plugin: address(plugin),
+ emit ModuleUninstalled(address(module), true);
+ IModuleManager(account1).uninstallModule({
+ module: address(module),
config: serializedManifest,
- pluginUninstallData: ""
+ moduleUninstallData: ""
});
- address[] memory plugins = IAccountLoupe(account1).getInstalledPlugins();
- assertEq(plugins.length, 0);
+ address[] memory modules = IAccountLoupe(account1).getInstalledModules();
+ assertEq(modules.length, 0);
}
- function test_uninstallPlugin_invalidManifestFails() public {
+ function test_uninstallModule_invalidManifestFails() public {
vm.startPrank(address(entryPoint));
- ComprehensivePlugin plugin = new ComprehensivePlugin();
- bytes memory serializedManifest = abi.encode(plugin.pluginManifest());
+ ComprehensiveModule module = new ComprehensiveModule();
+ bytes memory serializedManifest = abi.encode(module.moduleManifest());
bytes32 manifestHash = keccak256(serializedManifest);
- IPluginManager(account1).installPlugin({
- plugin: address(plugin),
+ IModuleManager(account1).installModule({
+ module: address(module),
manifestHash: manifestHash,
- pluginInstallData: ""
+ moduleInstallData: ""
});
// Attempt to uninstall with a blank _manifest
- PluginManifest memory blankManifest;
+ ModuleManifest memory blankManifest;
- vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector));
- IPluginManager(account1).uninstallPlugin({
- plugin: address(plugin),
+ vm.expectRevert(abi.encodeWithSelector(ModuleManagerInternals.InvalidModuleManifest.selector));
+ IModuleManager(account1).uninstallModule({
+ module: address(module),
config: abi.encode(blankManifest),
- pluginUninstallData: ""
+ moduleUninstallData: ""
});
- address[] memory plugins = IAccountLoupe(account1).getInstalledPlugins();
- assertEq(plugins.length, 1);
- assertEq(plugins[0], address(plugin));
+ address[] memory modules = IAccountLoupe(account1).getInstalledModules();
+ assertEq(modules.length, 1);
+ assertEq(modules[0], address(module));
}
- function _installPluginWithExecHooks() internal returns (MockPlugin plugin) {
+ function _installModuleWithExecHooks() internal returns (MockModule module) {
vm.startPrank(address(entryPoint));
- plugin = new MockPlugin(_manifest);
- bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest()));
+ module = new MockModule(_manifest);
+ bytes32 manifestHash = keccak256(abi.encode(module.moduleManifest()));
- IPluginManager(account1).installPlugin({
- plugin: address(plugin),
+ IModuleManager(account1).installModule({
+ module: address(module),
manifestHash: manifestHash,
- pluginInstallData: ""
+ moduleInstallData: ""
});
vm.stopPrank();
diff --git a/test/account/ValidationIntersection.t.sol b/test/account/ValidationIntersection.t.sol
index 3bdaa1b6..82a8fa7f 100644
--- a/test/account/ValidationIntersection.t.sol
+++ b/test/account/ValidationIntersection.t.sol
@@ -4,65 +4,65 @@ pragma solidity ^0.8.19;
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntity, PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntity, ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol";
import {
- MockBaseUserOpValidationPlugin,
- MockUserOpValidation1HookPlugin,
- MockUserOpValidation2HookPlugin,
- MockUserOpValidationPlugin
-} from "../mocks/plugins/ValidationPluginMocks.sol";
+ MockBaseUserOpValidationModule,
+ MockUserOpValidation1HookModule,
+ MockUserOpValidation2HookModule,
+ MockUserOpValidationModule
+} from "../mocks/modules/ValidationModuleMocks.sol";
import {AccountTestBase} from "../utils/AccountTestBase.sol";
contract ValidationIntersectionTest is AccountTestBase {
uint256 internal constant _SIG_VALIDATION_FAILED = 1;
- MockUserOpValidationPlugin public noHookPlugin;
- MockUserOpValidation1HookPlugin public oneHookPlugin;
- MockUserOpValidation2HookPlugin public twoHookPlugin;
+ MockUserOpValidationModule public noHookModule;
+ MockUserOpValidation1HookModule public oneHookModule;
+ MockUserOpValidation2HookModule public twoHookModule;
- PluginEntity public noHookValidation;
- PluginEntity public oneHookValidation;
- PluginEntity public twoHookValidation;
+ ModuleEntity public noHookValidation;
+ ModuleEntity public oneHookValidation;
+ ModuleEntity public twoHookValidation;
function setUp() public {
- noHookPlugin = new MockUserOpValidationPlugin();
- oneHookPlugin = new MockUserOpValidation1HookPlugin();
- twoHookPlugin = new MockUserOpValidation2HookPlugin();
+ noHookModule = new MockUserOpValidationModule();
+ oneHookModule = new MockUserOpValidation1HookModule();
+ twoHookModule = new MockUserOpValidation2HookModule();
- noHookValidation = PluginEntityLib.pack({
- addr: address(noHookPlugin),
- entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.USER_OP_VALIDATION)
+ noHookValidation = ModuleEntityLib.pack({
+ addr: address(noHookModule),
+ entityId: uint32(MockBaseUserOpValidationModule.EntityId.USER_OP_VALIDATION)
});
- oneHookValidation = PluginEntityLib.pack({
- addr: address(oneHookPlugin),
- entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.USER_OP_VALIDATION)
+ oneHookValidation = ModuleEntityLib.pack({
+ addr: address(oneHookModule),
+ entityId: uint32(MockBaseUserOpValidationModule.EntityId.USER_OP_VALIDATION)
});
- twoHookValidation = PluginEntityLib.pack({
- addr: address(twoHookPlugin),
- entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.USER_OP_VALIDATION)
+ twoHookValidation = ModuleEntityLib.pack({
+ addr: address(twoHookModule),
+ entityId: uint32(MockBaseUserOpValidationModule.EntityId.USER_OP_VALIDATION)
});
vm.startPrank(address(entryPoint));
- account1.installPlugin({
- plugin: address(noHookPlugin),
- manifestHash: keccak256(abi.encode(noHookPlugin.pluginManifest())),
- pluginInstallData: ""
+ account1.installModule({
+ module: address(noHookModule),
+ manifestHash: keccak256(abi.encode(noHookModule.moduleManifest())),
+ moduleInstallData: ""
});
- account1.installPlugin({
- plugin: address(oneHookPlugin),
- manifestHash: keccak256(abi.encode(oneHookPlugin.pluginManifest())),
- pluginInstallData: ""
+ account1.installModule({
+ module: address(oneHookModule),
+ manifestHash: keccak256(abi.encode(oneHookModule.moduleManifest())),
+ moduleInstallData: ""
});
// TODO: change with new install flow
// temporary fix to add the pre-validation hook
- PluginEntity[] memory preValidationHooks = new PluginEntity[](1);
- preValidationHooks[0] = PluginEntityLib.pack({
- addr: address(oneHookPlugin),
- entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.PRE_VALIDATION_HOOK_1)
+ ModuleEntity[] memory preValidationHooks = new ModuleEntity[](1);
+ preValidationHooks[0] = ModuleEntityLib.pack({
+ addr: address(oneHookModule),
+ entityId: uint32(MockBaseUserOpValidationModule.EntityId.PRE_VALIDATION_HOOK_1)
});
bytes[] memory installDatas = new bytes[](1);
account1.installValidation(
@@ -72,20 +72,20 @@ contract ValidationIntersectionTest is AccountTestBase {
abi.encode(preValidationHooks, installDatas),
bytes("")
);
- account1.installPlugin({
- plugin: address(twoHookPlugin),
- manifestHash: keccak256(abi.encode(twoHookPlugin.pluginManifest())),
- pluginInstallData: ""
+ account1.installModule({
+ module: address(twoHookModule),
+ manifestHash: keccak256(abi.encode(twoHookModule.moduleManifest())),
+ moduleInstallData: ""
});
// temporary fix to add the pre-validation hook
- preValidationHooks = new PluginEntity[](2);
- preValidationHooks[0] = PluginEntityLib.pack({
- addr: address(twoHookPlugin),
- entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.PRE_VALIDATION_HOOK_1)
+ preValidationHooks = new ModuleEntity[](2);
+ preValidationHooks[0] = ModuleEntityLib.pack({
+ addr: address(twoHookModule),
+ entityId: uint32(MockBaseUserOpValidationModule.EntityId.PRE_VALIDATION_HOOK_1)
});
- preValidationHooks[1] = PluginEntityLib.pack({
- addr: address(twoHookPlugin),
- entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.PRE_VALIDATION_HOOK_2)
+ preValidationHooks[1] = ModuleEntityLib.pack({
+ addr: address(twoHookModule),
+ entityId: uint32(MockBaseUserOpValidationModule.EntityId.PRE_VALIDATION_HOOK_2)
});
installDatas = new bytes[](2);
account1.installValidation(
@@ -99,10 +99,10 @@ contract ValidationIntersectionTest is AccountTestBase {
}
function testFuzz_validationIntersect_single(uint256 validationData) public {
- noHookPlugin.setValidationData(validationData);
+ noHookModule.setValidationData(validationData);
PackedUserOperation memory userOp;
- userOp.callData = bytes.concat(noHookPlugin.foo.selector);
+ userOp.callData = bytes.concat(noHookModule.foo.selector);
userOp.signature = _encodeSignature(noHookValidation, SELECTOR_ASSOCIATED_VALIDATION, "");
bytes32 uoHash = entryPoint.getUserOpHash(userOp);
@@ -113,13 +113,13 @@ contract ValidationIntersectionTest is AccountTestBase {
}
function test_validationIntersect_authorizer_sigfail_validationFunction() public {
- oneHookPlugin.setValidationData(
+ oneHookModule.setValidationData(
_SIG_VALIDATION_FAILED,
0 // returns OK
);
PackedUserOperation memory userOp;
- userOp.callData = bytes.concat(oneHookPlugin.bar.selector);
+ userOp.callData = bytes.concat(oneHookModule.bar.selector);
userOp.signature = _encodeSignature(oneHookValidation, SELECTOR_ASSOCIATED_VALIDATION, "");
bytes32 uoHash = entryPoint.getUserOpHash(userOp);
@@ -131,13 +131,13 @@ contract ValidationIntersectionTest is AccountTestBase {
}
function test_validationIntersect_authorizer_sigfail_hook() public {
- oneHookPlugin.setValidationData(
+ oneHookModule.setValidationData(
0, // returns OK
_SIG_VALIDATION_FAILED
);
PackedUserOperation memory userOp;
- userOp.callData = bytes.concat(oneHookPlugin.bar.selector);
+ userOp.callData = bytes.concat(oneHookModule.bar.selector);
userOp.signature = _encodeSignature(oneHookValidation, SELECTOR_ASSOCIATED_VALIDATION, "");
bytes32 uoHash = entryPoint.getUserOpHash(userOp);
@@ -155,12 +155,12 @@ contract ValidationIntersectionTest is AccountTestBase {
uint48 start2 = uint48(15);
uint48 end2 = uint48(25);
- oneHookPlugin.setValidationData(
+ oneHookModule.setValidationData(
_packValidationRes(address(0), start1, end1), _packValidationRes(address(0), start2, end2)
);
PackedUserOperation memory userOp;
- userOp.callData = bytes.concat(oneHookPlugin.bar.selector);
+ userOp.callData = bytes.concat(oneHookModule.bar.selector);
userOp.signature = _encodeSignature(oneHookValidation, SELECTOR_ASSOCIATED_VALIDATION, "");
bytes32 uoHash = entryPoint.getUserOpHash(userOp);
@@ -177,12 +177,12 @@ contract ValidationIntersectionTest is AccountTestBase {
uint48 start2 = uint48(15);
uint48 end2 = uint48(25);
- oneHookPlugin.setValidationData(
+ oneHookModule.setValidationData(
_packValidationRes(address(0), start2, end2), _packValidationRes(address(0), start1, end1)
);
PackedUserOperation memory userOp;
- userOp.callData = bytes.concat(oneHookPlugin.bar.selector);
+ userOp.callData = bytes.concat(oneHookModule.bar.selector);
userOp.signature = _encodeSignature(oneHookValidation, SELECTOR_ASSOCIATED_VALIDATION, "");
bytes32 uoHash = entryPoint.getUserOpHash(userOp);
@@ -195,14 +195,14 @@ contract ValidationIntersectionTest is AccountTestBase {
function test_validationIntersect_revert_unexpectedAuthorizer() public {
address badAuthorizer = makeAddr("badAuthorizer");
- oneHookPlugin.setValidationData(
+ oneHookModule.setValidationData(
0, // returns OK
uint256(uint160(badAuthorizer)) // returns an aggregator, which preValidation hooks are not allowed to
// do.
);
PackedUserOperation memory userOp;
- userOp.callData = bytes.concat(oneHookPlugin.bar.selector);
+ userOp.callData = bytes.concat(oneHookModule.bar.selector);
userOp.signature = _encodeSignature(oneHookValidation, SELECTOR_ASSOCIATED_VALIDATION, "");
bytes32 uoHash = entryPoint.getUserOpHash(userOp);
@@ -210,8 +210,8 @@ contract ValidationIntersectionTest is AccountTestBase {
vm.expectRevert(
abi.encodeWithSelector(
UpgradeableModularAccount.UnexpectedAggregator.selector,
- address(oneHookPlugin),
- MockBaseUserOpValidationPlugin.EntityId.PRE_VALIDATION_HOOK_1,
+ address(oneHookModule),
+ MockBaseUserOpValidationModule.EntityId.PRE_VALIDATION_HOOK_1,
badAuthorizer
)
);
@@ -221,13 +221,13 @@ contract ValidationIntersectionTest is AccountTestBase {
function test_validationIntersect_validAuthorizer() public {
address goodAuthorizer = makeAddr("goodAuthorizer");
- oneHookPlugin.setValidationData(
+ oneHookModule.setValidationData(
uint256(uint160(goodAuthorizer)), // returns a valid aggregator
0 // returns OK
);
PackedUserOperation memory userOp;
- userOp.callData = bytes.concat(oneHookPlugin.bar.selector);
+ userOp.callData = bytes.concat(oneHookModule.bar.selector);
userOp.signature = _encodeSignature(oneHookValidation, SELECTOR_ASSOCIATED_VALIDATION, "");
bytes32 uoHash = entryPoint.getUserOpHash(userOp);
@@ -246,12 +246,12 @@ contract ValidationIntersectionTest is AccountTestBase {
address goodAuthorizer = makeAddr("goodAuthorizer");
- oneHookPlugin.setValidationData(
+ oneHookModule.setValidationData(
_packValidationRes(goodAuthorizer, start1, end1), _packValidationRes(address(0), start2, end2)
);
PackedUserOperation memory userOp;
- userOp.callData = bytes.concat(oneHookPlugin.bar.selector);
+ userOp.callData = bytes.concat(oneHookModule.bar.selector);
userOp.signature = _encodeSignature(oneHookValidation, SELECTOR_ASSOCIATED_VALIDATION, "");
bytes32 uoHash = entryPoint.getUserOpHash(userOp);
@@ -268,14 +268,14 @@ contract ValidationIntersectionTest is AccountTestBase {
uint48 start2 = uint48(15);
uint48 end2 = uint48(25);
- twoHookPlugin.setValidationData(
+ twoHookModule.setValidationData(
0, // returns OK
_packValidationRes(address(0), start1, end1),
_packValidationRes(address(0), start2, end2)
);
PackedUserOperation memory userOp;
- userOp.callData = bytes.concat(twoHookPlugin.baz.selector);
+ userOp.callData = bytes.concat(twoHookModule.baz.selector);
userOp.signature = _encodeSignature(twoHookValidation, SELECTOR_ASSOCIATED_VALIDATION, "");
bytes32 uoHash = entryPoint.getUserOpHash(userOp);
@@ -286,14 +286,14 @@ contract ValidationIntersectionTest is AccountTestBase {
}
function test_validationIntersect_multiplePreValidationHooksSigFail() public {
- twoHookPlugin.setValidationData(
+ twoHookModule.setValidationData(
0, // returns OK
0, // returns OK
_SIG_VALIDATION_FAILED
);
PackedUserOperation memory userOp;
- userOp.callData = bytes.concat(twoHookPlugin.baz.selector);
+ userOp.callData = bytes.concat(twoHookModule.baz.selector);
userOp.signature = _encodeSignature(twoHookValidation, SELECTOR_ASSOCIATED_VALIDATION, "");
bytes32 uoHash = entryPoint.getUserOpHash(userOp);
diff --git a/test/libraries/KnowSelectors.t.sol b/test/libraries/KnowSelectors.t.sol
index 7ce0910d..48bd17e9 100644
--- a/test/libraries/KnowSelectors.t.sol
+++ b/test/libraries/KnowSelectors.t.sol
@@ -6,7 +6,7 @@ import {IPaymaster} from "@eth-infinitism/account-abstraction/interfaces/IPaymas
import {Test} from "forge-std/Test.sol";
import {KnownSelectors} from "../../src/helpers/KnownSelectors.sol";
-import {IPlugin} from "../../src/interfaces/IPlugin.sol";
+import {IModule} from "../../src/interfaces/IModule.sol";
contract KnownSelectorsTest is Test {
function test_isNativeFunction() public {
@@ -17,7 +17,7 @@ contract KnownSelectorsTest is Test {
assertTrue(KnownSelectors.isErc4337Function(IPaymaster.validatePaymasterUserOp.selector));
}
- function test_isIPluginFunction() public {
- assertTrue(KnownSelectors.isIPluginFunction(IPlugin.pluginMetadata.selector));
+ function test_isIModuleFunction() public {
+ assertTrue(KnownSelectors.isIModuleFunction(IModule.moduleMetadata.selector));
}
}
diff --git a/test/libraries/PluginEntityLib.t.sol b/test/libraries/ModuleEntityLib.t.sol
similarity index 56%
rename from test/libraries/PluginEntityLib.t.sol
rename to test/libraries/ModuleEntityLib.t.sol
index c93e1b61..205e53b9 100644
--- a/test/libraries/PluginEntityLib.t.sol
+++ b/test/libraries/ModuleEntityLib.t.sol
@@ -3,29 +3,29 @@ pragma solidity ^0.8.19;
import {Test} from "forge-std/Test.sol";
-import {PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
-import {PluginEntity} from "../../src/interfaces/IPluginManager.sol";
+import {ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
+import {ModuleEntity} from "../../src/interfaces/IModuleManager.sol";
-contract PluginEntityLibTest is Test {
- using PluginEntityLib for PluginEntity;
+contract ModuleEntityLibTest is Test {
+ using ModuleEntityLib for ModuleEntity;
- function testFuzz_pluginEntity_packing(address addr, uint32 entityId) public {
+ function testFuzz_moduleEntity_packing(address addr, uint32 entityId) public {
// console.log("addr: ", addr);
// console.log("entityId: ", vm.toString(entityId));
- PluginEntity fr = PluginEntityLib.pack(addr, entityId);
- // console.log("packed: ", vm.toString(PluginEntity.unwrap(fr)));
- (address addr2, uint32 entityId2) = PluginEntityLib.unpack(fr);
+ ModuleEntity fr = ModuleEntityLib.pack(addr, entityId);
+ // console.log("packed: ", vm.toString(ModuleEntity.unwrap(fr)));
+ (address addr2, uint32 entityId2) = ModuleEntityLib.unpack(fr);
// console.log("addr2: ", addr2);
// console.log("entityId2: ", vm.toString(entityId2));
assertEq(addr, addr2);
assertEq(entityId, entityId2);
}
- function testFuzz_pluginEntity_operators(PluginEntity a, PluginEntity b) public {
+ function testFuzz_moduleEntity_operators(ModuleEntity a, ModuleEntity b) public {
assertTrue(a.eq(a));
assertTrue(b.eq(b));
- if (PluginEntity.unwrap(a) == PluginEntity.unwrap(b)) {
+ if (ModuleEntity.unwrap(a) == ModuleEntity.unwrap(b)) {
assertTrue(a.eq(b));
assertTrue(b.eq(a));
assertFalse(a.notEq(b));
diff --git a/test/mocks/MockPlugin.sol b/test/mocks/MockModule.sol
similarity index 75%
rename from test/mocks/MockPlugin.sol
rename to test/mocks/MockModule.sol
index ef79c018..c6866bd4 100644
--- a/test/mocks/MockPlugin.sol
+++ b/test/mocks/MockModule.sol
@@ -4,10 +4,10 @@ pragma solidity ^0.8.19;
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {IExecutionHook} from "../../src/interfaces/IExecutionHook.sol";
-import {IPlugin, PluginManifest, PluginMetadata} from "../../src/interfaces/IPlugin.sol";
+import {IModule, ModuleManifest, ModuleMetadata} from "../../src/interfaces/IModule.sol";
import {IValidation} from "../../src/interfaces/IValidation.sol";
-contract MockPlugin is ERC165 {
+contract MockModule is ERC165 {
// It's super inefficient to hold the entire abi-encoded manifest in storage, but this is fine since it's
// just a mock. Note that the reason we do this is to allow copying the entire contents of the manifest
// into storage in a single line, since solidity fails to compile with memory -> storage copying of nested
@@ -17,41 +17,41 @@ contract MockPlugin is ERC165 {
// struct ManifestAssociatedFunction memory[] memory to storage not yet supported.
bytes internal _manifest;
- string internal constant _NAME = "Mock Plugin Modifiable";
+ string internal constant _NAME = "Mock Module Modifiable";
string internal constant _VERSION = "1.0.0";
string internal constant _AUTHOR = "ERC-6900 Authors";
event ReceivedCall(bytes msgData, uint256 msgValue);
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
- // ┃ Plugin interface functions ┃
+ // ┃ Module interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
- constructor(PluginManifest memory _pluginManifest) {
- _manifest = abi.encode(_pluginManifest);
+ constructor(ModuleManifest memory _moduleManifest) {
+ _manifest = abi.encode(_moduleManifest);
}
- function _getManifest() internal view returns (PluginManifest memory) {
- PluginManifest memory m = abi.decode(_manifest, (PluginManifest));
+ function _getManifest() internal view returns (ModuleManifest memory) {
+ ModuleManifest memory m = abi.decode(_manifest, (ModuleManifest));
return m;
}
- function _castToPure(function() internal view returns (PluginManifest memory) fnIn)
+ function _castToPure(function() internal view returns (ModuleManifest memory) fnIn)
internal
pure
- returns (function() internal pure returns (PluginManifest memory) fnOut)
+ returns (function() internal pure returns (ModuleManifest memory) fnOut)
{
assembly ("memory-safe") {
fnOut := fnIn
}
}
- function pluginManifest() external pure returns (PluginManifest memory) {
+ function moduleManifest() external pure returns (ModuleManifest memory) {
return _castToPure(_getManifest)();
}
- function pluginMetadata() external pure returns (PluginMetadata memory) {
- PluginMetadata memory metadata;
+ function moduleMetadata() external pure returns (ModuleMetadata memory) {
+ ModuleMetadata memory metadata;
metadata.name = _NAME;
metadata.version = _VERSION;
metadata.author = _AUTHOR;
@@ -65,14 +65,14 @@ contract MockPlugin is ERC165 {
///
/// This function call must use less than 30 000 gas.
///
- /// Supporting the IPlugin interface is a requirement for plugin installation. This is also used
+ /// Supporting the IModule interface is a requirement for module installation. This is also used
/// by the modular account to prevent standard execution functions `execute` and `executeBatch` from
- /// making calls to plugins.
+ /// making calls to modules.
/// @param interfaceId The interface ID to check for support.
/// @return True if the contract supports `interfaceId`.
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
- return interfaceId == type(IPlugin).interfaceId || super.supportsInterface(interfaceId);
+ return interfaceId == type(IModule).interfaceId || super.supportsInterface(interfaceId);
}
receive() external payable {}
diff --git a/test/mocks/SingleSignerFactoryFixture.sol b/test/mocks/SingleSignerFactoryFixture.sol
index b751d440..98dfc0b8 100644
--- a/test/mocks/SingleSignerFactoryFixture.sol
+++ b/test/mocks/SingleSignerFactoryFixture.sol
@@ -7,7 +7,7 @@ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol";
-import {SingleSignerValidation} from "../../src/plugins/validation/SingleSignerValidation.sol";
+import {SingleSignerValidation} from "../../src/modules/validation/SingleSignerValidation.sol";
import {OptimizedTest} from "../utils/OptimizedTest.sol";
import {TEST_DEFAULT_VALIDATION_ENTITY_ID} from "../utils/TestConstants.sol";
@@ -45,17 +45,17 @@ contract SingleSignerFactoryFixture is OptimizedTest {
// short circuit if exists
if (addr.code.length == 0) {
- bytes memory pluginInstallData = abi.encode(TEST_DEFAULT_VALIDATION_ENTITY_ID, owner);
+ bytes memory moduleInstallData = abi.encode(TEST_DEFAULT_VALIDATION_ENTITY_ID, owner);
// not necessary to check return addr since next call will fail if so
new ERC1967Proxy{salt: getSalt(owner, salt)}(address(accountImplementation), "");
- // point proxy to actual implementation and init plugins
+ // point proxy to actual implementation and init modules
UpgradeableModularAccount(payable(addr)).initializeWithValidation(
ValidationConfigLib.pack(
address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID, true, true
),
new bytes4[](0),
- pluginInstallData,
+ moduleInstallData,
"",
""
);
diff --git a/test/mocks/plugins/ComprehensivePlugin.sol b/test/mocks/modules/ComprehensiveModule.sol
similarity index 89%
rename from test/mocks/plugins/ComprehensivePlugin.sol
rename to test/mocks/modules/ComprehensiveModule.sol
index e4233cf2..bb73b5db 100644
--- a/test/mocks/plugins/ComprehensivePlugin.sol
+++ b/test/mocks/modules/ComprehensiveModule.sol
@@ -8,16 +8,16 @@ import {
ManifestExecutionFunction,
ManifestExecutionHook,
ManifestValidation,
- PluginManifest,
- PluginMetadata
-} from "../../../src/interfaces/IPlugin.sol";
-import {PluginManifest} from "../../../src/interfaces/IPlugin.sol";
+ ModuleManifest,
+ ModuleMetadata
+} from "../../../src/interfaces/IModule.sol";
+import {ModuleManifest} from "../../../src/interfaces/IModule.sol";
import {IValidation} from "../../../src/interfaces/IValidation.sol";
import {IValidationHook} from "../../../src/interfaces/IValidationHook.sol";
-import {BasePlugin} from "../../../src/plugins/BasePlugin.sol";
+import {BaseModule} from "../../../src/modules/BaseModule.sol";
-contract ComprehensivePlugin is IValidation, IValidationHook, IExecutionHook, BasePlugin {
+contract ComprehensiveModule is IValidation, IValidationHook, IExecutionHook, BaseModule {
enum EntityId {
PRE_VALIDATION_HOOK_1,
PRE_VALIDATION_HOOK_2,
@@ -28,7 +28,7 @@ contract ComprehensivePlugin is IValidation, IValidationHook, IExecutionHook, Ba
SIG_VALIDATION
}
- string internal constant _NAME = "Comprehensive Plugin";
+ string internal constant _NAME = "Comprehensive Module";
string internal constant _VERSION = "1.0.0";
string internal constant _AUTHOR = "ERC-6900 Authors";
@@ -39,7 +39,7 @@ contract ComprehensivePlugin is IValidation, IValidationHook, IExecutionHook, Ba
function foo() external {}
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
- // ┃ Plugin interface functions ┃
+ // ┃ Module interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
function onInstall(bytes calldata) external override {}
@@ -130,8 +130,8 @@ contract ComprehensivePlugin is IValidation, IValidationHook, IExecutionHook, Ba
revert NotImplemented();
}
- function pluginManifest() external pure override returns (PluginManifest memory) {
- PluginManifest memory manifest;
+ function moduleManifest() external pure override returns (ModuleManifest memory) {
+ ModuleManifest memory manifest;
manifest.executionFunctions = new ManifestExecutionFunction[](1);
manifest.executionFunctions[0] = ManifestExecutionFunction({
@@ -174,8 +174,8 @@ contract ComprehensivePlugin is IValidation, IValidationHook, IExecutionHook, Ba
return manifest;
}
- function pluginMetadata() external pure virtual override returns (PluginMetadata memory) {
- PluginMetadata memory metadata;
+ function moduleMetadata() external pure virtual override returns (ModuleMetadata memory) {
+ ModuleMetadata memory metadata;
metadata.name = _NAME;
metadata.version = _VERSION;
metadata.author = _AUTHOR;
diff --git a/test/mocks/plugins/DirectCallPlugin.sol b/test/mocks/modules/DirectCallModule.sol
similarity index 77%
rename from test/mocks/plugins/DirectCallPlugin.sol
rename to test/mocks/modules/DirectCallModule.sol
index 7ccda4f0..9e0f611d 100644
--- a/test/mocks/plugins/DirectCallPlugin.sol
+++ b/test/mocks/modules/DirectCallModule.sol
@@ -2,12 +2,12 @@
pragma solidity ^0.8.19;
import {IExecutionHook} from "../../../src/interfaces/IExecutionHook.sol";
-import {PluginManifest, PluginMetadata} from "../../../src/interfaces/IPlugin.sol";
+import {ModuleManifest, ModuleMetadata} from "../../../src/interfaces/IModule.sol";
import {IStandardExecutor} from "../../../src/interfaces/IStandardExecutor.sol";
-import {BasePlugin} from "../../../src/plugins/BasePlugin.sol";
+import {BaseModule} from "../../../src/modules/BaseModule.sol";
-contract DirectCallPlugin is BasePlugin, IExecutionHook {
+contract DirectCallModule is BaseModule, IExecutionHook {
bool public preHookRan = false;
bool public postHookRan = false;
@@ -15,7 +15,7 @@ contract DirectCallPlugin is BasePlugin, IExecutionHook {
function onUninstall(bytes calldata) external override {}
- function pluginManifest() external pure override returns (PluginManifest memory) {}
+ function moduleManifest() external pure override returns (ModuleManifest memory) {}
function directCall() external returns (bytes memory) {
return IStandardExecutor(msg.sender).execute(address(this), 0, abi.encodeCall(this.getData, ()));
@@ -25,7 +25,7 @@ contract DirectCallPlugin is BasePlugin, IExecutionHook {
return hex"04546b";
}
- function pluginMetadata() external pure override returns (PluginMetadata memory) {}
+ function moduleMetadata() external pure override returns (ModuleMetadata memory) {}
function preExecutionHook(uint32, address sender, uint256, bytes calldata)
external
diff --git a/test/mocks/plugins/MockAccessControlHookPlugin.sol b/test/mocks/modules/MockAccessControlHookModule.sol
similarity index 85%
rename from test/mocks/plugins/MockAccessControlHookPlugin.sol
rename to test/mocks/modules/MockAccessControlHookModule.sol
index 8fa49f8e..e3f47b86 100644
--- a/test/mocks/plugins/MockAccessControlHookPlugin.sol
+++ b/test/mocks/modules/MockAccessControlHookModule.sol
@@ -3,17 +3,17 @@ pragma solidity ^0.8.25;
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
-import {PluginManifest, PluginMetadata} from "../../../src/interfaces/IPlugin.sol";
+import {ModuleManifest, ModuleMetadata} from "../../../src/interfaces/IModule.sol";
import {IStandardExecutor} from "../../../src/interfaces/IStandardExecutor.sol";
import {IValidationHook} from "../../../src/interfaces/IValidationHook.sol";
-import {BasePlugin} from "../../../src/plugins/BasePlugin.sol";
+import {BaseModule} from "../../../src/modules/BaseModule.sol";
-// A pre validaiton hook plugin that uses per-hook data.
+// A pre validaiton hook module that uses per-hook data.
// This example enforces that the target of an `execute` call must only be the previously specified address.
// This is just a mock - it does not enforce this over `executeBatch` and other methods of making calls, and should
// not be used in production..
-contract MockAccessControlHookPlugin is IValidationHook, BasePlugin {
+contract MockAccessControlHookModule is IValidationHook, BaseModule {
enum EntityId {
PRE_VALIDATION_HOOK
}
@@ -73,7 +73,7 @@ contract MockAccessControlHookPlugin is IValidationHook, BasePlugin {
revert NotImplemented();
}
- function pluginMetadata() external pure override returns (PluginMetadata memory) {}
+ function moduleMetadata() external pure override returns (ModuleMetadata memory) {}
- function pluginManifest() external pure override returns (PluginManifest memory) {}
+ function moduleManifest() external pure override returns (ModuleManifest memory) {}
}
diff --git a/test/mocks/plugins/PermittedCallMocks.sol b/test/mocks/modules/PermittedCallMocks.sol
similarity index 53%
rename from test/mocks/plugins/PermittedCallMocks.sol
rename to test/mocks/modules/PermittedCallMocks.sol
index 77548225..bea02e78 100644
--- a/test/mocks/plugins/PermittedCallMocks.sol
+++ b/test/mocks/modules/PermittedCallMocks.sol
@@ -1,18 +1,18 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;
-import {ManifestExecutionFunction, PluginManifest, PluginMetadata} from "../../../src/interfaces/IPlugin.sol";
+import {ManifestExecutionFunction, ModuleManifest, ModuleMetadata} from "../../../src/interfaces/IModule.sol";
-import {BasePlugin} from "../../../src/plugins/BasePlugin.sol";
-import {ResultCreatorPlugin} from "./ReturnDataPluginMocks.sol";
+import {BaseModule} from "../../../src/modules/BaseModule.sol";
+import {ResultCreatorModule} from "./ReturnDataModuleMocks.sol";
-contract PermittedCallerPlugin is BasePlugin {
+contract PermittedCallerModule is BaseModule {
function onInstall(bytes calldata) external override {}
function onUninstall(bytes calldata) external override {}
- function pluginManifest() external pure override returns (PluginManifest memory) {
- PluginManifest memory manifest;
+ function moduleManifest() external pure override returns (ModuleManifest memory) {
+ ModuleManifest memory manifest;
manifest.executionFunctions = new ManifestExecutionFunction[](2);
manifest.executionFunctions[0].executionSelector = this.usePermittedCallAllowed.selector;
@@ -25,15 +25,15 @@ contract PermittedCallerPlugin is BasePlugin {
return manifest;
}
- function pluginMetadata() external pure override returns (PluginMetadata memory) {}
+ function moduleMetadata() external pure override returns (ModuleMetadata memory) {}
- // The manifest requested access to use the plugin-defined method "foo"
+ // The manifest requested access to use the module-defined method "foo"
function usePermittedCallAllowed() external view returns (bytes memory) {
- return abi.encode(ResultCreatorPlugin(msg.sender).foo());
+ return abi.encode(ResultCreatorModule(msg.sender).foo());
}
- // The manifest has not requested access to use the plugin-defined method "bar", so this should revert.
+ // The manifest has not requested access to use the module-defined method "bar", so this should revert.
function usePermittedCallNotAllowed() external view returns (bytes memory) {
- return abi.encode(ResultCreatorPlugin(msg.sender).bar());
+ return abi.encode(ResultCreatorModule(msg.sender).bar());
}
}
diff --git a/test/mocks/plugins/ReturnDataPluginMocks.sol b/test/mocks/modules/ReturnDataModuleMocks.sol
similarity index 84%
rename from test/mocks/plugins/ReturnDataPluginMocks.sol
rename to test/mocks/modules/ReturnDataModuleMocks.sol
index 96a77ffe..8fe3241d 100644
--- a/test/mocks/plugins/ReturnDataPluginMocks.sol
+++ b/test/mocks/modules/ReturnDataModuleMocks.sol
@@ -6,14 +6,14 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface
import {
ManifestExecutionFunction,
ManifestValidation,
- PluginManifest,
- PluginMetadata
-} from "../../../src/interfaces/IPlugin.sol";
+ ModuleManifest,
+ ModuleMetadata
+} from "../../../src/interfaces/IModule.sol";
import {IStandardExecutor} from "../../../src/interfaces/IStandardExecutor.sol";
import {IValidation} from "../../../src/interfaces/IValidation.sol";
-import {BasePlugin} from "../../../src/plugins/BasePlugin.sol";
+import {BaseModule} from "../../../src/modules/BaseModule.sol";
contract RegularResultContract {
function foo() external pure returns (bytes32) {
@@ -25,7 +25,7 @@ contract RegularResultContract {
}
}
-contract ResultCreatorPlugin is BasePlugin {
+contract ResultCreatorModule is BaseModule {
function onInstall(bytes calldata) external override {}
function onUninstall(bytes calldata) external override {}
@@ -38,8 +38,8 @@ contract ResultCreatorPlugin is BasePlugin {
return keccak256("foo");
}
- function pluginManifest() external pure override returns (PluginManifest memory) {
- PluginManifest memory manifest;
+ function moduleManifest() external pure override returns (ModuleManifest memory) {
+ ModuleManifest memory manifest;
manifest.executionFunctions = new ManifestExecutionFunction[](2);
manifest.executionFunctions[0] = ManifestExecutionFunction({
@@ -56,16 +56,16 @@ contract ResultCreatorPlugin is BasePlugin {
return manifest;
}
- function pluginMetadata() external pure override returns (PluginMetadata memory) {}
+ function moduleMetadata() external pure override returns (ModuleMetadata memory) {}
}
-contract ResultConsumerPlugin is BasePlugin, IValidation {
- ResultCreatorPlugin public immutable RESULT_CREATOR;
+contract ResultConsumerModule is BaseModule, IValidation {
+ ResultCreatorModule public immutable RESULT_CREATOR;
RegularResultContract public immutable REGULAR_RESULT_CONTRACT;
error NotAuthorized();
- constructor(ResultCreatorPlugin _resultCreator, RegularResultContract _regularResultContract) {
+ constructor(ResultCreatorModule _resultCreator, RegularResultContract _regularResultContract) {
RESULT_CREATOR = _resultCreator;
REGULAR_RESULT_CONTRACT = _regularResultContract;
}
@@ -93,7 +93,7 @@ contract ResultConsumerPlugin is BasePlugin, IValidation {
// Check the return data through the fallback
function checkResultFallback(bytes32 expected) external view returns (bool) {
// This result should be allowed based on the manifest permission request
- bytes32 actual = ResultCreatorPlugin(msg.sender).foo();
+ bytes32 actual = ResultCreatorModule(msg.sender).foo();
return actual == expected;
}
@@ -116,8 +116,8 @@ contract ResultConsumerPlugin is BasePlugin, IValidation {
function onUninstall(bytes calldata) external override {}
- function pluginManifest() external pure override returns (PluginManifest memory) {
- PluginManifest memory manifest;
+ function moduleManifest() external pure override returns (ModuleManifest memory) {
+ ModuleManifest memory manifest;
// todo: this is the exact workflow that would benefit from a "permiteed call" setup in the manifest.
bytes4[] memory validationSelectors = new bytes4[](1);
@@ -146,5 +146,5 @@ contract ResultConsumerPlugin is BasePlugin, IValidation {
return manifest;
}
- function pluginMetadata() external pure override returns (PluginMetadata memory) {}
+ function moduleMetadata() external pure override returns (ModuleMetadata memory) {}
}
diff --git a/test/mocks/plugins/ValidationPluginMocks.sol b/test/mocks/modules/ValidationModuleMocks.sol
similarity index 86%
rename from test/mocks/plugins/ValidationPluginMocks.sol
rename to test/mocks/modules/ValidationModuleMocks.sol
index 3cfe1d09..ed152af2 100644
--- a/test/mocks/plugins/ValidationPluginMocks.sol
+++ b/test/mocks/modules/ValidationModuleMocks.sol
@@ -6,14 +6,14 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface
import {
ManifestExecutionFunction,
ManifestValidation,
- PluginManifest,
- PluginMetadata
-} from "../../../src/interfaces/IPlugin.sol";
+ ModuleManifest,
+ ModuleMetadata
+} from "../../../src/interfaces/IModule.sol";
import {IValidation} from "../../../src/interfaces/IValidation.sol";
import {IValidationHook} from "../../../src/interfaces/IValidationHook.sol";
-import {BasePlugin} from "../../../src/plugins/BasePlugin.sol";
+import {BaseModule} from "../../../src/modules/BaseModule.sol";
-abstract contract MockBaseUserOpValidationPlugin is IValidation, IValidationHook, BasePlugin {
+abstract contract MockBaseUserOpValidationModule is IValidation, IValidationHook, BaseModule {
enum EntityId {
USER_OP_VALIDATION,
PRE_VALIDATION_HOOK_1,
@@ -25,7 +25,7 @@ abstract contract MockBaseUserOpValidationPlugin is IValidation, IValidationHook
uint256 internal _preUserOpValidationHook2Data;
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
- // ┃ Plugin interface functions ┃
+ // ┃ Module interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
function onInstall(bytes calldata) external override {}
@@ -68,7 +68,7 @@ abstract contract MockBaseUserOpValidationPlugin is IValidation, IValidationHook
}
// Empty stubs
- function pluginMetadata() external pure override returns (PluginMetadata memory) {}
+ function moduleMetadata() external pure override returns (ModuleMetadata memory) {}
function preRuntimeValidationHook(uint32, address, uint256, bytes calldata, bytes calldata)
external
@@ -87,7 +87,7 @@ abstract contract MockBaseUserOpValidationPlugin is IValidation, IValidationHook
}
}
-contract MockUserOpValidationPlugin is MockBaseUserOpValidationPlugin {
+contract MockUserOpValidationModule is MockBaseUserOpValidationModule {
function setValidationData(uint256 userOpValidationFunctionData) external {
_userOpValidationFunctionData = userOpValidationFunctionData;
}
@@ -99,11 +99,11 @@ contract MockUserOpValidationPlugin is MockBaseUserOpValidationPlugin {
function foo() external {}
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
- // ┃ Plugin interface functions ┃
+ // ┃ Module interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
- function pluginManifest() external pure override returns (PluginManifest memory) {
- PluginManifest memory manifest;
+ function moduleManifest() external pure override returns (ModuleManifest memory) {
+ ModuleManifest memory manifest;
manifest.executionFunctions = new ManifestExecutionFunction[](1);
manifest.executionFunctions[0] = ManifestExecutionFunction({
@@ -127,7 +127,7 @@ contract MockUserOpValidationPlugin is MockBaseUserOpValidationPlugin {
}
}
-contract MockUserOpValidation1HookPlugin is MockBaseUserOpValidationPlugin {
+contract MockUserOpValidation1HookModule is MockBaseUserOpValidationModule {
function setValidationData(uint256 userOpValidationFunctionData, uint256 preUserOpValidationHook1Data)
external
{
@@ -142,11 +142,11 @@ contract MockUserOpValidation1HookPlugin is MockBaseUserOpValidationPlugin {
function bar() external {}
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
- // ┃ Plugin interface functions ┃
+ // ┃ Module interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
- function pluginManifest() external pure override returns (PluginManifest memory) {
- PluginManifest memory manifest;
+ function moduleManifest() external pure override returns (ModuleManifest memory) {
+ ModuleManifest memory manifest;
manifest.executionFunctions = new ManifestExecutionFunction[](1);
manifest.executionFunctions[0] = ManifestExecutionFunction({
@@ -170,7 +170,7 @@ contract MockUserOpValidation1HookPlugin is MockBaseUserOpValidationPlugin {
}
}
-contract MockUserOpValidation2HookPlugin is MockBaseUserOpValidationPlugin {
+contract MockUserOpValidation2HookModule is MockBaseUserOpValidationModule {
function setValidationData(
uint256 userOpValidationFunctionData,
uint256 preUserOpValidationHook1Data,
@@ -188,11 +188,11 @@ contract MockUserOpValidation2HookPlugin is MockBaseUserOpValidationPlugin {
function baz() external {}
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
- // ┃ Plugin interface functions ┃
+ // ┃ Module interface functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
- function pluginManifest() external pure override returns (PluginManifest memory) {
- PluginManifest memory manifest;
+ function moduleManifest() external pure override returns (ModuleManifest memory) {
+ ModuleManifest memory manifest;
manifest.executionFunctions = new ManifestExecutionFunction[](1);
manifest.executionFunctions[0] = ManifestExecutionFunction({
diff --git a/test/plugin/ERC20TokenLimitPlugin.t.sol b/test/module/ERC20TokenLimitModule.t.sol
similarity index 75%
rename from test/plugin/ERC20TokenLimitPlugin.t.sol
rename to test/module/ERC20TokenLimitModule.t.sol
index cf7b422a..e88a4527 100644
--- a/test/plugin/ERC20TokenLimitPlugin.t.sol
+++ b/test/module/ERC20TokenLimitModule.t.sol
@@ -6,33 +6,33 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntity} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntity} from "../../src/helpers/ModuleEntityLib.sol";
-import {PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol";
import {ExecutionHook} from "../../src/interfaces/IAccountLoupe.sol";
-import {PluginManifest} from "../../src/interfaces/IPlugin.sol";
+import {ModuleManifest} from "../../src/interfaces/IModule.sol";
import {Call, IStandardExecutor} from "../../src/interfaces/IStandardExecutor.sol";
-import {ERC20TokenLimitPlugin} from "../../src/plugins/ERC20TokenLimitPlugin.sol";
-import {MockPlugin} from "../mocks/MockPlugin.sol";
+import {ERC20TokenLimitModule} from "../../src/modules/ERC20TokenLimitModule.sol";
+import {MockModule} from "../mocks/MockModule.sol";
import {AccountTestBase} from "../utils/AccountTestBase.sol";
-contract ERC20TokenLimitPluginTest is AccountTestBase {
+contract ERC20TokenLimitModuleTest is AccountTestBase {
address public recipient = address(1);
MockERC20 public erc20;
address payable public bundler = payable(address(2));
- PluginManifest internal _m;
- MockPlugin public validationPlugin = new MockPlugin(_m);
- PluginEntity public validationFunction;
+ ModuleManifest internal _m;
+ MockModule public validationModule = new MockModule(_m);
+ ModuleEntity public validationFunction;
UpgradeableModularAccount public acct;
- ERC20TokenLimitPlugin public plugin = new ERC20TokenLimitPlugin();
+ ERC20TokenLimitModule public module = new ERC20TokenLimitModule();
uint256 public spendLimit = 10 ether;
function setUp() public {
- // Set up a validator with hooks from the erc20 spend limit plugin attached
+ // Set up a validator with hooks from the erc20 spend limit module attached
acct = factory.createAccount(address(this), 0);
erc20 = new MockERC20();
@@ -40,7 +40,7 @@ contract ERC20TokenLimitPluginTest is AccountTestBase {
ExecutionHook[] memory permissionHooks = new ExecutionHook[](1);
permissionHooks[0] = ExecutionHook({
- hookFunction: PluginEntityLib.pack(address(plugin), 0),
+ hookFunction: ModuleEntityLib.pack(address(module), 0),
isPreHook: true,
isPostHook: false
});
@@ -49,22 +49,22 @@ contract ERC20TokenLimitPluginTest is AccountTestBase {
uint256[] memory limits = new uint256[](1);
limits[0] = spendLimit;
- ERC20TokenLimitPlugin.ERC20SpendLimit[] memory limit = new ERC20TokenLimitPlugin.ERC20SpendLimit[](1);
- limit[0] = ERC20TokenLimitPlugin.ERC20SpendLimit({token: address(erc20), limits: limits});
+ ERC20TokenLimitModule.ERC20SpendLimit[] memory limit = new ERC20TokenLimitModule.ERC20SpendLimit[](1);
+ limit[0] = ERC20TokenLimitModule.ERC20SpendLimit({token: address(erc20), limits: limits});
bytes[] memory permissionInitDatas = new bytes[](1);
permissionInitDatas[0] = abi.encode(uint8(0), limit);
vm.prank(address(acct));
acct.installValidation(
- ValidationConfigLib.pack(address(validationPlugin), 0, true, true),
+ ValidationConfigLib.pack(address(validationModule), 0, true, true),
new bytes4[](0),
new bytes(0),
new bytes(0),
abi.encode(permissionHooks, permissionInitDatas)
);
- validationFunction = PluginEntityLib.pack(address(validationPlugin), 0);
+ validationFunction = ModuleEntityLib.pack(address(validationModule), 0);
}
function _getPackedUO(bytes memory callData) internal view returns (PackedUserOperation memory uo) {
@@ -77,7 +77,7 @@ contract ERC20TokenLimitPluginTest is AccountTestBase {
preVerificationGas: 200_000,
gasFees: bytes32(uint256(uint128(0))),
paymasterAndData: "",
- signature: _encodeSignature(PluginEntityLib.pack(address(validationPlugin), 0), 1, "")
+ signature: _encodeSignature(ModuleEntityLib.pack(address(validationModule), 0), 1, "")
});
}
@@ -90,9 +90,9 @@ contract ERC20TokenLimitPluginTest is AccountTestBase {
function test_userOp_executeLimit() public {
vm.startPrank(address(entryPoint));
- assertEq(plugin.limits(0, address(erc20), address(acct)), 10 ether);
+ assertEq(module.limits(0, address(erc20), address(acct)), 10 ether);
acct.executeUserOp(_getPackedUO(_getExecuteWithSpend(5 ether)), bytes32(0));
- assertEq(plugin.limits(0, address(erc20), address(acct)), 5 ether);
+ assertEq(module.limits(0, address(erc20), address(acct)), 5 ether);
}
function test_userOp_executeBatchLimit() public {
@@ -108,9 +108,9 @@ contract ERC20TokenLimitPluginTest is AccountTestBase {
});
vm.startPrank(address(entryPoint));
- assertEq(plugin.limits(0, address(erc20), address(acct)), 10 ether);
+ assertEq(module.limits(0, address(erc20), address(acct)), 10 ether);
acct.executeUserOp(_getPackedUO(abi.encodeCall(IStandardExecutor.executeBatch, (calls))), bytes32(0));
- assertEq(plugin.limits(0, address(erc20), address(acct)), 10 ether - 6 ether - 100_001);
+ assertEq(module.limits(0, address(erc20), address(acct)), 10 ether - 6 ether - 100_001);
}
function test_userOp_executeBatch_approveAndTransferLimit() public {
@@ -126,9 +126,9 @@ contract ERC20TokenLimitPluginTest is AccountTestBase {
});
vm.startPrank(address(entryPoint));
- assertEq(plugin.limits(0, address(erc20), address(acct)), 10 ether);
+ assertEq(module.limits(0, address(erc20), address(acct)), 10 ether);
acct.executeUserOp(_getPackedUO(abi.encodeCall(IStandardExecutor.executeBatch, (calls))), bytes32(0));
- assertEq(plugin.limits(0, address(erc20), address(acct)), 10 ether - 6 ether - 100_001);
+ assertEq(module.limits(0, address(erc20), address(acct)), 10 ether - 6 ether - 100_001);
}
function test_userOp_executeBatch_approveAndTransferLimit_fail() public {
@@ -144,21 +144,21 @@ contract ERC20TokenLimitPluginTest is AccountTestBase {
});
vm.startPrank(address(entryPoint));
- assertEq(plugin.limits(0, address(erc20), address(acct)), 10 ether);
+ assertEq(module.limits(0, address(erc20), address(acct)), 10 ether);
PackedUserOperation[] memory uos = new PackedUserOperation[](1);
uos[0] = _getPackedUO(abi.encodeCall(IStandardExecutor.executeBatch, (calls)));
entryPoint.handleOps(uos, bundler);
// no spend consumed
- assertEq(plugin.limits(0, address(erc20), address(acct)), 10 ether);
+ assertEq(module.limits(0, address(erc20), address(acct)), 10 ether);
}
function test_runtime_executeLimit() public {
- assertEq(plugin.limits(0, address(erc20), address(acct)), 10 ether);
+ assertEq(module.limits(0, address(erc20), address(acct)), 10 ether);
acct.executeWithAuthorization(
_getExecuteWithSpend(5 ether),
- _encodeSignature(PluginEntityLib.pack(address(validationPlugin), 0), 1, "")
+ _encodeSignature(ModuleEntityLib.pack(address(validationModule), 0), 1, "")
);
- assertEq(plugin.limits(0, address(erc20), address(acct)), 5 ether);
+ assertEq(module.limits(0, address(erc20), address(acct)), 5 ether);
}
function test_runtime_executeBatchLimit() public {
@@ -173,11 +173,11 @@ contract ERC20TokenLimitPluginTest is AccountTestBase {
data: abi.encodeCall(IERC20.approve, (recipient, 5 ether + 100_000))
});
- assertEq(plugin.limits(0, address(erc20), address(acct)), 10 ether);
+ assertEq(module.limits(0, address(erc20), address(acct)), 10 ether);
acct.executeWithAuthorization(
abi.encodeCall(IStandardExecutor.executeBatch, (calls)),
- _encodeSignature(PluginEntityLib.pack(address(validationPlugin), 0), 1, "")
+ _encodeSignature(ModuleEntityLib.pack(address(validationModule), 0), 1, "")
);
- assertEq(plugin.limits(0, address(erc20), address(acct)), 10 ether - 6 ether - 100_001);
+ assertEq(module.limits(0, address(erc20), address(acct)), 10 ether - 6 ether - 100_001);
}
}
diff --git a/test/plugin/NativeTokenLimitPlugin.t.sol b/test/module/NativeTokenLimitModule.t.sol
similarity index 74%
rename from test/plugin/NativeTokenLimitPlugin.t.sol
rename to test/module/NativeTokenLimitModule.t.sol
index 0ae9ae40..a5e20389 100644
--- a/test/plugin/NativeTokenLimitPlugin.t.sol
+++ b/test/module/NativeTokenLimitModule.t.sol
@@ -4,43 +4,43 @@ pragma solidity ^0.8.19;
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntity} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntity} from "../../src/helpers/ModuleEntityLib.sol";
-import {PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol";
import {ExecutionHook} from "../../src/interfaces/IAccountLoupe.sol";
-import {PluginManifest} from "../../src/interfaces/IPlugin.sol";
+import {ModuleManifest} from "../../src/interfaces/IModule.sol";
import {Call, IStandardExecutor} from "../../src/interfaces/IStandardExecutor.sol";
-import {NativeTokenLimitPlugin} from "../../src/plugins/NativeTokenLimitPlugin.sol";
-import {MockPlugin} from "../mocks/MockPlugin.sol";
+import {NativeTokenLimitModule} from "../../src/modules/NativeTokenLimitModule.sol";
+import {MockModule} from "../mocks/MockModule.sol";
import {AccountTestBase} from "../utils/AccountTestBase.sol";
-contract NativeTokenLimitPluginTest is AccountTestBase {
+contract NativeTokenLimitModuleTest is AccountTestBase {
address public recipient = address(1);
address payable public bundler = payable(address(2));
- PluginManifest internal _m;
- MockPlugin public validationPlugin = new MockPlugin(_m);
- PluginEntity public validationFunction;
+ ModuleManifest internal _m;
+ MockModule public validationModule = new MockModule(_m);
+ ModuleEntity public validationFunction;
UpgradeableModularAccount public acct;
- NativeTokenLimitPlugin public plugin = new NativeTokenLimitPlugin();
+ NativeTokenLimitModule public module = new NativeTokenLimitModule();
uint256 public spendLimit = 10 ether;
function setUp() public {
- // Set up a validator with hooks from the gas spend limit plugin attached
+ // Set up a validator with hooks from the gas spend limit module attached
acct = factory.createAccount(address(this), 0);
vm.deal(address(acct), 10 ether);
- PluginEntity[] memory preValidationHooks = new PluginEntity[](1);
- preValidationHooks[0] = PluginEntityLib.pack(address(plugin), 0);
+ ModuleEntity[] memory preValidationHooks = new ModuleEntity[](1);
+ preValidationHooks[0] = ModuleEntityLib.pack(address(module), 0);
ExecutionHook[] memory permissionHooks = new ExecutionHook[](1);
permissionHooks[0] = ExecutionHook({
- hookFunction: PluginEntityLib.pack(address(plugin), 0),
+ hookFunction: ModuleEntityLib.pack(address(module), 0),
isPreHook: true,
isPostHook: false
});
@@ -56,14 +56,14 @@ contract NativeTokenLimitPluginTest is AccountTestBase {
vm.prank(address(acct));
acct.installValidation(
- ValidationConfigLib.pack(address(validationPlugin), 0, true, true),
+ ValidationConfigLib.pack(address(validationModule), 0, true, true),
new bytes4[](0),
new bytes(0),
abi.encode(preValidationHooks, preValHooksInitDatas),
abi.encode(permissionHooks, permissionInitDatas)
);
- validationFunction = PluginEntityLib.pack(address(validationPlugin), 0);
+ validationFunction = ModuleEntityLib.pack(address(validationModule), 0);
}
function _getExecuteWithValue(uint256 value) internal view returns (bytes memory) {
@@ -84,7 +84,7 @@ contract NativeTokenLimitPluginTest is AccountTestBase {
preVerificationGas: gas3,
gasFees: bytes32(uint256(uint128(gasPrice))),
paymasterAndData: "",
- signature: _encodeSignature(PluginEntityLib.pack(address(validationPlugin), 0), 1, "")
+ signature: _encodeSignature(ModuleEntityLib.pack(address(validationModule), 0), 1, "")
});
}
@@ -92,17 +92,17 @@ contract NativeTokenLimitPluginTest is AccountTestBase {
vm.startPrank(address(entryPoint));
// uses 10e - 200000 of gas
- assertEq(plugin.limits(0, address(acct)), 10 ether);
+ assertEq(module.limits(0, address(acct)), 10 ether);
uint256 result = acct.validateUserOp(
_getPackedUO(100_000, 100_000, 10 ether - 400_000, 1, _getExecuteWithValue(0)), bytes32(0), 0
);
- assertEq(plugin.limits(0, address(acct)), 200_000);
+ assertEq(module.limits(0, address(acct)), 200_000);
uint256 expected = uint256(type(uint48).max) << 160;
assertEq(result, expected);
// uses 200k + 1 wei of gas
- vm.expectRevert(NativeTokenLimitPlugin.ExceededNativeTokenLimit.selector);
+ vm.expectRevert(NativeTokenLimitModule.ExceededNativeTokenLimit.selector);
result = acct.validateUserOp(_getPackedUO(100_000, 100_000, 1, 1, _getExecuteWithValue(0)), bytes32(0), 0);
}
@@ -110,18 +110,18 @@ contract NativeTokenLimitPluginTest is AccountTestBase {
vm.startPrank(address(entryPoint));
// uses 5e of native tokens
- assertEq(plugin.limits(0, address(acct)), 10 ether);
+ assertEq(module.limits(0, address(acct)), 10 ether);
acct.executeUserOp(_getPackedUO(0, 0, 0, 0, _getExecuteWithValue(5 ether)), bytes32(0));
- assertEq(plugin.limits(0, address(acct)), 5 ether);
+ assertEq(module.limits(0, address(acct)), 5 ether);
// uses 5e + 1wei of native tokens
vm.expectRevert(
abi.encodePacked(
UpgradeableModularAccount.PreExecHookReverted.selector,
abi.encode(
- address(plugin),
+ address(module),
uint8(0),
- abi.encodePacked(NativeTokenLimitPlugin.ExceededNativeTokenLimit.selector)
+ abi.encodePacked(NativeTokenLimitModule.ExceededNativeTokenLimit.selector)
)
)
);
@@ -135,21 +135,21 @@ contract NativeTokenLimitPluginTest is AccountTestBase {
calls[2] = Call({target: recipient, value: 5 ether + 100_000, data: ""});
vm.startPrank(address(entryPoint));
- assertEq(plugin.limits(0, address(acct)), 10 ether);
+ assertEq(module.limits(0, address(acct)), 10 ether);
acct.executeUserOp(
_getPackedUO(0, 0, 0, 0, abi.encodeCall(IStandardExecutor.executeBatch, (calls))), bytes32(0)
);
- assertEq(plugin.limits(0, address(acct)), 10 ether - 6 ether - 100_001);
+ assertEq(module.limits(0, address(acct)), 10 ether - 6 ether - 100_001);
assertEq(recipient.balance, 6 ether + 100_001);
}
function test_userOp_combinedExecLimit_success() public {
- assertEq(plugin.limits(0, address(acct)), 10 ether);
+ assertEq(module.limits(0, address(acct)), 10 ether);
PackedUserOperation[] memory uos = new PackedUserOperation[](1);
uos[0] = _getPackedUO(200_000, 200_000, 200_000, 1, _getExecuteWithValue(5 ether));
entryPoint.handleOps(uos, bundler);
- assertEq(plugin.limits(0, address(acct)), 5 ether - 600_000);
+ assertEq(module.limits(0, address(acct)), 5 ether - 600_000);
assertEq(recipient.balance, 5 ether);
}
@@ -160,30 +160,30 @@ contract NativeTokenLimitPluginTest is AccountTestBase {
calls[2] = Call({target: recipient, value: 5 ether + 100_000, data: ""});
vm.startPrank(address(entryPoint));
- assertEq(plugin.limits(0, address(acct)), 10 ether);
+ assertEq(module.limits(0, address(acct)), 10 ether);
PackedUserOperation[] memory uos = new PackedUserOperation[](1);
uos[0] =
_getPackedUO(200_000, 200_000, 200_000, 1, abi.encodeCall(IStandardExecutor.executeBatch, (calls)));
entryPoint.handleOps(uos, bundler);
- assertEq(plugin.limits(0, address(acct)), 10 ether - 6 ether - 700_001);
+ assertEq(module.limits(0, address(acct)), 10 ether - 6 ether - 700_001);
assertEq(recipient.balance, 6 ether + 100_001);
}
function test_userOp_combinedExecLimit_failExec() public {
- assertEq(plugin.limits(0, address(acct)), 10 ether);
+ assertEq(module.limits(0, address(acct)), 10 ether);
PackedUserOperation[] memory uos = new PackedUserOperation[](1);
uos[0] = _getPackedUO(200_000, 200_000, 200_000, 1, _getExecuteWithValue(10 ether));
entryPoint.handleOps(uos, bundler);
- assertEq(plugin.limits(0, address(acct)), 10 ether - 600_000);
+ assertEq(module.limits(0, address(acct)), 10 ether - 600_000);
assertEq(recipient.balance, 0);
}
function test_runtime_executeLimit() public {
- assertEq(plugin.limits(0, address(acct)), 10 ether);
+ assertEq(module.limits(0, address(acct)), 10 ether);
acct.executeWithAuthorization(_getExecuteWithValue(5 ether), _encodeSignature(validationFunction, 1, ""));
- assertEq(plugin.limits(0, address(acct)), 5 ether);
+ assertEq(module.limits(0, address(acct)), 5 ether);
}
function test_runtime_executeBatchLimit() public {
@@ -192,10 +192,10 @@ contract NativeTokenLimitPluginTest is AccountTestBase {
calls[1] = Call({target: recipient, value: 1 ether, data: ""});
calls[2] = Call({target: recipient, value: 5 ether + 100_000, data: ""});
- assertEq(plugin.limits(0, address(acct)), 10 ether);
+ assertEq(module.limits(0, address(acct)), 10 ether);
acct.executeWithAuthorization(
abi.encodeCall(IStandardExecutor.executeBatch, (calls)), _encodeSignature(validationFunction, 1, "")
);
- assertEq(plugin.limits(0, address(acct)), 4 ether - 100_001);
+ assertEq(module.limits(0, address(acct)), 4 ether - 100_001);
}
}
diff --git a/test/plugin/TokenReceiverPlugin.t.sol b/test/module/TokenReceiverModule.t.sol
similarity index 92%
rename from test/plugin/TokenReceiverPlugin.t.sol
rename to test/module/TokenReceiverModule.t.sol
index 32fa2a9a..ffe85e86 100644
--- a/test/plugin/TokenReceiverPlugin.t.sol
+++ b/test/module/TokenReceiverModule.t.sol
@@ -7,7 +7,7 @@ import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Re
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {TokenReceiverPlugin} from "../../src/plugins/TokenReceiverPlugin.sol";
+import {TokenReceiverModule} from "../../src/modules/TokenReceiverModule.sol";
import {MockERC1155} from "../mocks/MockERC1155.sol";
import {MockERC721} from "../mocks/MockERC721.sol";
@@ -15,10 +15,10 @@ import {SingleSignerFactoryFixture} from "../mocks/SingleSignerFactoryFixture.so
import {OptimizedTest} from "../utils/OptimizedTest.sol";
-contract TokenReceiverPluginTest is OptimizedTest, IERC1155Receiver {
+contract TokenReceiverModuleTest is OptimizedTest, IERC1155Receiver {
EntryPoint public entryPoint;
UpgradeableModularAccount public acct;
- TokenReceiverPlugin public plugin;
+ TokenReceiverModule public module;
MockERC721 public t0;
MockERC1155 public t1;
@@ -39,7 +39,7 @@ contract TokenReceiverPluginTest is OptimizedTest, IERC1155Receiver {
new SingleSignerFactoryFixture(entryPoint, _deploySingleSignerValidation());
acct = factory.createAccount(address(this), 0);
- plugin = _deployTokenReceiverPlugin();
+ module = _deployTokenReceiverModule();
t0 = new MockERC721("t0", "t0");
t0.mint(address(this), _TOKEN_ID);
@@ -54,11 +54,11 @@ contract TokenReceiverPluginTest is OptimizedTest, IERC1155Receiver {
}
}
- function _initPlugin() internal {
- bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest()));
+ function _initModule() internal {
+ bytes32 manifestHash = keccak256(abi.encode(module.moduleManifest()));
vm.prank(address(entryPoint));
- acct.installPlugin(address(plugin), manifestHash, "");
+ acct.installModule(address(module), manifestHash, "");
}
function test_failERC721Transfer() public {
@@ -73,7 +73,7 @@ contract TokenReceiverPluginTest is OptimizedTest, IERC1155Receiver {
}
function test_passERC721Transfer() public {
- _initPlugin();
+ _initModule();
assertEq(t0.ownerOf(_TOKEN_ID), address(this));
t0.safeTransferFrom(address(this), address(acct), _TOKEN_ID);
assertEq(t0.ownerOf(_TOKEN_ID), address(acct));
@@ -102,7 +102,7 @@ contract TokenReceiverPluginTest is OptimizedTest, IERC1155Receiver {
}
function test_passERC1155Transfer() public {
- _initPlugin();
+ _initModule();
assertEq(t1.balanceOf(address(this), _TOKEN_ID), _TOKEN_AMOUNT);
assertEq(t1.balanceOf(address(acct), _TOKEN_ID), 0);
@@ -131,7 +131,7 @@ contract TokenReceiverPluginTest is OptimizedTest, IERC1155Receiver {
}
function test_passIntrospection() public {
- _initPlugin();
+ _initModule();
bool isSupported;
diff --git a/test/samples/AllowlistPlugin.t.sol b/test/samples/AllowlistModule.t.sol
similarity index 83%
rename from test/samples/AllowlistPlugin.t.sol
rename to test/samples/AllowlistModule.t.sol
index d2a28f5e..80b91fb5 100644
--- a/test/samples/AllowlistPlugin.t.sol
+++ b/test/samples/AllowlistModule.t.sol
@@ -4,23 +4,23 @@ pragma solidity ^0.8.25;
import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntity, PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntity, ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {Call} from "../../src/interfaces/IStandardExecutor.sol";
-import {AllowlistPlugin} from "../../src/samples/permissionhooks/AllowlistPlugin.sol";
+import {AllowlistModule} from "../../src/samples/permissionhooks/AllowlistModule.sol";
import {Counter} from "../mocks/Counter.sol";
import {CustomValidationTestBase} from "../utils/CustomValidationTestBase.sol";
-contract AllowlistPluginTest is CustomValidationTestBase {
- AllowlistPlugin public allowlistPlugin;
+contract AllowlistModuleTest is CustomValidationTestBase {
+ AllowlistModule public allowlistModule;
- AllowlistPlugin.AllowlistInit[] public allowlistInit;
+ AllowlistModule.AllowlistInit[] public allowlistInit;
Counter[] public counters;
function setUp() public {
- allowlistPlugin = new AllowlistPlugin();
+ allowlistModule = new AllowlistModule();
counters = new Counter[](10);
@@ -32,7 +32,7 @@ contract AllowlistPluginTest is CustomValidationTestBase {
}
function testFuzz_allowlistHook_userOp_single(uint256 seed) public {
- AllowlistPlugin.AllowlistInit[] memory inits;
+ AllowlistModule.AllowlistInit[] memory inits;
(inits, seed) = _generateRandomizedAllowlistInit(seed);
_copyInitToStorage(inits);
@@ -46,7 +46,7 @@ contract AllowlistPluginTest is CustomValidationTestBase {
}
function testFuzz_allowlistHook_userOp_batch(uint256 seed) public {
- AllowlistPlugin.AllowlistInit[] memory inits;
+ AllowlistModule.AllowlistInit[] memory inits;
(inits, seed) = _generateRandomizedAllowlistInit(seed);
_copyInitToStorage(inits);
@@ -60,7 +60,7 @@ contract AllowlistPluginTest is CustomValidationTestBase {
}
function testFuzz_allowlistHook_runtime_single(uint256 seed) public {
- AllowlistPlugin.AllowlistInit[] memory inits;
+ AllowlistModule.AllowlistInit[] memory inits;
(inits, seed) = _generateRandomizedAllowlistInit(seed);
_copyInitToStorage(inits);
@@ -78,7 +78,7 @@ contract AllowlistPluginTest is CustomValidationTestBase {
}
function testFuzz_allowlistHook_runtime_batch(uint256 seed) public {
- AllowlistPlugin.AllowlistInit[] memory inits;
+ AllowlistModule.AllowlistInit[] memory inits;
(inits, seed) = _generateRandomizedAllowlistInit(seed);
_copyInitToStorage(inits);
@@ -145,17 +145,17 @@ contract AllowlistPluginTest is CustomValidationTestBase {
Call memory call = calls[i];
(bool allowed, bool hasSelectorAllowlist) =
- allowlistPlugin.targetAllowlist(call.target, address(account1));
+ allowlistModule.targetAllowlist(call.target, address(account1));
if (allowed) {
if (
hasSelectorAllowlist
- && !allowlistPlugin.selectorAllowlist(call.target, bytes4(call.data), address(account1))
+ && !allowlistModule.selectorAllowlist(call.target, bytes4(call.data), address(account1))
) {
return abi.encodeWithSelector(
IEntryPoint.FailedOpWithRevert.selector,
0,
"AA23 reverted",
- abi.encodeWithSelector(AllowlistPlugin.SelectorNotAllowed.selector)
+ abi.encodeWithSelector(AllowlistModule.SelectorNotAllowed.selector)
);
}
} else {
@@ -163,7 +163,7 @@ contract AllowlistPluginTest is CustomValidationTestBase {
IEntryPoint.FailedOpWithRevert.selector,
0,
"AA23 reverted",
- abi.encodeWithSelector(AllowlistPlugin.TargetNotAllowed.selector)
+ abi.encodeWithSelector(AllowlistModule.TargetNotAllowed.selector)
);
}
}
@@ -176,30 +176,30 @@ contract AllowlistPluginTest is CustomValidationTestBase {
Call memory call = calls[i];
(bool allowed, bool hasSelectorAllowlist) =
- allowlistPlugin.targetAllowlist(call.target, address(account1));
+ allowlistModule.targetAllowlist(call.target, address(account1));
if (allowed) {
if (
hasSelectorAllowlist
- && !allowlistPlugin.selectorAllowlist(call.target, bytes4(call.data), address(account1))
+ && !allowlistModule.selectorAllowlist(call.target, bytes4(call.data), address(account1))
) {
return abi.encodeWithSelector(
UpgradeableModularAccount.PreRuntimeValidationHookFailed.selector,
- address(allowlistPlugin),
- uint32(AllowlistPlugin.EntityId.PRE_VALIDATION_HOOK),
- abi.encodeWithSelector(AllowlistPlugin.SelectorNotAllowed.selector)
+ address(allowlistModule),
+ uint32(AllowlistModule.EntityId.PRE_VALIDATION_HOOK),
+ abi.encodeWithSelector(AllowlistModule.SelectorNotAllowed.selector)
);
}
} else {
return abi.encodeWithSelector(
UpgradeableModularAccount.PreRuntimeValidationHookFailed.selector,
- address(allowlistPlugin),
- uint32(AllowlistPlugin.EntityId.PRE_VALIDATION_HOOK),
- abi.encodeWithSelector(AllowlistPlugin.TargetNotAllowed.selector)
+ address(allowlistModule),
+ uint32(AllowlistModule.EntityId.PRE_VALIDATION_HOOK),
+ abi.encodeWithSelector(AllowlistModule.TargetNotAllowed.selector)
);
}
}
- // At this point, we have returned any error that would come from the AllowlistPlugin.
+ // At this point, we have returned any error that would come from the AllowlistModule.
// But, because this is in the runtime path, the Counter itself may throw if it is not a valid selector.
for (uint256 i = 0; i < calls.length; i++) {
@@ -221,12 +221,12 @@ contract AllowlistPluginTest is CustomValidationTestBase {
function _generateRandomizedAllowlistInit(uint256 seed)
internal
view
- returns (AllowlistPlugin.AllowlistInit[] memory, uint256)
+ returns (AllowlistModule.AllowlistInit[] memory, uint256)
{
uint256 length = seed % 10;
seed = _next(seed);
- AllowlistPlugin.AllowlistInit[] memory init = new AllowlistPlugin.AllowlistInit[](length);
+ AllowlistModule.AllowlistInit[] memory init = new AllowlistModule.AllowlistInit[](length);
for (uint256 i = 0; i < length; i++) {
// Half the time, the target is a random counter, the other half, it's a random address.
@@ -271,7 +271,7 @@ contract AllowlistPluginTest is CustomValidationTestBase {
seed = _next(seed);
}
- init[i] = AllowlistPlugin.AllowlistInit(target, hasSelectorAllowlist, selectors);
+ init[i] = AllowlistModule.AllowlistInit(target, hasSelectorAllowlist, selectors);
}
return (init, seed);
@@ -291,12 +291,12 @@ contract AllowlistPluginTest is CustomValidationTestBase {
internal
virtual
override
- returns (PluginEntity, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory)
+ returns (ModuleEntity, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory)
{
- PluginEntity accessControlHook =
- PluginEntityLib.pack(address(allowlistPlugin), uint32(AllowlistPlugin.EntityId.PRE_VALIDATION_HOOK));
+ ModuleEntity accessControlHook =
+ ModuleEntityLib.pack(address(allowlistModule), uint32(AllowlistModule.EntityId.PRE_VALIDATION_HOOK));
- PluginEntity[] memory preValidationHooks = new PluginEntity[](1);
+ ModuleEntity[] memory preValidationHooks = new ModuleEntity[](1);
preValidationHooks[0] = accessControlHook;
bytes[] memory preValidationHookData = new bytes[](1);
@@ -318,7 +318,7 @@ contract AllowlistPluginTest is CustomValidationTestBase {
// Unfortunately, this is a feature that solidity has only implemented in via-ir, so we need to do it manually
// to be able to run the tests in lite mode.
- function _copyInitToStorage(AllowlistPlugin.AllowlistInit[] memory init) internal {
+ function _copyInitToStorage(AllowlistModule.AllowlistInit[] memory init) internal {
for (uint256 i = 0; i < init.length; i++) {
allowlistInit.push(init[i]);
}
diff --git a/test/utils/AccountTestBase.sol b/test/utils/AccountTestBase.sol
index 94caaabb..733b93e4 100644
--- a/test/utils/AccountTestBase.sol
+++ b/test/utils/AccountTestBase.sol
@@ -6,9 +6,9 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntity, PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntity, ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {Call, IStandardExecutor} from "../../src/interfaces/IStandardExecutor.sol";
-import {SingleSignerValidation} from "../../src/plugins/validation/SingleSignerValidation.sol";
+import {SingleSignerValidation} from "../../src/modules/validation/SingleSignerValidation.sol";
import {OptimizedTest} from "./OptimizedTest.sol";
import {TEST_DEFAULT_VALIDATION_ENTITY_ID as EXT_CONST_TEST_DEFAULT_VALIDATION_ENTITY_ID} from
@@ -19,7 +19,7 @@ import {SingleSignerFactoryFixture} from "../mocks/SingleSignerFactoryFixture.so
/// @dev This contract handles common boilerplate setup for tests using UpgradeableModularAccount with
/// SingleSignerValidation.
abstract contract AccountTestBase is OptimizedTest {
- using PluginEntityLib for PluginEntity;
+ using ModuleEntityLib for ModuleEntity;
using MessageHashUtils for bytes32;
EntryPoint public entryPoint;
@@ -32,7 +32,7 @@ abstract contract AccountTestBase is OptimizedTest {
uint256 public owner1Key;
UpgradeableModularAccount public account1;
- PluginEntity internal _signerValidation;
+ ModuleEntity internal _signerValidation;
uint8 public constant SELECTOR_ASSOCIATED_VALIDATION = 0;
uint8 public constant GLOBAL_VALIDATION = 1;
@@ -60,7 +60,7 @@ abstract contract AccountTestBase is OptimizedTest {
vm.deal(address(account1), 100 ether);
_signerValidation =
- PluginEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID);
+ ModuleEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID);
}
function _runExecUserOp(address target, bytes memory callData) internal {
@@ -103,7 +103,7 @@ abstract contract AccountTestBase is OptimizedTest {
(uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, userOpHash.toEthSignedMessageHash());
userOp.signature = _encodeSignature(
- PluginEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
+ ModuleEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
GLOBAL_VALIDATION,
abi.encodePacked(r, s, v)
);
@@ -156,7 +156,7 @@ abstract contract AccountTestBase is OptimizedTest {
account1.executeWithAuthorization(
callData,
_encodeSignature(
- PluginEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
+ ModuleEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
GLOBAL_VALIDATION,
""
)
@@ -171,7 +171,7 @@ abstract contract AccountTestBase is OptimizedTest {
account1.executeWithAuthorization(
callData,
_encodeSignature(
- PluginEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
+ ModuleEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
GLOBAL_VALIDATION,
""
)
@@ -193,7 +193,7 @@ abstract contract AccountTestBase is OptimizedTest {
)
),
_encodeSignature(
- PluginEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
+ ModuleEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
GLOBAL_VALIDATION,
""
)
@@ -207,7 +207,7 @@ abstract contract AccountTestBase is OptimizedTest {
// helper function to encode a signature, according to the per-hook and per-validation data format.
function _encodeSignature(
- PluginEntity validationFunction,
+ ModuleEntity validationFunction,
uint8 globalOrNot,
PreValidationHookData[] memory preValidationHookData,
bytes memory validationData
@@ -231,7 +231,7 @@ abstract contract AccountTestBase is OptimizedTest {
}
// overload for the case where there are no pre-validation hooks
- function _encodeSignature(PluginEntity validationFunction, uint8 globalOrNot, bytes memory validationData)
+ function _encodeSignature(ModuleEntity validationFunction, uint8 globalOrNot, bytes memory validationData)
internal
pure
returns (bytes memory)
diff --git a/test/utils/CustomValidationTestBase.sol b/test/utils/CustomValidationTestBase.sol
index f9e37c27..18fd6ae4 100644
--- a/test/utils/CustomValidationTestBase.sol
+++ b/test/utils/CustomValidationTestBase.sol
@@ -4,7 +4,7 @@ pragma solidity ^0.8.25;
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntity} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntity} from "../../src/helpers/ModuleEntityLib.sol";
import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol";
import {AccountTestBase} from "./AccountTestBase.sol";
@@ -16,7 +16,7 @@ import {AccountTestBase} from "./AccountTestBase.sol";
abstract contract CustomValidationTestBase is AccountTestBase {
function _customValidationSetup() internal {
(
- PluginEntity validationFunction,
+ ModuleEntity validationFunction,
bool isGlobal,
bool isSignatureValidation,
bytes4[] memory selectors,
@@ -44,7 +44,7 @@ abstract contract CustomValidationTestBase is AccountTestBase {
internal
virtual
returns (
- PluginEntity validationFunction,
+ ModuleEntity validationFunction,
bool shared,
bool isSignatureValidation,
bytes4[] memory selectors,
diff --git a/test/utils/OptimizedTest.sol b/test/utils/OptimizedTest.sol
index dc94380b..870d416a 100644
--- a/test/utils/OptimizedTest.sol
+++ b/test/utils/OptimizedTest.sol
@@ -7,8 +7,8 @@ import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntry
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {TokenReceiverPlugin} from "../../src/plugins/TokenReceiverPlugin.sol";
-import {SingleSignerValidation} from "../../src/plugins/validation/SingleSignerValidation.sol";
+import {TokenReceiverModule} from "../../src/modules/TokenReceiverModule.sol";
+import {SingleSignerValidation} from "../../src/modules/validation/SingleSignerValidation.sol";
/// @dev This contract provides functions to deploy optimized (via IR) precompiled contracts. By compiling just
/// the source contracts (excluding the test suite) via IR, and using the resulting bytecode within the tests
@@ -45,10 +45,10 @@ abstract contract OptimizedTest is Test {
: new UpgradeableModularAccount(entryPoint);
}
- function _deployTokenReceiverPlugin() internal returns (TokenReceiverPlugin) {
+ function _deployTokenReceiverModule() internal returns (TokenReceiverModule) {
return _isOptimizedTest()
- ? TokenReceiverPlugin(deployCode("out-optimized/TokenReceiverPlugin.sol/TokenReceiverPlugin.json"))
- : new TokenReceiverPlugin();
+ ? TokenReceiverModule(deployCode("out-optimized/TokenReceiverModule.sol/TokenReceiverModule.json"))
+ : new TokenReceiverModule();
}
function _deploySingleSignerValidation() internal returns (SingleSignerValidation) {
diff --git a/test/validation/SingleSignerValidation.t.sol b/test/validation/SingleSignerValidation.t.sol
index e81706fe..ae3be4e5 100644
--- a/test/validation/SingleSignerValidation.t.sol
+++ b/test/validation/SingleSignerValidation.t.sol
@@ -5,7 +5,7 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
-import {PluginEntityLib} from "../../src/helpers/PluginEntityLib.sol";
+import {ModuleEntityLib} from "../../src/helpers/ModuleEntityLib.sol";
import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol";
import {ContractOwner} from "../mocks/ContractOwner.sol";
@@ -50,7 +50,7 @@ contract SingleSignerValidationTest is AccountTestBase {
bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, userOpHash.toEthSignedMessageHash());
userOp.signature = _encodeSignature(
- PluginEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
+ ModuleEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
GLOBAL_VALIDATION,
abi.encodePacked(r, s, v)
);
@@ -68,7 +68,7 @@ contract SingleSignerValidationTest is AccountTestBase {
account.executeWithAuthorization(
abi.encodeCall(UpgradeableModularAccount.execute, (ethRecipient, 1 wei, "")),
_encodeSignature(
- PluginEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
+ ModuleEntityLib.pack(address(singleSignerValidation), TEST_DEFAULT_VALIDATION_ENTITY_ID),
GLOBAL_VALIDATION,
""
)
@@ -91,7 +91,7 @@ contract SingleSignerValidationTest is AccountTestBase {
account.executeWithAuthorization(
abi.encodeCall(UpgradeableModularAccount.execute, (ethRecipient, 1 wei, "")),
_encodeSignature(
- PluginEntityLib.pack(address(singleSignerValidation), newEntityId), GLOBAL_VALIDATION, ""
+ ModuleEntityLib.pack(address(singleSignerValidation), newEntityId), GLOBAL_VALIDATION, ""
)
);
assertEq(ethRecipient.balance, 1 wei);