diff --git a/src/account/BaseModularAccountLoupe.sol b/src/account/AccountLoupe.sol similarity index 67% rename from src/account/BaseModularAccountLoupe.sol rename to src/account/AccountLoupe.sol index 39ac5a77..526fe297 100644 --- a/src/account/BaseModularAccountLoupe.sol +++ b/src/account/AccountLoupe.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.19; import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import {IPluginLoupe} from "../interfaces/IPluginLoupe.sol"; +import {IAccountLoupe} from "../interfaces/IAccountLoupe.sol"; import {IPluginManager} from "../interfaces/IPluginManager.sol"; import {IStandardExecutor} from "../interfaces/IStandardExecutor.sol"; import { @@ -15,14 +15,12 @@ import { } from "../libraries/AccountStorage.sol"; import {FunctionReference} from "../libraries/FunctionReferenceLib.sol"; -abstract contract BaseModularAccountLoupe is IPluginLoupe { +abstract contract AccountLoupe is IAccountLoupe { using EnumerableSet for EnumerableSet.AddressSet; error ManifestDiscrepancy(address plugin); - /// @notice Gets the validator and plugin configuration for a selector - /// @param selector The selector to get the configuration for - /// @return config The configuration for this selector + /// @inheritdoc IAccountLoupe function getExecutionFunctionConfig(bytes4 selector) external view @@ -47,9 +45,7 @@ abstract contract BaseModularAccountLoupe is IPluginLoupe { config.runtimeValidationFunction = _storage.selectorData[selector].runtimeValidation; } - /// @notice Gets the pre and post execution hooks for a selector - /// @param selector The selector to get the hooks for - /// @return execHooks The pre and post execution hooks for this selector + /// @inheritdoc IAccountLoupe function getExecutionHooks(bytes4 selector) external view returns (ExecutionHooks[] memory execHooks) { AccountStorage storage _storage = getAccountStorage(); @@ -69,10 +65,7 @@ abstract contract BaseModularAccountLoupe is IPluginLoupe { } } - /// @notice Gets the pre and post permitted call hooks applied for a plugin calling this selector - /// @param callingPlugin The plugin that is calling the selector - /// @param selector The selector the plugin is calling - /// @return execHooks The pre and post permitted call hooks for this selector + /// @inheritdoc IAccountLoupe function getPermittedCallHooks(address callingPlugin, bytes4 selector) external view @@ -99,32 +92,22 @@ abstract contract BaseModularAccountLoupe is IPluginLoupe { } } - /// @notice Gets the pre user op validation hooks associated with a selector - /// @param selector The selector to get the hooks for - /// @return preValidationHooks The pre user op validation hooks for this selector - function getPreUserOpValidationHooks(bytes4 selector) + /// @inheritdoc IAccountLoupe + function getPreValidationHooks(bytes4 selector) external view - returns (FunctionReference[] memory preValidationHooks) + returns ( + FunctionReference[] memory preUserOpValidationHooks, + FunctionReference[] memory preRuntimeValidationHooks + ) { - preValidationHooks = + preUserOpValidationHooks = toFunctionReferenceArray(getAccountStorage().selectorData[selector].preUserOpValidationHooks); - } - - /// @notice Gets the pre runtime validation hooks associated with a selector - /// @param selector The selector to get the hooks for - /// @return preValidationHooks The pre runtime validation hooks for this selector - function getPreRuntimeValidationHooks(bytes4 selector) - external - view - returns (FunctionReference[] memory preValidationHooks) - { - preValidationHooks = + preRuntimeValidationHooks = toFunctionReferenceArray(getAccountStorage().selectorData[selector].preRuntimeValidationHooks); } - /// @notice Gets an array of all installed plugins - /// @return pluginAddresses The addresses of all installed plugins + /// @inheritdoc IAccountLoupe function getInstalledPlugins() external view returns (address[] memory pluginAddresses) { pluginAddresses = getAccountStorage().plugins.values(); } diff --git a/src/account/AccountStorageInitializable.sol b/src/account/AccountStorageInitializable.sol index 68805ffe..49d5b54a 100644 --- a/src/account/AccountStorageInitializable.sol +++ b/src/account/AccountStorageInitializable.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.19; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; + import {AccountStorage, getAccountStorage} from "../libraries/AccountStorage.sol"; abstract contract AccountStorageInitializable { diff --git a/src/account/BaseModularAccount.sol b/src/account/PluginManagerInternals.sol similarity index 98% rename from src/account/BaseModularAccount.sol rename to src/account/PluginManagerInternals.sol index b0b4f512..39050c41 100644 --- a/src/account/BaseModularAccount.sol +++ b/src/account/PluginManagerInternals.sol @@ -1,13 +1,9 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.19; -import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; -import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; -import {IPluginManager} from "../interfaces/IPluginManager.sol"; -import {AccountExecutor} from "./AccountExecutor.sol"; -import {FunctionReference, FunctionReferenceLib} from "../libraries/FunctionReferenceLib.sol"; import { AccountStorage, getAccountStorage, @@ -17,6 +13,8 @@ import { PermittedExternalCallData, StoredInjectedHook } from "../libraries/AccountStorage.sol"; +import {FunctionReference, FunctionReferenceLib} from "../libraries/FunctionReferenceLib.sol"; +import {IPluginManager} from "../interfaces/IPluginManager.sol"; import { IPlugin, ManifestExecutionHook, @@ -27,14 +25,10 @@ import { PluginManifest } from "../interfaces/IPlugin.sol"; -abstract contract BaseModularAccount is IPluginManager, AccountExecutor, IERC165 { +abstract contract PluginManagerInternals is IPluginManager { using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.AddressSet; - // As per the EIP-165 spec, no interface should ever match 0xffffffff - bytes4 internal constant _INTERFACE_ID_INVALID = 0xffffffff; - bytes4 internal constant _IERC165_INTERFACE_ID = 0x01ffc9a7; - error ArrayLengthMismatch(); error ExecuteFromPluginAlreadySet(bytes4 selector, address plugin); error PermittedExecutionSelectorNotInstalled(bytes4 selector, address plugin); @@ -382,9 +376,15 @@ abstract contract BaseModularAccount is IPluginManager, AccountExecutor, IERC165 // Update components according to the manifest. // All conflicts should revert. + + // Mark whether or not this plugin may spend native token amounts + if (manifest.canSpendNativeToken) { + _storage.pluginData[plugin].canSpendNativeToken = true; + } + length = manifest.executionFunctions.length; for (uint256 i = 0; i < length;) { - _setExecutionFunction(manifest.executionFunctions[i].selector, plugin); + _setExecutionFunction(manifest.executionFunctions[i], plugin); unchecked { ++i; @@ -402,7 +402,7 @@ abstract contract BaseModularAccount is IPluginManager, AccountExecutor, IERC165 } // Add the permitted external calls to the account. - if (manifest.permitAnyExternalContract) { + if (manifest.permitAnyExternalAddress) { _storage.pluginData[plugin].anyExternalExecPermitted = true; } else { // Only store the specific permitted external calls if "permit any" flag was not set. @@ -615,7 +615,7 @@ abstract contract BaseModularAccount is IPluginManager, AccountExecutor, IERC165 revert PluginInstallCallbackFailed(plugin, revertReason); } - emit PluginInstalled(plugin, manifestHash); + emit PluginInstalled(plugin, manifestHash, dependencies, injectedHooks); } function _uninstallPlugin( @@ -773,7 +773,7 @@ abstract contract BaseModularAccount is IPluginManager, AccountExecutor, IERC165 // remove external call permissions - if (manifest.permitAnyExternalContract) { + if (manifest.permitAnyExternalAddress) { // Only clear if it was set during install time _storage.pluginData[plugin].anyExternalExecPermitted = false; } else { @@ -839,7 +839,7 @@ abstract contract BaseModularAccount is IPluginManager, AccountExecutor, IERC165 length = manifest.executionFunctions.length; for (uint256 i = 0; i < length;) { - _removeExecutionFunction(manifest.executionFunctions[i].selector); + _removeExecutionFunction(manifest.executionFunctions[i]); unchecked { ++i; @@ -893,7 +893,7 @@ abstract contract BaseModularAccount is IPluginManager, AccountExecutor, IERC165 onUninstallSuccess = false; } - emit PluginUninstalled(plugin, manifestHash, onUninstallSuccess); + emit PluginUninstalled(plugin, onUninstallSuccess); } function _toSetValue(FunctionReference functionReference) internal pure returns (bytes32) { diff --git a/src/account/UpgradeableModularAccount.sol b/src/account/UpgradeableModularAccount.sol index 312c1d46..eb9cb5cc 100644 --- a/src/account/UpgradeableModularAccount.sol +++ b/src/account/UpgradeableModularAccount.sol @@ -1,32 +1,35 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.19; -import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; +import {BaseAccount} from "@eth-infinitism/account-abstraction/core/BaseAccount.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; - import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; -import {BaseAccount} from "@eth-infinitism/account-abstraction/core/BaseAccount.sol"; -import {BaseModularAccount} from "./BaseModularAccount.sol"; -import {BaseModularAccountLoupe} from "./BaseModularAccountLoupe.sol"; -import {IPlugin, PluginManifest} from "../interfaces/IPlugin.sol"; -import {IStandardExecutor, Call} from "../interfaces/IStandardExecutor.sol"; -import {IPluginExecutor} from "../interfaces/IPluginExecutor.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; + +import {AccountExecutor} from "./AccountExecutor.sol"; +import {AccountLoupe} from "./AccountLoupe.sol"; import {AccountStorage, getAccountStorage, getPermittedCallKey} from "../libraries/AccountStorage.sol"; -import {FunctionReference, FunctionReferenceLib} from "../libraries/FunctionReferenceLib.sol"; import {AccountStorageInitializable} from "./AccountStorageInitializable.sol"; +import {FunctionReference, FunctionReferenceLib} from "../libraries/FunctionReferenceLib.sol"; +import {IPlugin, PluginManifest} from "../interfaces/IPlugin.sol"; +import {IPluginExecutor} from "../interfaces/IPluginExecutor.sol"; import {IPluginManager} from "../interfaces/IPluginManager.sol"; +import {IStandardExecutor, Call} from "../interfaces/IStandardExecutor.sol"; +import {PluginManagerInternals} from "./PluginManagerInternals.sol"; import {_coalescePreValidation, _coalesceValidation} from "../helpers/ValidationDataHelpers.sol"; contract UpgradeableModularAccount is - IPluginManager, - BaseAccount, - BaseModularAccount, - BaseModularAccountLoupe, - UUPSUpgradeable, + AccountExecutor, + AccountLoupe, AccountStorageInitializable, + BaseAccount, + IERC165, + IPluginExecutor, IStandardExecutor, - IPluginExecutor + PluginManagerInternals, + UUPSUpgradeable { using EnumerableSet for EnumerableSet.Bytes32Set; @@ -37,6 +40,10 @@ contract UpgradeableModularAccount is IEntryPoint private immutable _ENTRY_POINT; + // As per the EIP-165 spec, no interface should ever match 0xffffffff + bytes4 internal constant _INTERFACE_ID_INVALID = 0xffffffff; + bytes4 internal constant _IERC165_INTERFACE_ID = 0x01ffc9a7; + event ModularAccountInitialized(IEntryPoint indexed entryPoint); error AlwaysDenyRule(); @@ -44,6 +51,7 @@ contract UpgradeableModularAccount is error ExecFromPluginNotPermitted(address plugin, bytes4 selector); error ExecFromPluginExternalNotPermitted(address plugin, address target, uint256 value, bytes data); error InvalidConfiguration(); + error NativeTokenSpendingNotPermitted(address plugin); error PostExecHookReverted(address plugin, uint8 functionId, bytes revertReason); error PreExecHookReverted(address plugin, uint8 functionId, bytes revertReason); error PreRuntimeValidationHookFailed(address plugin, uint8 functionId, bytes revertReason); @@ -213,6 +221,11 @@ contract UpgradeableModularAccount is bytes4 selector = bytes4(data); AccountStorage storage _storage = getAccountStorage(); + // Make sure plugin is allowed to spend native token. + if (value > 0 && value > msg.value && !_storage.pluginData[msg.sender].canSpendNativeToken) { + revert NativeTokenSpendingNotPermitted(msg.sender); + } + // Check the caller plugin's permission to make this call // Check the target contract permission. diff --git a/src/interfaces/IAccountLoupe.sol b/src/interfaces/IAccountLoupe.sol new file mode 100644 index 00000000..cdf1525f --- /dev/null +++ b/src/interfaces/IAccountLoupe.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.19; + +import {FunctionReference} from "../libraries/FunctionReferenceLib.sol"; + +interface IAccountLoupe { + /// @notice Config for an execution function, given a selector + struct ExecutionFunctionConfig { + address plugin; + FunctionReference userOpValidationFunction; + FunctionReference runtimeValidationFunction; + } + + /// @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 { + FunctionReference preExecHook; + FunctionReference postExecHook; + } + + /// @notice Gets 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 + /// @param selector The selector to get the configuration for + /// @return The configuration for this selector + function getExecutionFunctionConfig(bytes4 selector) external view returns (ExecutionFunctionConfig memory); + + /// @notice Gets the pre and post execution hooks for a selector + /// @param selector The selector to get the hooks for + /// @return The pre and post execution hooks for this selector + function getExecutionHooks(bytes4 selector) external view returns (ExecutionHooks[] memory); + + /// @notice Gets the pre and post permitted call hooks applied for a plugin calling this selector + /// @param callingPlugin The plugin that is calling the selector + /// @param selector The selector the plugin is calling + /// @return The pre and post permitted call hooks for this selector + function getPermittedCallHooks(address callingPlugin, bytes4 selector) + external + view + returns (ExecutionHooks[] memory); + + /// @notice Gets the pre user op and runtime validation hooks associated with a selector + /// @param selector The selector to get the hooks for + /// @return preUserOpValidationHooks The pre user op validation hooks for this selector + /// @return preRuntimeValidationHooks The pre runtime validation hooks for this selector + function getPreValidationHooks(bytes4 selector) + external + view + returns ( + FunctionReference[] memory preUserOpValidationHooks, + FunctionReference[] memory preRuntimeValidationHooks + ); + + /// @notice Gets an array of all installed plugins + /// @return The addresses of all installed plugins + function getInstalledPlugins() external view returns (address[] memory); +} diff --git a/src/interfaces/IPlugin.sol b/src/interfaces/IPlugin.sol index c0fa8edc..c3e27b0a 100644 --- a/src/interfaces/IPlugin.sol +++ b/src/interfaces/IPlugin.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.19; import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; + import {IPluginManager} from "./IPluginManager.sol"; // Forge formatter will displace the first comment for the enum field out of the enum itself, @@ -53,12 +54,13 @@ struct ManifestExternalCallPermission { bytes4[] selectors; } -struct ManifestExecutionFunction { - bytes4 selector; - string[] permissions; +struct SelectorPermission { + bytes4 functionSelector; + string permissionDescription; } -struct PluginManifest { +/// @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. string name; // The version of the plugin, following the semantic versioning scheme. @@ -66,6 +68,13 @@ struct PluginManifest { // The author field SHOULD be a username representing the identity of the user or organization // that created this plugin. string author; + // String desciptions of the relative sensitivity of specific functions. The selectors MUST be selectors for + // functions implemented by this plugin. + SelectorPermission[] permissionDescriptors; +} + +/// @dev A struct describing how the plugin should be installed on a modular account. +struct PluginManifest { // List of ERC-165 interfaceIds to add to account to support introspection checks. bytes4[] interfaceIds; // If this plugin depends on other plugins' validation functions and/or hooks, the interface IDs of @@ -73,12 +82,13 @@ struct PluginManifest { // members of `ManifestFunction` structs used in the manifest. bytes4[] dependencyInterfaceIds; // Execution functions defined in this plugin to be installed on the MSCA. - ManifestExecutionFunction[] executionFunctions; - // Native functions or execution functions already installed on the MSCA that this plugin will be - // able to call. + bytes4[] executionFunctions; + // Plugin execution functions already installed on the MSCA that this plugin will be able to call. bytes4[] permittedExecutionSelectors; - // External contract calls that this plugin will be able to make. - bool permitAnyExternalContract; + // Boolean to indicate whether the plugin can call any external contract addresses. + bool permitAnyExternalAddress; + // Boolean to indicate whether the plugin needs access to spend native tokens of the account. + bool canSpendNativeToken; ManifestExternalCallPermission[] permittedExternalCalls; ManifestAssociatedFunction[] userOpValidationFunctions; ManifestAssociatedFunction[] runtimeValidationFunctions; @@ -187,4 +197,9 @@ interface IPlugin { /// @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); + + /// @notice Describe the metadata of the plugin. + /// @dev This metadata MUST stay constant over time. + /// @return A metadata struct describing the plugin. + function pluginMetadata() external pure returns (PluginMetadata memory); } diff --git a/src/interfaces/IPluginLoupe.sol b/src/interfaces/IPluginLoupe.sol deleted file mode 100644 index 797c5567..00000000 --- a/src/interfaces/IPluginLoupe.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.19; - -import {FunctionReference} from "../libraries/FunctionReferenceLib.sol"; - -interface IPluginLoupe { - // Config for a Plugin Execution function - struct ExecutionFunctionConfig { - address plugin; - FunctionReference userOpValidationFunction; - FunctionReference runtimeValidationFunction; - } - - struct ExecutionHooks { - FunctionReference preExecHook; - FunctionReference postExecHook; - } - - function getExecutionFunctionConfig(bytes4 selector) external view returns (ExecutionFunctionConfig memory); - - function getExecutionHooks(bytes4 selector) external view returns (ExecutionHooks[] memory); - - function getPermittedCallHooks(address callingPlugin, bytes4 selector) - external - view - returns (ExecutionHooks[] memory); - - function getPreUserOpValidationHooks(bytes4 selector) external view returns (FunctionReference[] memory); - - function getPreRuntimeValidationHooks(bytes4 selector) external view returns (FunctionReference[] memory); - - function getInstalledPlugins() external view returns (address[] memory); -} diff --git a/src/interfaces/IPluginManager.sol b/src/interfaces/IPluginManager.sol index e646a501..7b7dd85f 100644 --- a/src/interfaces/IPluginManager.sol +++ b/src/interfaces/IPluginManager.sol @@ -3,9 +3,10 @@ pragma solidity ^0.8.19; import {FunctionReference} from "../libraries/FunctionReferenceLib.sol"; +/// @title Plugin Manager Interface interface IPluginManager { - // Pre/post exec hooks added by the user to limit the scope a plugin has - // These hooks are injected at plugin install time + /// @dev Pre/post exec hooks added by the user to limit the scope of a plugin. These hooks are injected at + /// plugin install time struct InjectedHook { // The plugin that provides the hook address providingPlugin; @@ -21,8 +22,15 @@ interface IPluginManager { uint8 postExecHookFunctionId; } - event PluginInstalled(address indexed plugin, bytes32 manifestHash); - event PluginUninstalled(address indexed plugin, bytes32 manifestHash, bool onUninstallSucceeded); + /// @dev Note that we strip hookApplyData from InjectedHooks in this event for gas savings + event PluginInstalled( + address indexed plugin, + bytes32 manifestHash, + FunctionReference[] dependencies, + InjectedHook[] injectedHooks + ); + + event PluginUninstalled(address indexed plugin, bool indexed callbacksSucceeded); /// @notice Install a plugin to the modular account. /// @param plugin The plugin to install. @@ -40,6 +48,7 @@ interface IPluginManager { ) external; /// @notice Uninstall a plugin from the modular account. + /// @dev Uninstalling owner plugins outside of a replace operation via executeBatch risks losing the account! /// @param plugin The plugin to uninstall. /// @param config An optional, implementation-specific field that accounts may use to ensure consistency /// guarantees. diff --git a/src/libraries/AccountStorage.sol b/src/libraries/AccountStorage.sol index 4254e2c2..7439dd56 100644 --- a/src/libraries/AccountStorage.sol +++ b/src/libraries/AccountStorage.sol @@ -10,6 +10,9 @@ bytes32 constant _ACCOUNT_STORAGE_SLOT = 0x9f09680beaa4e5c9f38841db2460c40149916 struct PluginData { bool anyExternalExecPermitted; + // boolean to indicate if the plugin can spend native tokens, if any of the execution function can spend + // native tokens, a plugin is considered to be able to spend native tokens of the accounts + bool canSpendNativeToken; bytes32 manifestHash; FunctionReference[] dependencies; // Tracks the number of times this plugin has been used as a dependency function diff --git a/src/plugins/BasePlugin.sol b/src/plugins/BasePlugin.sol index e03ba129..a8d610c1 100644 --- a/src/plugins/BasePlugin.sol +++ b/src/plugins/BasePlugin.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.19; import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; -import {IPlugin, PluginManifest} from "../interfaces/IPlugin.sol"; +import {IPlugin, PluginManifest, PluginMetadata} from "../interfaces/IPlugin.sol"; import {IPluginManager} from "../interfaces/IPluginManager.sol"; /// @title Base contract for plugins @@ -153,6 +153,11 @@ abstract contract BasePlugin is ERC165, IPlugin { revert NotImplemented(); } + /// @notice Describe the metadata of the plugin. + /// @dev This metadata MUST stay constant over time. + /// @return A metadata struct describing the plugin. + function pluginMetadata() external pure virtual returns (PluginMetadata memory); + /// @dev Returns true if this contract implements the interface defined by /// `interfaceId`. See the corresponding /// https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] diff --git a/src/plugins/TokenReceiverPlugin.sol b/src/plugins/TokenReceiverPlugin.sol index 8190a1c9..ac9335fd 100644 --- a/src/plugins/TokenReceiverPlugin.sol +++ b/src/plugins/TokenReceiverPlugin.sol @@ -10,7 +10,7 @@ import { ManifestAssociatedFunctionType, ManifestAssociatedFunction, PluginManifest, - ManifestExecutionFunction + PluginMetadata } from "../interfaces/IPlugin.sol"; import {BasePlugin} from "./BasePlugin.sol"; @@ -72,17 +72,11 @@ contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC777Recipient, I function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.name = NAME; - manifest.version = VERSION; - manifest.author = AUTHOR; - - manifest.executionFunctions = new ManifestExecutionFunction[](4); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.tokensReceived.selector, new string[](0)); - manifest.executionFunctions[1] = ManifestExecutionFunction(this.onERC721Received.selector, new string[](0)); - manifest.executionFunctions[2] = - ManifestExecutionFunction(this.onERC1155Received.selector, new string[](0)); - manifest.executionFunctions[3] = - ManifestExecutionFunction(this.onERC1155BatchReceived.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](4); + manifest.executionFunctions[0] = this.tokensReceived.selector; + manifest.executionFunctions[1] = this.onERC721Received.selector; + manifest.executionFunctions[2] = this.onERC1155Received.selector; + manifest.executionFunctions[3] = this.onERC1155BatchReceived.selector; // Only runtime validationFunction is needed since callbacks come from token contracts only ManifestFunction memory alwaysAllowFunction = ManifestFunction({ @@ -115,4 +109,13 @@ contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC777Recipient, I return manifest; } + + /// @inheritdoc BasePlugin + function pluginMetadata() external pure virtual override returns (PluginMetadata memory) { + PluginMetadata memory metadata; + metadata.name = NAME; + metadata.version = VERSION; + metadata.author = AUTHOR; + return metadata; + } } diff --git a/src/plugins/owner/SingleOwnerPlugin.sol b/src/plugins/owner/SingleOwnerPlugin.sol index 91143eb3..fa8ed177 100644 --- a/src/plugins/owner/SingleOwnerPlugin.sol +++ b/src/plugins/owner/SingleOwnerPlugin.sol @@ -13,7 +13,8 @@ import { ManifestAssociatedFunctionType, ManifestAssociatedFunction, PluginManifest, - ManifestExecutionFunction + PluginMetadata, + SelectorPermission } from "../../interfaces/IPlugin.sol"; import {IStandardExecutor} from "../../interfaces/IStandardExecutor.sol"; import {BasePlugin} from "../BasePlugin.sol"; @@ -139,18 +140,10 @@ contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.name = NAME; - manifest.version = VERSION; - manifest.author = AUTHOR; - - string[] memory ownerPermissions = new string[](1); - ownerPermissions[0] = "Modify Ownership"; - - manifest.executionFunctions = new ManifestExecutionFunction[](3); - manifest.executionFunctions[0] = - ManifestExecutionFunction(this.transferOwnership.selector, ownerPermissions); - manifest.executionFunctions[1] = ManifestExecutionFunction(this.isValidSignature.selector, new string[](0)); - manifest.executionFunctions[2] = ManifestExecutionFunction(this.owner.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](3); + manifest.executionFunctions[0] = this.transferOwnership.selector; + manifest.executionFunctions[1] = this.isValidSignature.selector; + manifest.executionFunctions[2] = this.owner.selector; ManifestFunction memory ownerUserOpValidationFunction = ManifestFunction({ functionType: ManifestAssociatedFunctionType.SELF, @@ -238,6 +231,25 @@ contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 { return manifest; } + /// @inheritdoc BasePlugin + function pluginMetadata() external pure virtual override returns (PluginMetadata memory) { + PluginMetadata memory metadata; + metadata.name = NAME; + metadata.version = VERSION; + metadata.author = AUTHOR; + + // Permission strings + string memory modifyOwnershipPermission = "Modify Ownership"; + + // Permission descriptions + metadata.permissionDescriptors = new SelectorPermission[](1); + metadata.permissionDescriptors[0] = SelectorPermission({ + functionSelector: this.transferOwnership.selector, + permissionDescription: modifyOwnershipPermission + }); + + return metadata; + } // ┏━━━━━━━━━━━━━━━┓ // ┃ EIP-165 ┃ // ┗━━━━━━━━━━━━━━━┛ diff --git a/test/account/ModularAccountLoupe.t.sol b/test/account/AccountLoupe.t.sol similarity index 94% rename from test/account/ModularAccountLoupe.t.sol rename to test/account/AccountLoupe.t.sol index 5757c001..31d08bb1 100644 --- a/test/account/ModularAccountLoupe.t.sol +++ b/test/account/AccountLoupe.t.sol @@ -15,7 +15,7 @@ import { ManifestFunction, PluginManifest } from "../../src/interfaces/IPlugin.sol"; -import {IPluginLoupe} from "../../src/interfaces/IPluginLoupe.sol"; +import {IAccountLoupe} from "../../src/interfaces/IAccountLoupe.sol"; import {IPluginManager} from "../../src/interfaces/IPluginManager.sol"; import {IStandardExecutor} from "../../src/interfaces/IStandardExecutor.sol"; import {FunctionReference, FunctionReferenceLib} from "../../src/libraries/FunctionReferenceLib.sol"; @@ -24,7 +24,7 @@ import {MSCAFactoryFixture} from "../mocks/MSCAFactoryFixture.sol"; import {ComprehensivePlugin} from "../mocks/plugins/ComprehensivePlugin.sol"; import {MockPlugin} from "../mocks/MockPlugin.sol"; -contract ModularAccountLoupeTest is Test { +contract AccountLoupeTest is Test { EntryPoint public entryPoint; SingleOwnerPlugin public singleOwnerPlugin; MSCAFactoryFixture public factory; @@ -98,7 +98,7 @@ contract ModularAccountLoupeTest is Test { expectedRuntimeValidations[4] = ownerRuntimeValidation; for (uint256 i = 0; i < selectorsToCheck.length; i++) { - IPluginLoupe.ExecutionFunctionConfig memory config = + IAccountLoupe.ExecutionFunctionConfig memory config = account1.getExecutionFunctionConfig(selectorsToCheck[i]); assertEq(config.plugin, address(account1)); @@ -134,7 +134,7 @@ contract ModularAccountLoupeTest is Test { expectedRuntimeValidations[1] = ownerRuntimeValidation; for (uint256 i = 0; i < selectorsToCheck.length; i++) { - IPluginLoupe.ExecutionFunctionConfig memory config = + IAccountLoupe.ExecutionFunctionConfig memory config = account1.getExecutionFunctionConfig(selectorsToCheck[i]); assertEq(config.plugin, expectedPluginAddress[i]); @@ -150,7 +150,7 @@ contract ModularAccountLoupeTest is Test { } function test_pluginLoupe_getExecutionHooks() public { - IPluginLoupe.ExecutionHooks[] memory hooks = account1.getExecutionHooks(comprehensivePlugin.foo.selector); + IAccountLoupe.ExecutionHooks[] memory hooks = account1.getExecutionHooks(comprehensivePlugin.foo.selector); assertEq(hooks.length, 1); assertEq( @@ -172,7 +172,7 @@ contract ModularAccountLoupeTest is Test { } function test_pluginLoupe_getPermittedCallHooks() public { - IPluginLoupe.ExecutionHooks[] memory hooks = + IAccountLoupe.ExecutionHooks[] memory hooks = account1.getPermittedCallHooks(address(comprehensivePlugin), comprehensivePlugin.foo.selector); assertEq(hooks.length, 1); @@ -243,7 +243,7 @@ contract ModularAccountLoupeTest is Test { // Assert that the returned execution hooks are what is expected - IPluginLoupe.ExecutionHooks[] memory hooks = account1.getExecutionHooks(comprehensivePlugin.foo.selector); + IAccountLoupe.ExecutionHooks[] memory hooks = account1.getExecutionHooks(comprehensivePlugin.foo.selector); assertEq(hooks.length, 2); assertEq( @@ -295,7 +295,7 @@ contract ModularAccountLoupeTest is Test { } function test_pluginLoupe_getPreUserOpValidationHooks() public { - FunctionReference[] memory hooks = account1.getPreUserOpValidationHooks(comprehensivePlugin.foo.selector); + (FunctionReference[] memory hooks,) = account1.getPreValidationHooks(comprehensivePlugin.foo.selector); assertEq(hooks.length, 2); assertEq( @@ -319,7 +319,7 @@ contract ModularAccountLoupeTest is Test { } function test_pluginLoupe_getPreRuntimeValidationHooks() public { - FunctionReference[] memory hooks = account1.getPreRuntimeValidationHooks(comprehensivePlugin.foo.selector); + (, FunctionReference[] memory hooks) = account1.getPreValidationHooks(comprehensivePlugin.foo.selector); assertEq(hooks.length, 2); assertEq( diff --git a/test/account/ManifestValidity.t.sol b/test/account/ManifestValidity.t.sol index 034e1929..08de7f63 100644 --- a/test/account/ManifestValidity.t.sol +++ b/test/account/ManifestValidity.t.sol @@ -7,7 +7,7 @@ import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.so import {IPluginManager} from "../../src/interfaces/IPluginManager.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; -import {BaseModularAccount} from "../../src/account/BaseModularAccount.sol"; +import {PluginManagerInternals} from "../../src/account/PluginManagerInternals.sol"; import {SingleOwnerPlugin} from "../../src/plugins/owner/SingleOwnerPlugin.sol"; import {FunctionReference} from "../../src/libraries/FunctionReferenceLib.sol"; @@ -47,7 +47,7 @@ contract ManifestValidityTest is Test { bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest())); - vm.expectRevert(abi.encodeWithSelector(BaseModularAccount.InvalidPluginManifest.selector)); + vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector)); account.installPlugin({ plugin: address(plugin), manifestHash: manifestHash, @@ -65,7 +65,7 @@ contract ManifestValidityTest is Test { bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest())); - vm.expectRevert(abi.encodeWithSelector(BaseModularAccount.InvalidPluginManifest.selector)); + vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector)); account.installPlugin({ plugin: address(plugin), manifestHash: manifestHash, @@ -83,7 +83,7 @@ contract ManifestValidityTest is Test { bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest())); - vm.expectRevert(abi.encodeWithSelector(BaseModularAccount.InvalidPluginManifest.selector)); + vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector)); account.installPlugin({ plugin: address(plugin), manifestHash: manifestHash, @@ -99,7 +99,7 @@ contract ManifestValidityTest is Test { bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest())); - vm.expectRevert(abi.encodeWithSelector(BaseModularAccount.InvalidPluginManifest.selector)); + vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector)); account.installPlugin({ plugin: address(plugin), manifestHash: manifestHash, @@ -115,7 +115,7 @@ contract ManifestValidityTest is Test { bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest())); - vm.expectRevert(abi.encodeWithSelector(BaseModularAccount.InvalidPluginManifest.selector)); + vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector)); account.installPlugin({ plugin: address(plugin), manifestHash: manifestHash, @@ -132,7 +132,7 @@ contract ManifestValidityTest is Test { bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest())); - vm.expectRevert(abi.encodeWithSelector(BaseModularAccount.InvalidPluginManifest.selector)); + vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector)); account.installPlugin({ plugin: address(plugin), manifestHash: manifestHash, @@ -149,7 +149,7 @@ contract ManifestValidityTest is Test { bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest())); - vm.expectRevert(abi.encodeWithSelector(BaseModularAccount.InvalidPluginManifest.selector)); + vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector)); account.installPlugin({ plugin: address(plugin), manifestHash: manifestHash, @@ -165,7 +165,7 @@ contract ManifestValidityTest is Test { bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest())); - vm.expectRevert(abi.encodeWithSelector(BaseModularAccount.InvalidPluginManifest.selector)); + vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector)); account.installPlugin({ plugin: address(plugin), manifestHash: manifestHash, diff --git a/test/account/UpgradeableModularAccount.t.sol b/test/account/UpgradeableModularAccount.t.sol index 3b584181..421f08da 100644 --- a/test/account/UpgradeableModularAccount.t.sol +++ b/test/account/UpgradeableModularAccount.t.sol @@ -7,12 +7,12 @@ import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol"; import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; -import {BaseModularAccount} from "../../src/account/BaseModularAccount.sol"; +import {PluginManagerInternals} from "../../src/account/PluginManagerInternals.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; import {SingleOwnerPlugin} from "../../src/plugins/owner/SingleOwnerPlugin.sol"; import {TokenReceiverPlugin} from "../../src/plugins/TokenReceiverPlugin.sol"; import {PluginManifest} from "../../src/interfaces/IPlugin.sol"; -import {IPluginLoupe} from "../../src/interfaces/IPluginLoupe.sol"; +import {IAccountLoupe} from "../../src/interfaces/IAccountLoupe.sol"; import {IPluginManager} from "../../src/interfaces/IPluginManager.sol"; import {IPluginExecutor} from "../../src/interfaces/IPluginExecutor.sol"; import {Call} from "../../src/interfaces/IStandardExecutor.sol"; @@ -53,8 +53,13 @@ contract UpgradeableModularAccountTest is Test { uint256 public constant CALL_GAS_LIMIT = 50000; uint256 public constant VERIFICATION_GAS_LIMIT = 1200000; - event PluginInstalled(address indexed plugin, bytes32 manifestHash); - event PluginUninstalled(address indexed plugin, bytes32 manifestHash, bool onUninstallSucceeded); + event PluginInstalled( + address indexed plugin, + bytes32 manifestHash, + FunctionReference[] dependencies, + IPluginManager.InjectedHook[] injectedHooks + ); + event PluginUninstalled(address indexed plugin, bool indexed callbacksSucceeded); event ReceivedCall(bytes msgData, uint256 msgValue); function setUp() public { @@ -271,7 +276,12 @@ contract UpgradeableModularAccountTest is Test { bytes32 manifestHash = keccak256(abi.encode(tokenReceiverPlugin.pluginManifest())); vm.expectEmit(true, true, true, true); - emit PluginInstalled(address(tokenReceiverPlugin), manifestHash); + emit PluginInstalled( + address(tokenReceiverPlugin), + manifestHash, + new FunctionReference[](0), + new IPluginManager.InjectedHook[](0) + ); IPluginManager(account2).installPlugin({ plugin: address(tokenReceiverPlugin), manifestHash: manifestHash, @@ -280,7 +290,7 @@ contract UpgradeableModularAccountTest is Test { injectedHooks: new IPluginManager.InjectedHook[](0) }); - address[] memory plugins = IPluginLoupe(account2).getInstalledPlugins(); + address[] memory plugins = IAccountLoupe(account2).getInstalledPlugins(); assertEq(plugins.length, 2); assertEq(plugins[0], address(singleOwnerPlugin)); assertEq(plugins[1], address(tokenReceiverPlugin)); @@ -298,7 +308,7 @@ contract UpgradeableModularAccountTest is Test { vm.expectRevert( abi.encodeWithSelector( - BaseModularAccount.PermittedExecutionSelectorNotInstalled.selector, + PluginManagerInternals.PermittedExecutionSelectorNotInstalled.selector, IPlugin.onInstall.selector, address(mockPluginWithBadPermittedExec) ) @@ -315,7 +325,7 @@ contract UpgradeableModularAccountTest is Test { function test_installPlugin_invalidManifest() public { vm.startPrank(owner2); - vm.expectRevert(abi.encodeWithSelector(BaseModularAccount.InvalidPluginManifest.selector)); + vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector)); IPluginManager(account2).installPlugin({ plugin: address(tokenReceiverPlugin), manifestHash: bytes32(0), @@ -330,7 +340,7 @@ contract UpgradeableModularAccountTest is Test { address badPlugin = address(1); vm.expectRevert( - abi.encodeWithSelector(BaseModularAccount.PluginInterfaceNotSupported.selector, address(badPlugin)) + abi.encodeWithSelector(PluginManagerInternals.PluginInterfaceNotSupported.selector, address(badPlugin)) ); IPluginManager(account2).installPlugin({ plugin: address(badPlugin), @@ -355,7 +365,7 @@ contract UpgradeableModularAccountTest is Test { vm.expectRevert( abi.encodeWithSelector( - BaseModularAccount.PluginAlreadyInstalled.selector, address(tokenReceiverPlugin) + PluginManagerInternals.PluginAlreadyInstalled.selector, address(tokenReceiverPlugin) ) ); IPluginManager(account2).installPlugin({ @@ -381,14 +391,14 @@ contract UpgradeableModularAccountTest is Test { }); vm.expectEmit(true, true, true, true); - emit PluginUninstalled(address(plugin), manifestHash, true); + emit PluginUninstalled(address(plugin), true); IPluginManager(account2).uninstallPlugin({ plugin: address(plugin), config: "", pluginUninstallData: "", hookUnapplyData: new bytes[](0) }); - address[] memory plugins = IPluginLoupe(account2).getInstalledPlugins(); + address[] memory plugins = IAccountLoupe(account2).getInstalledPlugins(); assertEq(plugins.length, 1); assertEq(plugins[0], address(singleOwnerPlugin)); } @@ -408,14 +418,14 @@ contract UpgradeableModularAccountTest is Test { }); vm.expectEmit(true, true, true, true); - emit PluginUninstalled(address(plugin), manifestHash, true); + emit PluginUninstalled(address(plugin), true); IPluginManager(account2).uninstallPlugin({ plugin: address(plugin), config: serializedManifest, pluginUninstallData: "", hookUnapplyData: new bytes[](0) }); - address[] memory plugins = IPluginLoupe(account2).getInstalledPlugins(); + address[] memory plugins = IAccountLoupe(account2).getInstalledPlugins(); assertEq(plugins.length, 1); assertEq(plugins[0], address(singleOwnerPlugin)); } @@ -437,14 +447,14 @@ contract UpgradeableModularAccountTest is Test { // Attempt to uninstall with a blank manifest PluginManifest memory blankManifest; - vm.expectRevert(abi.encodeWithSelector(BaseModularAccount.InvalidPluginManifest.selector)); + vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector)); IPluginManager(account2).uninstallPlugin({ plugin: address(plugin), config: abi.encode(blankManifest), pluginUninstallData: "", hookUnapplyData: new bytes[](0) }); - address[] memory plugins = IPluginLoupe(account2).getInstalledPlugins(); + address[] memory plugins = IAccountLoupe(account2).getInstalledPlugins(); assertEq(plugins.length, 2); assertEq(plugins[0], address(singleOwnerPlugin)); assertEq(plugins[1], address(plugin)); @@ -473,7 +483,7 @@ contract UpgradeableModularAccountTest is Test { { hooksPlugin = _installPluginWithExecHooks(); - manifest.permitAnyExternalContract = true; + manifest.permitAnyExternalAddress = true; newPlugin = new MockPlugin(manifest); manifestHash = keccak256(abi.encode(newPlugin.pluginManifest())); @@ -485,7 +495,7 @@ contract UpgradeableModularAccountTest is Test { vm.prank(owner2); vm.expectEmit(true, true, true, true); - emit PluginInstalled(address(newPlugin), manifestHash); + emit PluginInstalled(address(newPlugin), manifestHash, new FunctionReference[](0), hooks); emit ReceivedCall(abi.encodeCall(IPlugin.onHookApply, (address(newPlugin), injectedHooksInfo, "")), 0); IPluginManager(account2).installPlugin({ plugin: address(newPlugin), @@ -539,7 +549,7 @@ contract UpgradeableModularAccountTest is Test { ); vm.expectEmit(true, true, true, true); - emit PluginInstalled(address(newPlugin), manifestHash); + emit PluginInstalled(address(newPlugin), manifestHash, new FunctionReference[](0), hooks); emit ReceivedCall( abi.encodeCall(IPlugin.onHookApply, (address(newPlugin), injectedHooksInfo, onApplyData)), 0 ); @@ -567,7 +577,7 @@ contract UpgradeableModularAccountTest is Test { ); vm.expectRevert( - abi.encodeWithSelector(BaseModularAccount.MissingPluginDependency.selector, address(hooksPlugin)) + abi.encodeWithSelector(PluginManagerInternals.MissingPluginDependency.selector, address(hooksPlugin)) ); vm.prank(owner2); IPluginManager(account2).installPlugin({ @@ -583,7 +593,7 @@ contract UpgradeableModularAccountTest is Test { (, MockPlugin newPlugin, bytes32 manifestHash) = _installWithInjectHooks(); vm.expectEmit(true, true, true, true); - emit PluginUninstalled(address(newPlugin), manifestHash, true); + emit PluginUninstalled(address(newPlugin), true); vm.prank(owner2); IPluginManager(account2).uninstallPlugin({ plugin: address(newPlugin), @@ -598,7 +608,7 @@ contract UpgradeableModularAccountTest is Test { vm.prank(owner2); vm.expectRevert( - abi.encodeWithSelector(BaseModularAccount.PluginDependencyViolation.selector, address(hooksPlugin)) + abi.encodeWithSelector(PluginManagerInternals.PluginDependencyViolation.selector, address(hooksPlugin)) ); IPluginManager(account2).uninstallPlugin({ plugin: address(hooksPlugin), @@ -634,7 +644,7 @@ contract UpgradeableModularAccountTest is Test { // length != installed hooks length bytes[] memory injectedHooksDatas = new bytes[](2); - vm.expectRevert(BaseModularAccount.ArrayLengthMismatch.selector); + vm.expectRevert(PluginManagerInternals.ArrayLengthMismatch.selector); vm.prank(owner2); IPluginManager(account2).uninstallPlugin({ plugin: address(newPlugin), diff --git a/test/mocks/MockPlugin.sol b/test/mocks/MockPlugin.sol index 7daa8e5a..273d5335 100644 --- a/test/mocks/MockPlugin.sol +++ b/test/mocks/MockPlugin.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.19; import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; -import {PluginManifest, IPlugin} from "../../src/interfaces/IPlugin.sol"; +import {PluginManifest, IPlugin, PluginMetadata} from "../../src/interfaces/IPlugin.sol"; contract MockPlugin is ERC165 { // It's super inefficient to hold the entire abi-encoded manifest in storage, but this is fine since it's @@ -26,10 +26,6 @@ contract MockPlugin is ERC165 { // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ constructor(PluginManifest memory _pluginManifest) { - _pluginManifest.name = NAME; - _pluginManifest.version = VERSION; - _pluginManifest.author = AUTHOR; - _manifest = abi.encode(_pluginManifest); } @@ -52,6 +48,14 @@ contract MockPlugin is ERC165 { return _castToPure(_getManifest)(); } + function pluginMetadata() external pure returns (PluginMetadata memory) { + PluginMetadata memory metadata; + metadata.name = NAME; + metadata.version = VERSION; + metadata.author = AUTHOR; + return metadata; + } + /// @dev Returns true if this contract implements the interface defined by /// `interfaceId`. See the corresponding /// https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] @@ -64,6 +68,7 @@ contract MockPlugin is ERC165 { /// making calls to plugins. /// @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); } diff --git a/test/mocks/plugins/BadTransferOwnershipPlugin.sol b/test/mocks/plugins/BadTransferOwnershipPlugin.sol index f7e6a744..0b291c03 100644 --- a/test/mocks/plugins/BadTransferOwnershipPlugin.sol +++ b/test/mocks/plugins/BadTransferOwnershipPlugin.sol @@ -7,7 +7,7 @@ import { ManifestAssociatedFunctionType, ManifestAssociatedFunction, PluginManifest, - ManifestExecutionFunction + PluginMetadata } from "../../../src/interfaces/IPlugin.sol"; import {IPluginManager} from "../../../src/interfaces/IPluginManager.sol"; import {BasePlugin} from "../../../src/plugins/BasePlugin.sol"; @@ -41,13 +41,8 @@ contract BadTransferOwnershipPlugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.name = NAME; - manifest.version = VERSION; - manifest.author = AUTHOR; - - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = - ManifestExecutionFunction(this.evilTransferOwnership.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.evilTransferOwnership.selector; manifest.permittedExecutionSelectors = new bytes4[](1); manifest.permittedExecutionSelectors[0] = ISingleOwnerPlugin.transferOwnership.selector; @@ -64,4 +59,12 @@ contract BadTransferOwnershipPlugin is BasePlugin { return manifest; } + + function pluginMetadata() external pure virtual override returns (PluginMetadata memory) { + PluginMetadata memory metadata; + metadata.name = NAME; + metadata.version = VERSION; + metadata.author = AUTHOR; + return metadata; + } } diff --git a/test/mocks/plugins/BaseTestPlugin.sol b/test/mocks/plugins/BaseTestPlugin.sol new file mode 100644 index 00000000..508845c1 --- /dev/null +++ b/test/mocks/plugins/BaseTestPlugin.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import {BasePlugin} from "../../../src/plugins/BasePlugin.sol"; +import {PluginMetadata} from "../../../src/interfaces/IPlugin.sol"; + +contract BaseTestPlugin is BasePlugin { + // Don't need to implement this in each context + function pluginMetadata() external pure virtual override returns (PluginMetadata memory) { + revert NotImplemented(); + } +} diff --git a/test/mocks/plugins/ComprehensivePlugin.sol b/test/mocks/plugins/ComprehensivePlugin.sol index 391b1cee..4be37ff8 100644 --- a/test/mocks/plugins/ComprehensivePlugin.sol +++ b/test/mocks/plugins/ComprehensivePlugin.sol @@ -9,7 +9,7 @@ import { ManifestAssociatedFunctionType, ManifestAssociatedFunction, PluginManifest, - ManifestExecutionFunction + PluginMetadata } from "../../../src/interfaces/IPlugin.sol"; import {IStandardExecutor} from "../../../src/interfaces/IStandardExecutor.sol"; import {BasePlugin} from "../../../src/plugins/BasePlugin.sol"; @@ -118,12 +118,8 @@ contract ComprehensivePlugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.name = NAME; - manifest.version = VERSION; - manifest.author = AUTHOR; - - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.foo.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.foo.selector; ManifestFunction memory fooUserOpValidationFunction = ManifestFunction({ functionType: ManifestAssociatedFunctionType.SELF, @@ -247,4 +243,12 @@ contract ComprehensivePlugin is BasePlugin { return manifest; } + + function pluginMetadata() external pure virtual override returns (PluginMetadata memory) { + PluginMetadata memory metadata; + metadata.name = NAME; + metadata.version = VERSION; + metadata.author = AUTHOR; + return metadata; + } } diff --git a/test/mocks/plugins/ExecFromPluginPermissionsMocks.sol b/test/mocks/plugins/ExecFromPluginPermissionsMocks.sol index d6ed7663..8861012f 100644 --- a/test/mocks/plugins/ExecFromPluginPermissionsMocks.sol +++ b/test/mocks/plugins/ExecFromPluginPermissionsMocks.sol @@ -7,13 +7,12 @@ import { ManifestAssociatedFunction, ManifestExternalCallPermission, ManifestExecutionHook, - PluginManifest, - ManifestExecutionFunction + PluginManifest } from "../../../src/interfaces/IPlugin.sol"; import {IStandardExecutor} from "../../../src/interfaces/IStandardExecutor.sol"; import {IPluginExecutor} from "../../../src/interfaces/IPluginExecutor.sol"; import {IPlugin} from "../../../src/interfaces/IPlugin.sol"; -import {BasePlugin} from "../../../src/plugins/BasePlugin.sol"; +import {BaseTestPlugin} from "./BaseTestPlugin.sol"; import {FunctionReference} from "../../../src/libraries/FunctionReferenceLib.sol"; import {ResultCreatorPlugin} from "./ReturnDataPluginMocks.sol"; @@ -25,7 +24,7 @@ address constant counter1 = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f; address constant counter2 = 0x2e234DAe75C793f67A35089C9d99245E1C58470b; address constant counter3 = 0xF62849F9A0B5Bf2913b396098F7c7019b51A820a; -contract EFPCallerPlugin is BasePlugin { +contract EFPCallerPlugin is BaseTestPlugin { function onInstall(bytes calldata) external override {} function onUninstall(bytes calldata) external override {} @@ -33,29 +32,18 @@ contract EFPCallerPlugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](11); - manifest.executionFunctions[0] = - ManifestExecutionFunction(this.useEFPPermissionAllowed.selector, new string[](0)); - manifest.executionFunctions[1] = - ManifestExecutionFunction(this.useEFPPermissionNotAllowed.selector, new string[](0)); - manifest.executionFunctions[2] = - ManifestExecutionFunction(this.setNumberCounter1.selector, new string[](0)); - manifest.executionFunctions[3] = - ManifestExecutionFunction(this.getNumberCounter1.selector, new string[](0)); - manifest.executionFunctions[4] = - ManifestExecutionFunction(this.incrementCounter1.selector, new string[](0)); - manifest.executionFunctions[5] = - ManifestExecutionFunction(this.setNumberCounter2.selector, new string[](0)); - manifest.executionFunctions[6] = - ManifestExecutionFunction(this.getNumberCounter2.selector, new string[](0)); - manifest.executionFunctions[7] = - ManifestExecutionFunction(this.incrementCounter2.selector, new string[](0)); - manifest.executionFunctions[8] = - ManifestExecutionFunction(this.setNumberCounter3.selector, new string[](0)); - manifest.executionFunctions[9] = - ManifestExecutionFunction(this.getNumberCounter3.selector, new string[](0)); - manifest.executionFunctions[10] = - ManifestExecutionFunction(this.incrementCounter3.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](11); + manifest.executionFunctions[0] = this.useEFPPermissionAllowed.selector; + manifest.executionFunctions[1] = this.useEFPPermissionNotAllowed.selector; + manifest.executionFunctions[2] = this.setNumberCounter1.selector; + manifest.executionFunctions[3] = this.getNumberCounter1.selector; + manifest.executionFunctions[4] = this.incrementCounter1.selector; + manifest.executionFunctions[5] = this.setNumberCounter2.selector; + manifest.executionFunctions[6] = this.getNumberCounter2.selector; + manifest.executionFunctions[7] = this.incrementCounter2.selector; + manifest.executionFunctions[8] = this.setNumberCounter3.selector; + manifest.executionFunctions[9] = this.getNumberCounter3.selector; + manifest.executionFunctions[10] = this.incrementCounter3.selector; manifest.runtimeValidationFunctions = new ManifestAssociatedFunction[](11); @@ -67,7 +55,7 @@ contract EFPCallerPlugin is BasePlugin { for (uint256 i = 0; i < manifest.executionFunctions.length; i++) { manifest.runtimeValidationFunctions[i] = ManifestAssociatedFunction({ - executionSelector: manifest.executionFunctions[i].selector, + executionSelector: manifest.executionFunctions[i], associatedFunction: alwaysAllowValidationFunction }); } @@ -182,7 +170,7 @@ contract EFPCallerPlugin is BasePlugin { } } -contract EFPCallerPluginAnyExternal is BasePlugin { +contract EFPCallerPluginAnyExternal is BaseTestPlugin { function onInstall(bytes calldata) external override {} function onUninstall(bytes calldata) external override {} @@ -190,9 +178,8 @@ contract EFPCallerPluginAnyExternal is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = - ManifestExecutionFunction(this.passthroughExecute.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.passthroughExecute.selector; manifest.runtimeValidationFunctions = new ManifestAssociatedFunction[](1); manifest.runtimeValidationFunctions[0] = ManifestAssociatedFunction({ @@ -204,7 +191,7 @@ contract EFPCallerPluginAnyExternal is BasePlugin { }) }); - manifest.permitAnyExternalContract = true; + manifest.permitAnyExternalAddress = true; return manifest; } @@ -219,7 +206,7 @@ contract EFPCallerPluginAnyExternal is BasePlugin { } // Create pre and post permitted call hooks for calling ResultCreatorPlugin.foo via `executeFromPlugin` -contract EFPPermittedCallHookPlugin is BasePlugin { +contract EFPPermittedCallHookPlugin is BaseTestPlugin { bool public preExecHookCalled; bool public postExecHookCalled; @@ -242,8 +229,8 @@ contract EFPPermittedCallHookPlugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.performEFPCall.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.performEFPCall.selector; manifest.runtimeValidationFunctions = new ManifestAssociatedFunction[](1); manifest.runtimeValidationFunctions[0] = ManifestAssociatedFunction({ @@ -282,7 +269,7 @@ contract EFPPermittedCallHookPlugin is BasePlugin { } // Creates pre and post permitted call hooks for `executeFromPluginExternal` -contract EFPExternalPermittedCallHookPlugin is BasePlugin { +contract EFPExternalPermittedCallHookPlugin is BaseTestPlugin { bool public preExecHookCalled; bool public postExecHookCalled; @@ -305,8 +292,8 @@ contract EFPExternalPermittedCallHookPlugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.performIncrement.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.performIncrement.selector; manifest.runtimeValidationFunctions = new ManifestAssociatedFunction[](1); manifest.runtimeValidationFunctions[0] = ManifestAssociatedFunction({ @@ -333,7 +320,7 @@ contract EFPExternalPermittedCallHookPlugin is BasePlugin { }) }); - manifest.permitAnyExternalContract = true; + manifest.permitAnyExternalAddress = true; return manifest; } diff --git a/test/mocks/plugins/ManifestValidityMocks.sol b/test/mocks/plugins/ManifestValidityMocks.sol index 4241a4d2..6ec719f4 100644 --- a/test/mocks/plugins/ManifestValidityMocks.sol +++ b/test/mocks/plugins/ManifestValidityMocks.sol @@ -7,16 +7,15 @@ import { ManifestAssociatedFunction, ManifestExecutionHook, ManifestExternalCallPermission, - PluginManifest, - ManifestExecutionFunction + PluginManifest } from "../../../src/interfaces/IPlugin.sol"; import {IStandardExecutor} from "../../../src/interfaces/IStandardExecutor.sol"; import {IPluginExecutor} from "../../../src/interfaces/IPluginExecutor.sol"; import {IPlugin} from "../../../src/interfaces/IPlugin.sol"; -import {BasePlugin} from "../../../src/plugins/BasePlugin.sol"; +import {BaseTestPlugin} from "./BaseTestPlugin.sol"; import {FunctionReference} from "../../../src/libraries/FunctionReferenceLib.sol"; -contract BadValidationMagicValue_UserOp_Plugin is BasePlugin { +contract BadValidationMagicValue_UserOp_Plugin is BaseTestPlugin { function onInstall(bytes calldata) external override {} function onUninstall(bytes calldata) external override {} @@ -28,8 +27,8 @@ contract BadValidationMagicValue_UserOp_Plugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.foo.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.foo.selector; manifest.userOpValidationFunctions = new ManifestAssociatedFunction[](1); manifest.userOpValidationFunctions[0] = ManifestAssociatedFunction({ @@ -46,7 +45,7 @@ contract BadValidationMagicValue_UserOp_Plugin is BasePlugin { } } -contract BadValidationMagicValue_PreRuntimeValidationHook_Plugin is BasePlugin { +contract BadValidationMagicValue_PreRuntimeValidationHook_Plugin is BaseTestPlugin { function onInstall(bytes calldata) external override {} function onUninstall(bytes calldata) external override {} @@ -58,8 +57,8 @@ contract BadValidationMagicValue_PreRuntimeValidationHook_Plugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.foo.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.foo.selector; manifest.runtimeValidationFunctions = new ManifestAssociatedFunction[](1); manifest.runtimeValidationFunctions[0] = ManifestAssociatedFunction({ @@ -72,7 +71,6 @@ contract BadValidationMagicValue_PreRuntimeValidationHook_Plugin is BasePlugin { }); manifest.preRuntimeValidationHooks = new ManifestAssociatedFunction[](1); - // Illegal assignment: validation always allow only usable on runtime validation functions manifest.preRuntimeValidationHooks[0] = ManifestAssociatedFunction({ executionSelector: this.foo.selector, @@ -87,7 +85,7 @@ contract BadValidationMagicValue_PreRuntimeValidationHook_Plugin is BasePlugin { } } -contract BadValidationMagicValue_PreUserOpValidationHook_Plugin is BasePlugin { +contract BadValidationMagicValue_PreUserOpValidationHook_Plugin is BaseTestPlugin { function onInstall(bytes calldata) external override {} function onUninstall(bytes calldata) external override {} @@ -99,8 +97,8 @@ contract BadValidationMagicValue_PreUserOpValidationHook_Plugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.foo.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.foo.selector; manifest.userOpValidationFunctions = new ManifestAssociatedFunction[](1); manifest.userOpValidationFunctions[0] = ManifestAssociatedFunction({ @@ -113,7 +111,6 @@ contract BadValidationMagicValue_PreUserOpValidationHook_Plugin is BasePlugin { }); manifest.preUserOpValidationHooks = new ManifestAssociatedFunction[](1); - // Illegal assignment: validation always allow only usable on runtime validation functions manifest.preUserOpValidationHooks[0] = ManifestAssociatedFunction({ executionSelector: this.foo.selector, @@ -128,7 +125,7 @@ contract BadValidationMagicValue_PreUserOpValidationHook_Plugin is BasePlugin { } } -contract BadValidationMagicValue_PreExecHook_Plugin is BasePlugin { +contract BadValidationMagicValue_PreExecHook_Plugin is BaseTestPlugin { function onInstall(bytes calldata) external override {} function onUninstall(bytes calldata) external override {} @@ -140,8 +137,8 @@ contract BadValidationMagicValue_PreExecHook_Plugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.foo.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.foo.selector; manifest.executionHooks = new ManifestExecutionHook[](1); @@ -164,7 +161,7 @@ contract BadValidationMagicValue_PreExecHook_Plugin is BasePlugin { } } -contract BadValidationMagicValue_PostExecHook_Plugin is BasePlugin { +contract BadValidationMagicValue_PostExecHook_Plugin is BaseTestPlugin { function onInstall(bytes calldata) external override {} function onUninstall(bytes calldata) external override {} @@ -176,11 +173,10 @@ contract BadValidationMagicValue_PostExecHook_Plugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.foo.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.foo.selector; manifest.executionHooks = new ManifestExecutionHook[](1); - // Illegal assignment: validation always allow only usable on runtime validation functions manifest.executionHooks[0] = ManifestExecutionHook({ executionSelector: this.foo.selector, @@ -200,7 +196,7 @@ contract BadValidationMagicValue_PostExecHook_Plugin is BasePlugin { } } -contract BadHookMagicValue_UserOpValidationFunction_Plugin is BasePlugin { +contract BadHookMagicValue_UserOpValidationFunction_Plugin is BaseTestPlugin { function onInstall(bytes calldata) external override {} function onUninstall(bytes calldata) external override {} @@ -212,8 +208,8 @@ contract BadHookMagicValue_UserOpValidationFunction_Plugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.foo.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.foo.selector; manifest.userOpValidationFunctions = new ManifestAssociatedFunction[](1); manifest.userOpValidationFunctions[0] = ManifestAssociatedFunction({ @@ -229,7 +225,7 @@ contract BadHookMagicValue_UserOpValidationFunction_Plugin is BasePlugin { } } -contract BadHookMagicValue_RuntimeValidationFunction_Plugin is BasePlugin { +contract BadHookMagicValue_RuntimeValidationFunction_Plugin is BaseTestPlugin { function onInstall(bytes calldata) external override {} function onUninstall(bytes calldata) external override {} @@ -241,8 +237,8 @@ contract BadHookMagicValue_RuntimeValidationFunction_Plugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.foo.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.foo.selector; manifest.runtimeValidationFunctions = new ManifestAssociatedFunction[](1); manifest.runtimeValidationFunctions[0] = ManifestAssociatedFunction({ @@ -258,7 +254,7 @@ contract BadHookMagicValue_RuntimeValidationFunction_Plugin is BasePlugin { } } -contract BadHookMagicValue_PostExecHook_Plugin is BasePlugin { +contract BadHookMagicValue_PostExecHook_Plugin is BaseTestPlugin { function onInstall(bytes calldata) external override {} function onUninstall(bytes calldata) external override {} @@ -270,11 +266,10 @@ contract BadHookMagicValue_PostExecHook_Plugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.foo.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.foo.selector; manifest.executionHooks = new ManifestExecutionHook[](1); - // Illegal assignment: hook always deny only usable on runtime validation functions manifest.executionHooks[0] = ManifestExecutionHook({ executionSelector: this.foo.selector, diff --git a/test/mocks/plugins/ReturnDataPluginMocks.sol b/test/mocks/plugins/ReturnDataPluginMocks.sol index c0dd4d85..e226a329 100644 --- a/test/mocks/plugins/ReturnDataPluginMocks.sol +++ b/test/mocks/plugins/ReturnDataPluginMocks.sol @@ -6,13 +6,12 @@ import { ManifestAssociatedFunctionType, ManifestAssociatedFunction, ManifestExternalCallPermission, - PluginManifest, - ManifestExecutionFunction + PluginManifest } from "../../../src/interfaces/IPlugin.sol"; import {IStandardExecutor} from "../../../src/interfaces/IStandardExecutor.sol"; import {IPluginExecutor} from "../../../src/interfaces/IPluginExecutor.sol"; import {IPlugin} from "../../../src/interfaces/IPlugin.sol"; -import {BasePlugin} from "../../../src/plugins/BasePlugin.sol"; +import {BaseTestPlugin} from "./BaseTestPlugin.sol"; import {FunctionReference} from "../../../src/libraries/FunctionReferenceLib.sol"; contract RegularResultContract { @@ -25,7 +24,7 @@ contract RegularResultContract { } } -contract ResultCreatorPlugin is BasePlugin { +contract ResultCreatorPlugin is BaseTestPlugin { function onInstall(bytes calldata) external override {} function onUninstall(bytes calldata) external override {} @@ -41,9 +40,9 @@ contract ResultCreatorPlugin is BasePlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](2); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.foo.selector, new string[](0)); - manifest.executionFunctions[1] = ManifestExecutionFunction(this.bar.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](2); + manifest.executionFunctions[0] = this.foo.selector; + manifest.executionFunctions[1] = this.bar.selector; manifest.runtimeValidationFunctions = new ManifestAssociatedFunction[](1); manifest.runtimeValidationFunctions[0] = ManifestAssociatedFunction({ @@ -59,7 +58,7 @@ contract ResultCreatorPlugin is BasePlugin { } } -contract ResultConsumerPlugin is BasePlugin { +contract ResultConsumerPlugin is BaseTestPlugin { ResultCreatorPlugin public immutable resultCreator; RegularResultContract public immutable regularResultContract; @@ -117,11 +116,9 @@ contract ResultConsumerPlugin is BasePlugin { function _innerPluginManifest() internal view returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](2); - manifest.executionFunctions[0] = - ManifestExecutionFunction(this.checkResultEFPFallback.selector, new string[](0)); - manifest.executionFunctions[1] = - ManifestExecutionFunction(this.checkResultEFPExternal.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](2); + manifest.executionFunctions[0] = this.checkResultEFPFallback.selector; + manifest.executionFunctions[1] = this.checkResultEFPExternal.selector; manifest.runtimeValidationFunctions = new ManifestAssociatedFunction[](2); manifest.runtimeValidationFunctions[0] = ManifestAssociatedFunction({ diff --git a/test/mocks/plugins/ValidationPluginMocks.sol b/test/mocks/plugins/ValidationPluginMocks.sol index adcc7052..1e6cc941 100644 --- a/test/mocks/plugins/ValidationPluginMocks.sol +++ b/test/mocks/plugins/ValidationPluginMocks.sol @@ -7,12 +7,11 @@ import { ManifestFunction, ManifestAssociatedFunctionType, ManifestAssociatedFunction, - PluginManifest, - ManifestExecutionFunction + PluginManifest } from "../../../src/interfaces/IPlugin.sol"; -import {BasePlugin} from "../../../src/plugins/BasePlugin.sol"; +import {BaseTestPlugin} from "./BaseTestPlugin.sol"; -abstract contract MockBaseUserOpValidationPlugin is BasePlugin { +abstract contract MockBaseUserOpValidationPlugin is BaseTestPlugin { enum FunctionId { USER_OP_VALIDATION, PRE_USER_OP_VALIDATION_HOOK_1, @@ -76,8 +75,8 @@ contract MockUserOpValidationPlugin is MockBaseUserOpValidationPlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.foo.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.foo.selector; manifest.userOpValidationFunctions = new ManifestAssociatedFunction[](1); manifest.userOpValidationFunctions[0] = ManifestAssociatedFunction({ @@ -114,8 +113,8 @@ contract MockUserOpValidation1HookPlugin is MockBaseUserOpValidationPlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.bar.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.bar.selector; ManifestFunction memory userOpValidationFunctionRef = ManifestFunction({ functionType: ManifestAssociatedFunctionType.SELF, @@ -166,8 +165,8 @@ contract MockUserOpValidation2HookPlugin is MockBaseUserOpValidationPlugin { function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction(this.baz.selector, new string[](0)); + manifest.executionFunctions = new bytes4[](1); + manifest.executionFunctions[0] = this.baz.selector; ManifestFunction memory userOpValidationFunctionRef = ManifestFunction({ functionType: ManifestAssociatedFunctionType.SELF,