diff --git a/src/account/AccountLoupe.sol b/src/account/AccountLoupe.sol index d652f45c..8817f4b7 100644 --- a/src/account/AccountLoupe.sol +++ b/src/account/AccountLoupe.sol @@ -6,7 +6,7 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import {IAccountLoupe, ExecutionHook} from "../interfaces/IAccountLoupe.sol"; -import {FunctionReference, IPluginManager} from "../interfaces/IPluginManager.sol"; +import {PackedPluginEntity, IPluginManager} from "../interfaces/IPluginManager.sol"; import {IStandardExecutor} from "../interfaces/IStandardExecutor.sol"; import {getAccountStorage, toExecutionHook, toSelector} from "./AccountStorage.sol"; @@ -29,7 +29,7 @@ abstract contract AccountLoupe is IAccountLoupe { } /// @inheritdoc IAccountLoupe - function getSelectors(FunctionReference validationFunction) external view returns (bytes4[] memory) { + function getSelectors(PackedPluginEntity validationFunction) external view returns (bytes4[] memory) { uint256 length = getAccountStorage().validationData[validationFunction].selectors.length(); bytes4[] memory selectors = new bytes4[](length); @@ -61,7 +61,7 @@ abstract contract AccountLoupe is IAccountLoupe { } /// @inheritdoc IAccountLoupe - function getPermissionHooks(FunctionReference validationFunction) + function getPermissionHooks(PackedPluginEntity validationFunction) external view override @@ -79,11 +79,11 @@ abstract contract AccountLoupe is IAccountLoupe { } /// @inheritdoc IAccountLoupe - function getPreValidationHooks(FunctionReference validationFunction) + function getPreValidationHooks(PackedPluginEntity validationFunction) external view override - returns (FunctionReference[] memory preValidationHooks) + returns (PackedPluginEntity[] memory preValidationHooks) { preValidationHooks = getAccountStorage().validationData[validationFunction].preValidationHooks; } diff --git a/src/account/AccountStorage.sol b/src/account/AccountStorage.sol index 383f02e2..47290283 100644 --- a/src/account/AccountStorage.sol +++ b/src/account/AccountStorage.sol @@ -5,7 +5,7 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import {ExecutionHook} from "../interfaces/IAccountLoupe.sol"; -import {FunctionReference} from "../interfaces/IPluginManager.sol"; +import {PackedPluginEntity} from "../interfaces/IPluginManager.sol"; // bytes = keccak256("ERC6900.UpgradeableModularAccount.Storage") bytes32 constant _ACCOUNT_STORAGE_SLOT = 0x9f09680beaa4e5c9f38841db2460c401499164f368baef687948c315d9073e40; @@ -33,7 +33,7 @@ struct ValidationData { // How many execution hooks require the UO context. uint8 requireUOHookCount; // The pre validation hooks for this function selector. - FunctionReference[] preValidationHooks; + PackedPluginEntity[] preValidationHooks; // Permission hooks for this validation function. EnumerableSet.Bytes32Set permissionHooks; // The set of selectors that may be validated by this validation function. @@ -48,7 +48,7 @@ struct AccountStorage { EnumerableMap.AddressToUintMap pluginManifestHashes; // Execution functions and their associated functions mapping(bytes4 => SelectorData) selectorData; - mapping(FunctionReference validationFunction => ValidationData) validationData; + mapping(PackedPluginEntity validationFunction => ValidationData) validationData; // For ERC165 introspection mapping(bytes4 => uint256) supportedIfaces; } @@ -61,12 +61,12 @@ function getAccountStorage() pure returns (AccountStorage storage _storage) { using EnumerableSet for EnumerableSet.Bytes32Set; -function toSetValue(FunctionReference functionReference) pure returns (bytes32) { - return bytes32(FunctionReference.unwrap(functionReference)); +function toSetValue(PackedPluginEntity functionReference) pure returns (bytes32) { + return bytes32(PackedPluginEntity.unwrap(functionReference)); } -function toFunctionReference(bytes32 setValue) pure returns (FunctionReference) { - return FunctionReference.wrap(bytes24(setValue)); +function toPackedPluginEntity(bytes32 setValue) pure returns (PackedPluginEntity) { + return PackedPluginEntity.wrap(bytes24(setValue)); } // ExecutionHook layout: @@ -75,16 +75,16 @@ function toFunctionReference(bytes32 setValue) pure returns (FunctionReference) // 0x____________________________________________BB__________________ is post hook function toSetValue(ExecutionHook memory executionHook) pure returns (bytes32) { - return bytes32(FunctionReference.unwrap(executionHook.hookFunction)) + return bytes32(PackedPluginEntity.unwrap(executionHook.hookFunction)) | bytes32(executionHook.isPreHook ? uint256(1) << 56 : 0) | bytes32(executionHook.isPostHook ? uint256(1) << 48 : 0); } function toExecutionHook(bytes32 setValue) pure - returns (FunctionReference hookFunction, bool isPreHook, bool isPostHook) + returns (PackedPluginEntity hookFunction, bool isPreHook, bool isPostHook) { - hookFunction = FunctionReference.wrap(bytes24(setValue)); + hookFunction = PackedPluginEntity.wrap(bytes24(setValue)); isPreHook = (uint256(setValue) >> 56) & 0xFF == 1; isPostHook = (uint256(setValue) >> 48) & 0xFF == 1; } @@ -98,15 +98,15 @@ function toSelector(bytes32 setValue) pure returns (bytes4) { } /// @dev Helper function to get all elements of a set into memory. -function toFunctionReferenceArray(EnumerableSet.Bytes32Set storage set) +function toPackedPluginEntityArray(EnumerableSet.Bytes32Set storage set) view - returns (FunctionReference[] memory) + returns (PackedPluginEntity[] memory) { uint256 length = set.length(); - FunctionReference[] memory result = new FunctionReference[](length); + PackedPluginEntity[] memory result = new PackedPluginEntity[](length); for (uint256 i = 0; i < length; ++i) { bytes32 key = set.at(i); - result[i] = FunctionReference.wrap(bytes24(key)); + result[i] = PackedPluginEntity.wrap(bytes24(key)); } return result; } diff --git a/src/account/PluginManager2.sol b/src/account/PluginManager2.sol index 28eb0ecf..c1dae3ff 100644 --- a/src/account/PluginManager2.sol +++ b/src/account/PluginManager2.sol @@ -4,10 +4,10 @@ pragma solidity ^0.8.25; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {IPlugin} from "../interfaces/IPlugin.sol"; -import {FunctionReference, ValidationConfig} from "../interfaces/IPluginManager.sol"; -import {FunctionReferenceLib} from "../helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntity, ValidationConfig} from "../interfaces/IPluginManager.sol"; +import {PackedPluginEntityLib} from "../helpers/PackedPluginEntityLib.sol"; import {ValidationConfigLib} from "../helpers/ValidationConfigLib.sol"; -import {ValidationData, getAccountStorage, toSetValue, toFunctionReference} from "./AccountStorage.sol"; +import {ValidationData, getAccountStorage, toSetValue, toPackedPluginEntity} from "./AccountStorage.sol"; import {ExecutionHook} from "../interfaces/IAccountLoupe.sol"; // Temporary additional functions for a user-controlled install flow for validation functions. @@ -18,10 +18,10 @@ abstract contract PluginManager2 { // Index marking the start of the data for the validation function. uint8 internal constant _RESERVED_VALIDATION_DATA_INDEX = 255; - error PreValidationAlreadySet(FunctionReference validationFunction, FunctionReference preValidationFunction); - error ValidationAlreadySet(bytes4 selector, FunctionReference validationFunction); - error ValidationNotSet(bytes4 selector, FunctionReference validationFunction); - error PermissionAlreadySet(FunctionReference validationFunction, ExecutionHook hook); + error PreValidationAlreadySet(PackedPluginEntity validationFunction, PackedPluginEntity preValidationFunction); + error ValidationAlreadySet(bytes4 selector, PackedPluginEntity validationFunction); + error ValidationNotSet(bytes4 selector, PackedPluginEntity validationFunction); + error PermissionAlreadySet(PackedPluginEntity validationFunction, ExecutionHook hook); error PreValidationHookLimitExceeded(); function _installValidation( @@ -35,16 +35,16 @@ abstract contract PluginManager2 { getAccountStorage().validationData[validationConfig.functionReference()]; if (preValidationHooks.length > 0) { - (FunctionReference[] memory preValidationFunctions, bytes[] memory initDatas) = - abi.decode(preValidationHooks, (FunctionReference[], bytes[])); + (PackedPluginEntity[] memory preValidationFunctions, bytes[] memory initDatas) = + abi.decode(preValidationHooks, (PackedPluginEntity[], bytes[])); for (uint256 i = 0; i < preValidationFunctions.length; ++i) { - FunctionReference preValidationFunction = preValidationFunctions[i]; + PackedPluginEntity preValidationFunction = preValidationFunctions[i]; _validationData.preValidationHooks.push(preValidationFunction); if (initDatas[i].length > 0) { - (address preValidationPlugin,) = FunctionReferenceLib.unpack(preValidationFunction); + (address preValidationPlugin,) = PackedPluginEntityLib.unpack(preValidationFunction); IPlugin(preValidationPlugin).onInstall(initDatas[i]); } } @@ -67,7 +67,7 @@ abstract contract PluginManager2 { } if (initDatas[i].length > 0) { - (address executionPlugin,) = FunctionReferenceLib.unpack(permissionFunction.hookFunction); + (address executionPlugin,) = PackedPluginEntityLib.unpack(permissionFunction.hookFunction); IPlugin(executionPlugin).onInstall(initDatas[i]); } } @@ -90,7 +90,7 @@ abstract contract PluginManager2 { } function _uninstallValidation( - FunctionReference validationFunction, + PackedPluginEntity validationFunction, bytes calldata uninstallData, bytes calldata preValidationHookUninstallData, bytes calldata permissionHookUninstallData @@ -104,11 +104,11 @@ abstract contract PluginManager2 { bytes[] memory preValidationHookUninstallDatas = abi.decode(preValidationHookUninstallData, (bytes[])); // Clear pre validation hooks - FunctionReference[] storage preValidationHooks = _validationData.preValidationHooks; + PackedPluginEntity[] storage preValidationHooks = _validationData.preValidationHooks; for (uint256 i = 0; i < preValidationHooks.length; ++i) { - FunctionReference preValidationFunction = preValidationHooks[i]; + PackedPluginEntity preValidationFunction = preValidationHooks[i]; if (preValidationHookUninstallDatas[0].length > 0) { - (address preValidationPlugin,) = FunctionReferenceLib.unpack(preValidationFunction); + (address preValidationPlugin,) = PackedPluginEntityLib.unpack(preValidationFunction); IPlugin(preValidationPlugin).onUninstall(preValidationHookUninstallDatas[0]); } } @@ -122,9 +122,9 @@ abstract contract PluginManager2 { EnumerableSet.Bytes32Set storage permissionHooks = _validationData.permissionHooks; uint256 i = 0; while (permissionHooks.length() > 0) { - FunctionReference permissionHook = toFunctionReference(permissionHooks.at(0)); + PackedPluginEntity permissionHook = toPackedPluginEntity(permissionHooks.at(0)); permissionHooks.remove(toSetValue(permissionHook)); - (address permissionHookPlugin,) = FunctionReferenceLib.unpack(permissionHook); + (address permissionHookPlugin,) = PackedPluginEntityLib.unpack(permissionHook); IPlugin(permissionHookPlugin).onUninstall(permissionHookUninstallDatas[i++]); } } @@ -137,7 +137,7 @@ abstract contract PluginManager2 { } if (uninstallData.length > 0) { - (address plugin,) = FunctionReferenceLib.unpack(validationFunction); + (address plugin,) = PackedPluginEntityLib.unpack(validationFunction); IPlugin(plugin).onUninstall(uninstallData); } } diff --git a/src/account/PluginManagerInternals.sol b/src/account/PluginManagerInternals.sol index 90f9b05b..765991ea 100644 --- a/src/account/PluginManagerInternals.sol +++ b/src/account/PluginManagerInternals.sol @@ -5,17 +5,17 @@ import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165C import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; -import {FunctionReferenceLib} from "../helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntityLib} from "../helpers/PackedPluginEntityLib.sol"; import {IPlugin, ManifestExecutionHook, ManifestValidation, PluginManifest} from "../interfaces/IPlugin.sol"; import {ExecutionHook} from "../interfaces/IAccountLoupe.sol"; -import {FunctionReference, IPluginManager} from "../interfaces/IPluginManager.sol"; +import {PackedPluginEntity, IPluginManager} from "../interfaces/IPluginManager.sol"; import {KnownSelectors} from "../helpers/KnownSelectors.sol"; import {AccountStorage, getAccountStorage, SelectorData, toSetValue} from "./AccountStorage.sol"; abstract contract PluginManagerInternals is IPluginManager { using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableMap for EnumerableMap.AddressToUintMap; - using FunctionReferenceLib for FunctionReference; + using PackedPluginEntityLib for PackedPluginEntity; error ArrayLengthMismatch(); error Erc4337FunctionNotAllowed(bytes4 selector); @@ -23,13 +23,13 @@ abstract contract PluginManagerInternals is IPluginManager { error InvalidPluginManifest(); error IPluginFunctionNotAllowed(bytes4 selector); error NativeFunctionNotAllowed(bytes4 selector); - error NullFunctionReference(); + error NullPackedPluginEntity(); error NullPlugin(); error PluginAlreadyInstalled(address plugin); error PluginInstallCallbackFailed(address plugin, bytes revertReason); error PluginInterfaceNotSupported(address plugin); error PluginNotInstalled(address plugin); - error ValidationFunctionAlreadySet(bytes4 selector, FunctionReference validationFunction); + error ValidationFunctionAlreadySet(bytes4 selector, PackedPluginEntity validationFunction); // Storage update operations @@ -78,7 +78,7 @@ abstract contract PluginManagerInternals is IPluginManager { function _addValidationFunction(address plugin, ManifestValidation memory mv) internal { AccountStorage storage _storage = getAccountStorage(); - FunctionReference validationFunction = FunctionReferenceLib.pack(plugin, mv.entityId); + PackedPluginEntity validationFunction = PackedPluginEntityLib.pack(plugin, mv.entityId); if (mv.isDefault) { _storage.validationData[validationFunction].isGlobal = true; @@ -99,7 +99,7 @@ abstract contract PluginManagerInternals is IPluginManager { function _removeValidationFunction(address plugin, ManifestValidation memory mv) internal { AccountStorage storage _storage = getAccountStorage(); - FunctionReference validationFunction = FunctionReferenceLib.pack(plugin, mv.entityId); + PackedPluginEntity validationFunction = PackedPluginEntityLib.pack(plugin, mv.entityId); _storage.validationData[validationFunction].isGlobal = false; _storage.validationData[validationFunction].isSignatureValidation = false; @@ -113,7 +113,7 @@ abstract contract PluginManagerInternals is IPluginManager { function _addExecHooks( EnumerableSet.Bytes32Set storage hooks, - FunctionReference hookFunction, + PackedPluginEntity hookFunction, bool isPreExecHook, bool isPostExecHook ) internal { @@ -126,7 +126,7 @@ abstract contract PluginManagerInternals is IPluginManager { function _removeExecHooks( EnumerableSet.Bytes32Set storage hooks, - FunctionReference hookFunction, + PackedPluginEntity hookFunction, bool isPreExecHook, bool isPostExecHook ) internal { @@ -183,7 +183,7 @@ abstract contract PluginManagerInternals is IPluginManager { for (uint256 i = 0; i < length; ++i) { ManifestExecutionHook memory mh = manifest.executionHooks[i]; EnumerableSet.Bytes32Set storage execHooks = _storage.selectorData[mh.executionSelector].executionHooks; - FunctionReference hookFunction = FunctionReferenceLib.pack(plugin, mh.entityId); + PackedPluginEntity hookFunction = PackedPluginEntityLib.pack(plugin, mh.entityId); _addExecHooks(execHooks, hookFunction, mh.isPreHook, mh.isPostHook); } @@ -223,7 +223,7 @@ abstract contract PluginManagerInternals is IPluginManager { uint256 length = manifest.executionHooks.length; for (uint256 i = 0; i < length; ++i) { ManifestExecutionHook memory mh = manifest.executionHooks[i]; - FunctionReference hookFunction = FunctionReferenceLib.pack(plugin, mh.entityId); + PackedPluginEntity hookFunction = PackedPluginEntityLib.pack(plugin, mh.entityId); EnumerableSet.Bytes32Set storage execHooks = _storage.selectorData[mh.executionSelector].executionHooks; _removeExecHooks(execHooks, hookFunction, mh.isPreHook, mh.isPostHook); } diff --git a/src/account/UpgradeableModularAccount.sol b/src/account/UpgradeableModularAccount.sol index 8e7c2ec6..5f745c8d 100644 --- a/src/account/UpgradeableModularAccount.sol +++ b/src/account/UpgradeableModularAccount.sol @@ -10,7 +10,7 @@ import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import {FunctionReferenceLib} from "../helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntityLib} from "../helpers/PackedPluginEntityLib.sol"; import {ValidationConfigLib} from "../helpers/ValidationConfigLib.sol"; import {SparseCalldataSegmentLib} from "../helpers/SparseCalldataSegmentLib.sol"; import {_coalescePreValidation, _coalesceValidation} from "../helpers/ValidationDataHelpers.sol"; @@ -18,7 +18,7 @@ import {IPlugin, PluginManifest} from "../interfaces/IPlugin.sol"; import {IValidation} from "../interfaces/IValidation.sol"; import {IValidationHook} from "../interfaces/IValidationHook.sol"; import {IExecutionHook} from "../interfaces/IExecutionHook.sol"; -import {FunctionReference, IPluginManager, ValidationConfig} from "../interfaces/IPluginManager.sol"; +import {PackedPluginEntity, IPluginManager, ValidationConfig} from "../interfaces/IPluginManager.sol"; import {IStandardExecutor, Call} from "../interfaces/IStandardExecutor.sol"; import {AccountExecutor} from "./AccountExecutor.sol"; import {AccountLoupe} from "./AccountLoupe.sol"; @@ -41,13 +41,13 @@ contract UpgradeableModularAccount is UUPSUpgradeable { using EnumerableSet for EnumerableSet.Bytes32Set; - using FunctionReferenceLib for FunctionReference; + using PackedPluginEntityLib for PackedPluginEntity; using ValidationConfigLib for ValidationConfig; using SparseCalldataSegmentLib for bytes; struct PostExecToRun { bytes preExecHookReturnData; - FunctionReference postExecHook; + PackedPluginEntity postExecHook; } IEntryPoint private immutable _ENTRY_POINT; @@ -164,7 +164,7 @@ contract UpgradeableModularAccount is revert NotEntryPoint(); } - FunctionReference userOpValidationFunction = FunctionReference.wrap(bytes24(userOp.signature[:24])); + PackedPluginEntity userOpValidationFunction = PackedPluginEntity.wrap(bytes24(userOp.signature[:24])); PostExecToRun[] memory postPermissionHooks = _doPreHooks(getAccountStorage().validationData[userOpValidationFunction].permissionHooks, msg.data); @@ -217,7 +217,7 @@ contract UpgradeableModularAccount is returns (bytes memory) { // Revert if the provided `authorization` less than 21 bytes long, rather than right-padding. - FunctionReference runtimeValidationFunction = FunctionReference.wrap(bytes24(authorization[:24])); + PackedPluginEntity runtimeValidationFunction = PackedPluginEntity.wrap(bytes24(authorization[:24])); // Check if the runtime validation function is allowed to be called bool isGlobalValidation = uint8(authorization[24]) == 1; @@ -301,7 +301,7 @@ contract UpgradeableModularAccount is /// @inheritdoc IPluginManager /// @notice May be validated by a global validation. function uninstallValidation( - FunctionReference validationFunction, + PackedPluginEntity validationFunction, bytes calldata uninstallData, bytes calldata preValidationHookUninstallData, bytes calldata permissionHookUninstallData @@ -341,7 +341,7 @@ contract UpgradeableModularAccount is function isValidSignature(bytes32 hash, bytes calldata signature) public view override returns (bytes4) { AccountStorage storage _storage = getAccountStorage(); - FunctionReference sigValidation = FunctionReference.wrap(bytes24(signature)); + PackedPluginEntity sigValidation = PackedPluginEntity.wrap(bytes24(signature)); (address plugin, uint32 entityId) = sigValidation.unpack(); if (!_storage.validationData[sigValidation].isSignatureValidation) { @@ -375,7 +375,7 @@ contract UpgradeableModularAccount is } // Revert if the provided `authorization` less than 21 bytes long, rather than right-padding. - FunctionReference userOpValidationFunction = FunctionReference.wrap(bytes24(userOp.signature[:24])); + PackedPluginEntity userOpValidationFunction = PackedPluginEntity.wrap(bytes24(userOp.signature[:24])); bool isGlobalValidation = uint8(userOp.signature[24]) == 1; _checkIfValidationAppliesCallData(userOp.callData, userOpValidationFunction, isGlobalValidation); @@ -396,7 +396,7 @@ contract UpgradeableModularAccount is // To support gas estimation, we don't fail early when the failure is caused by a signature failure function _doUserOpValidation( - FunctionReference userOpValidationFunction, + PackedPluginEntity userOpValidationFunction, PackedUserOperation memory userOp, bytes calldata signature, bytes32 userOpHash @@ -408,7 +408,7 @@ contract UpgradeableModularAccount is uint256 validationData; // Do preUserOpValidation hooks - FunctionReference[] memory preUserOpValidationHooks = + PackedPluginEntity[] memory preUserOpValidationHooks = getAccountStorage().validationData[userOpValidationFunction].preValidationHooks; for (uint256 i = 0; i < preUserOpValidationHooks.length; ++i) { @@ -466,7 +466,7 @@ contract UpgradeableModularAccount is } function _doRuntimeValidation( - FunctionReference runtimeValidationFunction, + PackedPluginEntity runtimeValidationFunction, bytes calldata callData, bytes calldata authorizationData ) internal { @@ -475,7 +475,7 @@ contract UpgradeableModularAccount is (authSegment, authorizationData) = authorizationData.getNextSegment(); // run all preRuntimeValidation hooks - FunctionReference[] memory preRuntimeValidationHooks = + PackedPluginEntity[] memory preRuntimeValidationHooks = getAccountStorage().validationData[runtimeValidationFunction].preValidationHooks; for (uint256 i = 0; i < preRuntimeValidationHooks.length; ++i) { @@ -538,7 +538,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); - (FunctionReference hookFunction,, bool isPostHook) = toExecutionHook(key); + (PackedPluginEntity hookFunction,, bool isPostHook) = toExecutionHook(key); if (isPostHook) { postHooksToRun[i].postExecHook = hookFunction; } @@ -548,7 +548,7 @@ contract UpgradeableModularAccount is // exists. for (uint256 i = 0; i < hooksLength; ++i) { bytes32 key = executionHooks.at(i); - (FunctionReference hookFunction, bool isPreHook, bool isPostHook) = toExecutionHook(key); + (PackedPluginEntity hookFunction, bool isPreHook, bool isPostHook) = toExecutionHook(key); if (isPreHook) { bytes memory preExecHookReturnData; @@ -563,7 +563,7 @@ contract UpgradeableModularAccount is } } - function _runPreExecHook(FunctionReference preExecHook, bytes memory data) + function _runPreExecHook(PackedPluginEntity preExecHook, bytes memory data) internal returns (bytes memory preExecHookReturnData) { @@ -606,7 +606,7 @@ contract UpgradeableModularAccount is function _checkIfValidationAppliesCallData( bytes calldata callData, - FunctionReference validationFunction, + PackedPluginEntity validationFunction, bool isGlobal ) internal view { bytes4 outerSelector = bytes4(callData[:4]); @@ -659,7 +659,7 @@ contract UpgradeableModularAccount is function _checkIfValidationAppliesSelector( bytes4 selector, - FunctionReference validationFunction, + PackedPluginEntity validationFunction, bool isGlobal ) internal view { AccountStorage storage _storage = getAccountStorage(); diff --git a/src/helpers/FunctionReferenceLib.sol b/src/helpers/FunctionReferenceLib.sol deleted file mode 100644 index 6e9c4dc6..00000000 --- a/src/helpers/FunctionReferenceLib.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.25; - -import {FunctionReference} from "../interfaces/IPluginManager.sol"; - -library FunctionReferenceLib { - // Empty or unset function reference. - FunctionReference internal constant _EMPTY_FUNCTION_REFERENCE = FunctionReference.wrap(bytes24(0)); - // Magic value for hooks that should always revert. - FunctionReference internal constant _PRE_HOOK_ALWAYS_DENY = FunctionReference.wrap(bytes24(uint192(2))); - - function pack(address addr, uint32 entityId) internal pure returns (FunctionReference) { - return FunctionReference.wrap(bytes24(bytes20(addr)) | bytes24(uint192(entityId))); - } - - function unpack(FunctionReference fr) internal pure returns (address addr, uint32 entityId) { - bytes24 underlying = FunctionReference.unwrap(fr); - addr = address(bytes20(underlying)); - entityId = uint32(bytes4(underlying << 160)); - } - - function isEmpty(FunctionReference fr) internal pure returns (bool) { - return FunctionReference.unwrap(fr) == bytes24(0); - } - - function notEmpty(FunctionReference fr) internal pure returns (bool) { - return FunctionReference.unwrap(fr) != bytes24(0); - } - - function eq(FunctionReference a, FunctionReference b) internal pure returns (bool) { - return FunctionReference.unwrap(a) == FunctionReference.unwrap(b); - } - - function notEq(FunctionReference a, FunctionReference b) internal pure returns (bool) { - return FunctionReference.unwrap(a) != FunctionReference.unwrap(b); - } -} diff --git a/src/helpers/PackedPluginEntityLib.sol b/src/helpers/PackedPluginEntityLib.sol new file mode 100644 index 00000000..bff90e80 --- /dev/null +++ b/src/helpers/PackedPluginEntityLib.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.25; + +import {PackedPluginEntity} from "../interfaces/IPluginManager.sol"; + +library PackedPluginEntityLib { + // Empty or unset PackedPluginEntity. + PackedPluginEntity internal constant _EMPTY_PACKED_PLUGIN_ENTITY = PackedPluginEntity.wrap(bytes24(0)); + // Magic value for hooks that should always revert. + PackedPluginEntity internal constant _PRE_HOOK_ALWAYS_DENY = PackedPluginEntity.wrap(bytes24(uint192(2))); + + function pack(address addr, uint32 entityId) internal pure returns (PackedPluginEntity) { + return PackedPluginEntity.wrap(bytes24(bytes20(addr)) | bytes24(uint192(entityId))); + } + + function unpack(PackedPluginEntity fr) internal pure returns (address addr, uint32 entityId) { + bytes24 underlying = PackedPluginEntity.unwrap(fr); + addr = address(bytes20(underlying)); + entityId = uint32(bytes4(underlying << 160)); + } + + function isEmpty(PackedPluginEntity fr) internal pure returns (bool) { + return PackedPluginEntity.unwrap(fr) == bytes24(0); + } + + function notEmpty(PackedPluginEntity fr) internal pure returns (bool) { + return PackedPluginEntity.unwrap(fr) != bytes24(0); + } + + function eq(PackedPluginEntity a, PackedPluginEntity b) internal pure returns (bool) { + return PackedPluginEntity.unwrap(a) == PackedPluginEntity.unwrap(b); + } + + function notEq(PackedPluginEntity a, PackedPluginEntity b) internal pure returns (bool) { + return PackedPluginEntity.unwrap(a) != PackedPluginEntity.unwrap(b); + } +} diff --git a/src/helpers/ValidationConfigLib.sol b/src/helpers/ValidationConfigLib.sol index f2dfacea..c295b96e 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 {FunctionReference, ValidationConfig} from "../interfaces/IPluginManager.sol"; +import {PackedPluginEntity, ValidationConfig} from "../interfaces/IPluginManager.sol"; // Validation config is a packed representation of a validation function and flags for its configuration. // Layout: @@ -12,14 +12,14 @@ import {FunctionReference, ValidationConfig} from "../interfaces/IPluginManager. // 0x______________________________________________000000000000000000 // unused library ValidationConfigLib { - function pack(FunctionReference _validationFunction, bool _isGlobal, bool _isSignatureValidation) + function pack(PackedPluginEntity _validationFunction, bool _isGlobal, bool _isSignatureValidation) internal pure returns (ValidationConfig) { return ValidationConfig.wrap( bytes26( - bytes26(FunctionReference.unwrap(_validationFunction)) + bytes26(PackedPluginEntity.unwrap(_validationFunction)) // isGlobal flag stored in the 25th byte | bytes26(bytes32(_isGlobal ? uint256(1) << 56 : 0)) // isSignatureValidation flag stored in the 26th byte @@ -62,10 +62,10 @@ library ValidationConfigLib { function unpack(ValidationConfig config) internal pure - returns (FunctionReference _validationFunction, bool _isGlobal, bool _isSignatureValidation) + returns (PackedPluginEntity _validationFunction, bool _isGlobal, bool _isSignatureValidation) { bytes26 configBytes = ValidationConfig.unwrap(config); - _validationFunction = FunctionReference.wrap(bytes24(configBytes)); + _validationFunction = PackedPluginEntity.wrap(bytes24(configBytes)); _isGlobal = uint8(configBytes[24]) == 1; _isSignatureValidation = uint8(configBytes[25]) == 1; } @@ -78,8 +78,8 @@ library ValidationConfigLib { return uint32(bytes4(ValidationConfig.unwrap(config) << 160)); } - function functionReference(ValidationConfig config) internal pure returns (FunctionReference) { - return FunctionReference.wrap(bytes24(ValidationConfig.unwrap(config))); + function functionReference(ValidationConfig config) internal pure returns (PackedPluginEntity) { + return PackedPluginEntity.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 d74c5940..70e408ec 100644 --- a/src/interfaces/IAccountLoupe.sol +++ b/src/interfaces/IAccountLoupe.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.25; -import {FunctionReference} from "../interfaces/IPluginManager.sol"; +import {PackedPluginEntity} from "../interfaces/IPluginManager.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 { - FunctionReference hookFunction; + PackedPluginEntity hookFunction; bool isPreHook; bool isPostHook; } @@ -21,7 +21,7 @@ interface IAccountLoupe { /// @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(FunctionReference validationFunction) external view returns (bytes4[] memory); + function getSelectors(PackedPluginEntity 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,7 +31,7 @@ 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(FunctionReference validationFunction) + function getPermissionHooks(PackedPluginEntity validationFunction) external view returns (ExecutionHook[] memory); @@ -39,10 +39,10 @@ interface IAccountLoupe { /// @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(FunctionReference validationFunction) + function getPreValidationHooks(PackedPluginEntity validationFunction) external view - returns (FunctionReference[] memory preValidationHooks); + returns (PackedPluginEntity[] memory preValidationHooks); /// @notice Get an array of all installed plugins. /// @return The addresses of all installed plugins. diff --git a/src/interfaces/IPluginManager.sol b/src/interfaces/IPluginManager.sol index 78508645..217ff3af 100644 --- a/src/interfaces/IPluginManager.sol +++ b/src/interfaces/IPluginManager.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.25; -type FunctionReference is bytes24; +type PackedPluginEntity is bytes24; type ValidationConfig is bytes26; @@ -45,7 +45,7 @@ interface IPluginManager { /// data /// @param permissionHookUninstallData Optional data to be decoded and used by the plugin to clear account data function uninstallValidation( - FunctionReference validationFunction, + PackedPluginEntity validationFunction, bytes calldata uninstallData, bytes calldata preValidationHookUninstallData, bytes calldata permissionHookUninstallData diff --git a/standard/ERCs/erc-6900.md b/standard/ERCs/erc-6900.md index 9c80488c..4d42ef46 100644 --- a/standard/ERCs/erc-6900.md +++ b/standard/ERCs/erc-6900.md @@ -106,10 +106,10 @@ Plugin manager interface. Modular Smart Contract Accounts **MUST** implement thi ```solidity // Treats the first 20 bytes as an address, and the last byte as a function identifier. -type FunctionReference is bytes21; +type PackedPluginEntity is bytes21; interface IPluginManager { - event PluginInstalled(address indexed plugin, bytes32 manifestHash, FunctionReference[] dependencies); + event PluginInstalled(address indexed plugin, bytes32 manifestHash, PackedPluginEntity[] dependencies); event PluginUninstalled(address indexed plugin, bool indexed onUninstallSucceeded); @@ -118,13 +118,13 @@ interface IPluginManager { /// @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 /// for the modular account. - /// @param dependencies The dependencies of the plugin, as described in the manifest. Each FunctionReference + /// @param dependencies The dependencies of the plugin, as described in the manifest. Each PackedPluginEntity /// MUST be composed of an installed plugin's address and a function ID of its validation function. function installPlugin( address plugin, bytes32 manifestHash, bytes calldata pluginInstallData, - FunctionReference[] calldata dependencies + PackedPluginEntity[] calldata dependencies ) external; /// @notice Uninstall a plugin from the modular account. @@ -215,13 +215,13 @@ interface IAccountLoupe { /// @notice Config for an execution function, given a selector. struct ExecutionFunctionConfig { address plugin; - FunctionReference validationFunction; + PackedPluginEntity 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 { - FunctionReference hookFunction; + PackedPluginEntity hookFunction; bool isPreHook; bool isPostHook; } @@ -243,7 +243,7 @@ interface IAccountLoupe { function getPreValidationHooks(bytes4 selector) external view - returns (FunctionReference[] memory preValidationHooks); + returns (PackedPluginEntity[] memory preValidationHooks); /// @notice Get an array of all installed plugins. /// @return The addresses of all installed plugins. @@ -513,7 +513,7 @@ Additionally, when the modular account natively implements functions in `IPlugin 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 `FunctionReference`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 `PackedPluginEntity`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. diff --git a/test/account/AccountLoupe.t.sol b/test/account/AccountLoupe.t.sol index 9602393f..122b27ba 100644 --- a/test/account/AccountLoupe.t.sol +++ b/test/account/AccountLoupe.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.19; import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; -import {FunctionReference, FunctionReferenceLib} from "../../src/helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntity, PackedPluginEntityLib} from "../../src/helpers/PackedPluginEntityLib.sol"; import {ExecutionHook} from "../../src/interfaces/IAccountLoupe.sol"; import {IPluginManager} from "../../src/interfaces/IPluginManager.sol"; import {IStandardExecutor} from "../../src/interfaces/IStandardExecutor.sol"; @@ -69,7 +69,7 @@ contract AccountLoupeTest is CustomValidationTestBase { } function test_pluginLoupe_getSelectors() public { - FunctionReference comprehensivePluginValidation = FunctionReferenceLib.pack( + PackedPluginEntity comprehensivePluginValidation = PackedPluginEntityLib.pack( address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.VALIDATION) ); @@ -83,21 +83,21 @@ contract AccountLoupeTest is CustomValidationTestBase { ExecutionHook[] memory hooks = account1.getExecutionHooks(comprehensivePlugin.foo.selector); ExecutionHook[3] memory expectedHooks = [ ExecutionHook({ - hookFunction: FunctionReferenceLib.pack( + hookFunction: PackedPluginEntityLib.pack( address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.BOTH_EXECUTION_HOOKS) ), isPreHook: true, isPostHook: true }), ExecutionHook({ - hookFunction: FunctionReferenceLib.pack( + hookFunction: PackedPluginEntityLib.pack( address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.PRE_EXECUTION_HOOK) ), isPreHook: true, isPostHook: false }), ExecutionHook({ - hookFunction: FunctionReferenceLib.pack( + hookFunction: PackedPluginEntityLib.pack( address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.POST_EXECUTION_HOOK) ), isPreHook: false, @@ -108,8 +108,8 @@ contract AccountLoupeTest is CustomValidationTestBase { assertEq(hooks.length, 3); for (uint256 i = 0; i < hooks.length; i++) { assertEq( - FunctionReference.unwrap(hooks[i].hookFunction), - FunctionReference.unwrap(expectedHooks[i].hookFunction) + PackedPluginEntity.unwrap(hooks[i].hookFunction), + PackedPluginEntity.unwrap(expectedHooks[i].hookFunction) ); assertEq(hooks[i].isPreHook, expectedHooks[i].isPreHook); assertEq(hooks[i].isPostHook, expectedHooks[i].isPostHook); @@ -117,21 +117,21 @@ contract AccountLoupeTest is CustomValidationTestBase { } function test_pluginLoupe_getValidationHooks() public { - FunctionReference[] memory hooks = account1.getPreValidationHooks(_ownerValidation); + PackedPluginEntity[] memory hooks = account1.getPreValidationHooks(_ownerValidation); assertEq(hooks.length, 2); assertEq( - FunctionReference.unwrap(hooks[0]), - FunctionReference.unwrap( - FunctionReferenceLib.pack( + PackedPluginEntity.unwrap(hooks[0]), + PackedPluginEntity.unwrap( + PackedPluginEntityLib.pack( address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.PRE_VALIDATION_HOOK_1) ) ) ); assertEq( - FunctionReference.unwrap(hooks[1]), - FunctionReference.unwrap( - FunctionReferenceLib.pack( + PackedPluginEntity.unwrap(hooks[1]), + PackedPluginEntity.unwrap( + PackedPluginEntityLib.pack( address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.PRE_VALIDATION_HOOK_2) ) ) @@ -144,13 +144,13 @@ contract AccountLoupeTest is CustomValidationTestBase { internal virtual override - returns (FunctionReference, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory) + returns (PackedPluginEntity, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory) { - FunctionReference[] memory preValidationHooks = new FunctionReference[](2); - preValidationHooks[0] = FunctionReferenceLib.pack( + PackedPluginEntity[] memory preValidationHooks = new PackedPluginEntity[](2); + preValidationHooks[0] = PackedPluginEntityLib.pack( address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.PRE_VALIDATION_HOOK_1) ); - preValidationHooks[1] = FunctionReferenceLib.pack( + preValidationHooks[1] = PackedPluginEntityLib.pack( address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.PRE_VALIDATION_HOOK_2) ); diff --git a/test/account/AccountReturnData.t.sol b/test/account/AccountReturnData.t.sol index 1738c722..a8e6ffc3 100644 --- a/test/account/AccountReturnData.t.sol +++ b/test/account/AccountReturnData.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {FunctionReferenceLib} from "../../src/helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntityLib} from "../../src/helpers/PackedPluginEntityLib.sol"; import {Call} from "../../src/interfaces/IStandardExecutor.sol"; import { @@ -58,7 +58,7 @@ contract AccountReturnDataTest is AccountTestBase { (address(regularResultContract), 0, abi.encodeCall(RegularResultContract.foo, ())) ), _encodeSignature( - FunctionReferenceLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), + PackedPluginEntityLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), GLOBAL_VALIDATION, "" ) @@ -86,7 +86,7 @@ contract AccountReturnDataTest is AccountTestBase { bytes memory retData = account1.executeWithAuthorization( abi.encodeCall(account1.executeBatch, (calls)), _encodeSignature( - FunctionReferenceLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), + PackedPluginEntityLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), GLOBAL_VALIDATION, "" ) diff --git a/test/account/GlobalValidationTest.t.sol b/test/account/GlobalValidationTest.t.sol index 9f40f806..77160d3a 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 {FunctionReferenceLib} from "../../src/helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntityLib} from "../../src/helpers/PackedPluginEntityLib.sol"; import {AccountTestBase} from "../utils/AccountTestBase.sol"; @@ -26,7 +26,7 @@ contract GlobalValidationTest is AccountTestBase { account2 = UpgradeableModularAccount(payable(factory.getAddress(owner2, 0))); vm.deal(address(account2), 100 ether); - _ownerValidation = FunctionReferenceLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID); + _ownerValidation = PackedPluginEntityLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID); ethRecipient = makeAddr("ethRecipient"); vm.deal(ethRecipient, 1 wei); diff --git a/test/account/MultiValidation.t.sol b/test/account/MultiValidation.t.sol index 5254c50d..f91ced7e 100644 --- a/test/account/MultiValidation.t.sol +++ b/test/account/MultiValidation.t.sol @@ -8,9 +8,9 @@ import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/Messa import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; -import {FunctionReference} from "../../src/interfaces/IPluginManager.sol"; +import {PackedPluginEntity} from "../../src/interfaces/IPluginManager.sol"; import {IStandardExecutor} from "../../src/interfaces/IStandardExecutor.sol"; -import {FunctionReferenceLib} from "../../src/helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntityLib} from "../../src/helpers/PackedPluginEntityLib.sol"; import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol"; import {SingleOwnerPlugin} from "../../src/plugins/owner/SingleOwnerPlugin.sol"; @@ -42,9 +42,9 @@ contract MultiValidationTest is AccountTestBase { "" ); - FunctionReference[] memory validations = new FunctionReference[](2); - validations[0] = FunctionReferenceLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID); - validations[1] = FunctionReferenceLib.pack(address(validator2), TEST_DEFAULT_OWNER_FUNCTION_ID); + PackedPluginEntity[] memory validations = new PackedPluginEntity[](2); + validations[0] = PackedPluginEntityLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID); + validations[1] = PackedPluginEntityLib.pack(address(validator2), TEST_DEFAULT_OWNER_FUNCTION_ID); bytes4[] memory selectors0 = account1.getSelectors(validations[0]); bytes4[] memory selectors1 = account1.getSelectors(validations[1]); @@ -71,7 +71,7 @@ contract MultiValidationTest is AccountTestBase { account1.executeWithAuthorization( abi.encodeCall(IStandardExecutor.execute, (address(0), 0, "")), _encodeSignature( - FunctionReferenceLib.pack(address(validator2), TEST_DEFAULT_OWNER_FUNCTION_ID), + PackedPluginEntityLib.pack(address(validator2), TEST_DEFAULT_OWNER_FUNCTION_ID), GLOBAL_VALIDATION, "" ) @@ -81,7 +81,7 @@ contract MultiValidationTest is AccountTestBase { account1.executeWithAuthorization( abi.encodeCall(IStandardExecutor.execute, (address(0), 0, "")), _encodeSignature( - FunctionReferenceLib.pack(address(validator2), TEST_DEFAULT_OWNER_FUNCTION_ID), + PackedPluginEntityLib.pack(address(validator2), TEST_DEFAULT_OWNER_FUNCTION_ID), GLOBAL_VALIDATION, "" ) @@ -109,7 +109,7 @@ contract MultiValidationTest is AccountTestBase { bytes32 userOpHash = entryPoint.getUserOpHash(userOp); (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner2Key, userOpHash.toEthSignedMessageHash()); userOp.signature = _encodeSignature( - FunctionReferenceLib.pack(address(validator2), TEST_DEFAULT_OWNER_FUNCTION_ID), + PackedPluginEntityLib.pack(address(validator2), TEST_DEFAULT_OWNER_FUNCTION_ID), GLOBAL_VALIDATION, abi.encodePacked(r, s, v) ); @@ -124,7 +124,7 @@ contract MultiValidationTest is AccountTestBase { userOp.nonce = 1; (v, r, s) = vm.sign(owner1Key, userOpHash.toEthSignedMessageHash()); userOp.signature = _encodeSignature( - FunctionReferenceLib.pack(address(validator2), TEST_DEFAULT_OWNER_FUNCTION_ID), + PackedPluginEntityLib.pack(address(validator2), TEST_DEFAULT_OWNER_FUNCTION_ID), GLOBAL_VALIDATION, abi.encodePacked(r, s, v) ); diff --git a/test/account/PerHookData.t.sol b/test/account/PerHookData.t.sol index 74228643..3f8c3b39 100644 --- a/test/account/PerHookData.t.sol +++ b/test/account/PerHookData.t.sol @@ -6,7 +6,7 @@ import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntry import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; -import {FunctionReference, FunctionReferenceLib} from "../../src/helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntity, PackedPluginEntityLib} from "../../src/helpers/PackedPluginEntityLib.sol"; import {MockAccessControlHookPlugin} from "../mocks/plugins/MockAccessControlHookPlugin.sol"; import {Counter} from "../mocks/Counter.sol"; @@ -325,13 +325,13 @@ contract PerHookDataTest is CustomValidationTestBase { internal virtual override - returns (FunctionReference, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory) + returns (PackedPluginEntity, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory) { - FunctionReference accessControlHook = FunctionReferenceLib.pack( + PackedPluginEntity accessControlHook = PackedPluginEntityLib.pack( address(_accessControlHookPlugin), uint32(MockAccessControlHookPlugin.EntityId.PRE_VALIDATION_HOOK) ); - FunctionReference[] memory preValidationHooks = new FunctionReference[](1); + PackedPluginEntity[] memory preValidationHooks = new PackedPluginEntity[](1); preValidationHooks[0] = accessControlHook; bytes[] memory preValidationHookData = new bytes[](1); diff --git a/test/account/SelfCallAuthorization.t.sol b/test/account/SelfCallAuthorization.t.sol index 708117e2..2eeb1b5b 100644 --- a/test/account/SelfCallAuthorization.t.sol +++ b/test/account/SelfCallAuthorization.t.sol @@ -7,7 +7,7 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; import {IStandardExecutor, Call} from "../../src/interfaces/IStandardExecutor.sol"; -import {FunctionReference, FunctionReferenceLib} from "../../src/helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntity, PackedPluginEntityLib} from "../../src/helpers/PackedPluginEntityLib.sol"; import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol"; import {AccountTestBase} from "../utils/AccountTestBase.sol"; @@ -16,7 +16,7 @@ import {ComprehensivePlugin} from "../mocks/plugins/ComprehensivePlugin.sol"; contract SelfCallAuthorizationTest is AccountTestBase { ComprehensivePlugin public comprehensivePlugin; - FunctionReference public comprehensivePluginValidation; + PackedPluginEntity public comprehensivePluginValidation; function setUp() public { // install the comprehensive plugin to get new exec functions with different validations configured. @@ -27,7 +27,7 @@ contract SelfCallAuthorizationTest is AccountTestBase { vm.prank(address(entryPoint)); account1.installPlugin(address(comprehensivePlugin), manifestHash, ""); - comprehensivePluginValidation = FunctionReferenceLib.pack( + comprehensivePluginValidation = PackedPluginEntityLib.pack( address(comprehensivePlugin), uint32(ComprehensivePlugin.EntityId.VALIDATION) ); } diff --git a/test/account/ValidationIntersection.t.sol b/test/account/ValidationIntersection.t.sol index 5011aad8..222e4df2 100644 --- a/test/account/ValidationIntersection.t.sol +++ b/test/account/ValidationIntersection.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.19; import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; -import {FunctionReference, FunctionReferenceLib} from "../../src/helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntity, PackedPluginEntityLib} from "../../src/helpers/PackedPluginEntityLib.sol"; import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol"; import { @@ -22,26 +22,26 @@ contract ValidationIntersectionTest is AccountTestBase { MockUserOpValidation1HookPlugin public oneHookPlugin; MockUserOpValidation2HookPlugin public twoHookPlugin; - FunctionReference public noHookValidation; - FunctionReference public oneHookValidation; - FunctionReference public twoHookValidation; + PackedPluginEntity public noHookValidation; + PackedPluginEntity public oneHookValidation; + PackedPluginEntity public twoHookValidation; function setUp() public { noHookPlugin = new MockUserOpValidationPlugin(); oneHookPlugin = new MockUserOpValidation1HookPlugin(); twoHookPlugin = new MockUserOpValidation2HookPlugin(); - noHookValidation = FunctionReferenceLib.pack({ + noHookValidation = PackedPluginEntityLib.pack({ addr: address(noHookPlugin), entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.USER_OP_VALIDATION) }); - oneHookValidation = FunctionReferenceLib.pack({ + oneHookValidation = PackedPluginEntityLib.pack({ addr: address(oneHookPlugin), entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.USER_OP_VALIDATION) }); - twoHookValidation = FunctionReferenceLib.pack({ + twoHookValidation = PackedPluginEntityLib.pack({ addr: address(twoHookPlugin), entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.USER_OP_VALIDATION) }); @@ -59,8 +59,8 @@ contract ValidationIntersectionTest is AccountTestBase { }); // TODO: change with new install flow // temporary fix to add the pre-validation hook - FunctionReference[] memory preValidationHooks = new FunctionReference[](1); - preValidationHooks[0] = FunctionReferenceLib.pack({ + PackedPluginEntity[] memory preValidationHooks = new PackedPluginEntity[](1); + preValidationHooks[0] = PackedPluginEntityLib.pack({ addr: address(oneHookPlugin), entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.PRE_VALIDATION_HOOK_1) }); @@ -78,12 +78,12 @@ contract ValidationIntersectionTest is AccountTestBase { pluginInstallData: "" }); // temporary fix to add the pre-validation hook - preValidationHooks = new FunctionReference[](2); - preValidationHooks[0] = FunctionReferenceLib.pack({ + preValidationHooks = new PackedPluginEntity[](2); + preValidationHooks[0] = PackedPluginEntityLib.pack({ addr: address(twoHookPlugin), entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.PRE_VALIDATION_HOOK_1) }); - preValidationHooks[1] = FunctionReferenceLib.pack({ + preValidationHooks[1] = PackedPluginEntityLib.pack({ addr: address(twoHookPlugin), entityId: uint32(MockBaseUserOpValidationPlugin.EntityId.PRE_VALIDATION_HOOK_2) }); diff --git a/test/libraries/FunctionReferenceLib.t.sol b/test/libraries/FunctionReferenceLib.t.sol index 4ecfb0e9..5b9a66c3 100644 --- a/test/libraries/FunctionReferenceLib.t.sol +++ b/test/libraries/FunctionReferenceLib.t.sol @@ -3,29 +3,29 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; -import {FunctionReferenceLib} from "../../src/helpers/FunctionReferenceLib.sol"; -import {FunctionReference} from "../../src/interfaces/IPluginManager.sol"; +import {PackedPluginEntityLib} from "../../src/helpers/PackedPluginEntityLib.sol"; +import {PackedPluginEntity} from "../../src/interfaces/IPluginManager.sol"; -contract FunctionReferenceLibTest is Test { - using FunctionReferenceLib for FunctionReference; +contract PackedPluginEntityLibTest is Test { + using PackedPluginEntityLib for PackedPluginEntity; function testFuzz_functionReference_packing(address addr, uint32 entityId) public { // console.log("addr: ", addr); // console.log("entityId: ", vm.toString(entityId)); - FunctionReference fr = FunctionReferenceLib.pack(addr, entityId); - // console.log("packed: ", vm.toString(FunctionReference.unwrap(fr))); - (address addr2, uint32 entityId2) = FunctionReferenceLib.unpack(fr); + PackedPluginEntity fr = PackedPluginEntityLib.pack(addr, entityId); + // console.log("packed: ", vm.toString(PackedPluginEntity.unwrap(fr))); + (address addr2, uint32 entityId2) = PackedPluginEntityLib.unpack(fr); // console.log("addr2: ", addr2); // console.log("entityId2: ", vm.toString(entityId2)); assertEq(addr, addr2); assertEq(entityId, entityId2); } - function testFuzz_functionReference_operators(FunctionReference a, FunctionReference b) public { + function testFuzz_functionReference_operators(PackedPluginEntity a, PackedPluginEntity b) public { assertTrue(a.eq(a)); assertTrue(b.eq(b)); - if (FunctionReference.unwrap(a) == FunctionReference.unwrap(b)) { + if (PackedPluginEntity.unwrap(a) == PackedPluginEntity.unwrap(b)) { assertTrue(a.eq(b)); assertTrue(b.eq(a)); assertFalse(a.notEq(b)); diff --git a/test/samples/AllowlistPlugin.t.sol b/test/samples/AllowlistPlugin.t.sol index 4bf5f60e..ea10666d 100644 --- a/test/samples/AllowlistPlugin.t.sol +++ b/test/samples/AllowlistPlugin.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.25; import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol"; import {Call} from "../../src/interfaces/IStandardExecutor.sol"; -import {FunctionReference, FunctionReferenceLib} from "../../src/helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntity, PackedPluginEntityLib} from "../../src/helpers/PackedPluginEntityLib.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; import {AllowlistPlugin} from "../../src/samples/permissionhooks/AllowlistPlugin.sol"; @@ -290,13 +290,13 @@ contract AllowlistPluginTest is CustomValidationTestBase { internal virtual override - returns (FunctionReference, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory) + returns (PackedPluginEntity, bool, bool, bytes4[] memory, bytes memory, bytes memory, bytes memory) { - FunctionReference accessControlHook = FunctionReferenceLib.pack( + PackedPluginEntity accessControlHook = PackedPluginEntityLib.pack( address(allowlistPlugin), uint32(AllowlistPlugin.EntityId.PRE_VALIDATION_HOOK) ); - FunctionReference[] memory preValidationHooks = new FunctionReference[](1); + PackedPluginEntity[] memory preValidationHooks = new PackedPluginEntity[](1); preValidationHooks[0] = accessControlHook; bytes[] memory preValidationHookData = new bytes[](1); diff --git a/test/utils/AccountTestBase.sol b/test/utils/AccountTestBase.sol index 75123567..347705eb 100644 --- a/test/utils/AccountTestBase.sol +++ b/test/utils/AccountTestBase.sol @@ -5,7 +5,7 @@ import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.so import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; -import {FunctionReference, FunctionReferenceLib} from "../../src/helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntity, PackedPluginEntityLib} from "../../src/helpers/PackedPluginEntityLib.sol"; import {IStandardExecutor, Call} from "../../src/interfaces/IStandardExecutor.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; import {SingleOwnerPlugin} from "../../src/plugins/owner/SingleOwnerPlugin.sol"; @@ -18,7 +18,7 @@ import {MSCAFactoryFixture} from "../mocks/MSCAFactoryFixture.sol"; /// @dev This contract handles common boilerplate setup for tests using UpgradeableModularAccount with /// SingleOwnerPlugin. abstract contract AccountTestBase is OptimizedTest { - using FunctionReferenceLib for FunctionReference; + using PackedPluginEntityLib for PackedPluginEntity; using MessageHashUtils for bytes32; EntryPoint public entryPoint; @@ -30,7 +30,7 @@ abstract contract AccountTestBase is OptimizedTest { uint256 public owner1Key; UpgradeableModularAccount public account1; - FunctionReference internal _ownerValidation; + PackedPluginEntity internal _ownerValidation; uint8 public constant SELECTOR_ASSOCIATED_VALIDATION = 0; uint8 public constant GLOBAL_VALIDATION = 1; @@ -57,7 +57,7 @@ abstract contract AccountTestBase is OptimizedTest { account1 = factory.createAccount(owner1, 0); vm.deal(address(account1), 100 ether); - _ownerValidation = FunctionReferenceLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID); + _ownerValidation = PackedPluginEntityLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID); } function _runExecUserOp(address target, bytes memory callData) internal { @@ -100,7 +100,7 @@ abstract contract AccountTestBase is OptimizedTest { (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, userOpHash.toEthSignedMessageHash()); userOp.signature = _encodeSignature( - FunctionReferenceLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), + PackedPluginEntityLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), GLOBAL_VALIDATION, abi.encodePacked(r, s, v) ); @@ -153,7 +153,7 @@ abstract contract AccountTestBase is OptimizedTest { account1.executeWithAuthorization( callData, _encodeSignature( - FunctionReferenceLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), + PackedPluginEntityLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), GLOBAL_VALIDATION, "" ) @@ -168,7 +168,7 @@ abstract contract AccountTestBase is OptimizedTest { account1.executeWithAuthorization( callData, _encodeSignature( - FunctionReferenceLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), + PackedPluginEntityLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), GLOBAL_VALIDATION, "" ) @@ -190,7 +190,7 @@ abstract contract AccountTestBase is OptimizedTest { ) ), _encodeSignature( - FunctionReferenceLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), + PackedPluginEntityLib.pack(address(singleOwnerPlugin), TEST_DEFAULT_OWNER_FUNCTION_ID), GLOBAL_VALIDATION, "" ) @@ -204,7 +204,7 @@ abstract contract AccountTestBase is OptimizedTest { // helper function to encode a signature, according to the per-hook and per-validation data format. function _encodeSignature( - FunctionReference validationFunction, + PackedPluginEntity validationFunction, uint8 globalOrNot, PreValidationHookData[] memory preValidationHookData, bytes memory validationData @@ -228,11 +228,11 @@ abstract contract AccountTestBase is OptimizedTest { } // overload for the case where there are no pre-validation hooks - function _encodeSignature(FunctionReference validationFunction, uint8 globalOrNot, bytes memory validationData) - internal - pure - returns (bytes memory) - { + function _encodeSignature( + PackedPluginEntity validationFunction, + uint8 globalOrNot, + bytes memory validationData + ) internal pure returns (bytes memory) { PreValidationHookData[] memory emptyPreValidationHookData = new PreValidationHookData[](0); return _encodeSignature(validationFunction, globalOrNot, emptyPreValidationHookData, validationData); } diff --git a/test/utils/CustomValidationTestBase.sol b/test/utils/CustomValidationTestBase.sol index 2244c865..ff7feced 100644 --- a/test/utils/CustomValidationTestBase.sol +++ b/test/utils/CustomValidationTestBase.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.25; import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; -import {FunctionReference} from "../../src/helpers/FunctionReferenceLib.sol"; +import {PackedPluginEntity} from "../../src/helpers/PackedPluginEntityLib.sol"; import {ValidationConfigLib} from "../../src/helpers/ValidationConfigLib.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; @@ -16,7 +16,7 @@ import {AccountTestBase} from "./AccountTestBase.sol"; abstract contract CustomValidationTestBase is AccountTestBase { function _customValidationSetup() internal { ( - FunctionReference validationFunction, + PackedPluginEntity validationFunction, bool isGlobal, bool isSignatureValidation, bytes4[] memory selectors, @@ -44,7 +44,7 @@ abstract contract CustomValidationTestBase is AccountTestBase { internal virtual returns ( - FunctionReference validationFunction, + PackedPluginEntity validationFunction, bool shared, bool isSignatureValidation, bytes4[] memory selectors,