From 400e83392461cf93a6ee6762e188765925d5ed4e Mon Sep 17 00:00:00 2001 From: Adam Egyed <5456061+adamegyed@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:49:06 -0400 Subject: [PATCH] feat: [v0.8-develop] remove execute from plugin (#65) --- src/account/AccountStorage.sol | 16 -- src/account/PluginManagerInternals.sol | 67 +----- src/account/UpgradeableModularAccount.sol | 85 +------ src/helpers/KnownSelectors.sol | 6 +- src/interfaces/IPlugin.sol | 12 - src/interfaces/IPluginExecutor.sol | 33 --- src/interfaces/IStandardExecutor.sol | 10 + test/account/AccountExecHooks.t.sol | 10 +- test/account/AccountReturnData.t.sol | 10 +- .../ExecuteFromPluginPermissions.t.sol | 210 ------------------ test/account/PermittedCallPermissions.t.sol | 61 +++++ test/account/UpgradeableModularAccount.t.sol | 8 +- .../plugins/BadTransferOwnershipPlugin.sol | 55 ----- .../ExecFromPluginPermissionsMocks.sol | 209 ----------------- test/mocks/plugins/PermittedCallMocks.sol | 43 ++++ test/mocks/plugins/ReturnDataPluginMocks.sol | 91 ++++---- 16 files changed, 178 insertions(+), 748 deletions(-) delete mode 100644 src/interfaces/IPluginExecutor.sol delete mode 100644 test/account/ExecuteFromPluginPermissions.t.sol create mode 100644 test/account/PermittedCallPermissions.t.sol delete mode 100644 test/mocks/plugins/BadTransferOwnershipPlugin.sol delete mode 100644 test/mocks/plugins/ExecFromPluginPermissionsMocks.sol create mode 100644 test/mocks/plugins/PermittedCallMocks.sol diff --git a/src/account/AccountStorage.sol b/src/account/AccountStorage.sol index 61ddabb3..0a992a33 100644 --- a/src/account/AccountStorage.sol +++ b/src/account/AccountStorage.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.25; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import {IPlugin} from "../interfaces/IPlugin.sol"; import {ExecutionHook} from "../interfaces/IAccountLoupe.sol"; import {FunctionReference} from "../interfaces/IPluginManager.sol"; @@ -11,25 +10,12 @@ import {FunctionReference} from "../interfaces/IPluginManager.sol"; bytes32 constant _ACCOUNT_STORAGE_SLOT = 0x9f09680beaa4e5c9f38841db2460c401499164f368baef687948c315d9073e40; struct PluginData { - bool anyExternalExecPermitted; - // boolean to indicate if the plugin can spend native tokens from the account. - bool canSpendNativeToken; bytes32 manifestHash; FunctionReference[] dependencies; // Tracks the number of times this plugin has been used as a dependency function uint256 dependentCount; } -// Represents data associated with a plugin's permission to use `executeFromPluginExternal` -// to interact with contracts and addresses external to the account and its plugins. -struct PermittedExternalCallData { - // Is this address on the permitted addresses list? If it is, we either have a - // list of allowed selectors, or the flag that allows any selector. - bool addressPermitted; - bool anySelectorPermitted; - mapping(bytes4 => bool) permittedSelectors; -} - // Represents data associated with a specifc function selector. struct SelectorData { // The plugin that implements this execution function. @@ -67,8 +53,6 @@ struct AccountStorage { mapping(bytes4 => SelectorData) selectorData; mapping(FunctionReference validationFunction => ValidationData) validationData; mapping(address caller => mapping(bytes4 selector => bool)) callPermitted; - // key = address(calling plugin) || target address - mapping(IPlugin => mapping(address => PermittedExternalCallData)) permittedExternalCalls; // For ERC165 introspection mapping(bytes4 => uint256) supportedIfaces; } diff --git a/src/account/PluginManagerInternals.sol b/src/account/PluginManagerInternals.sol index 4db38b55..2ec06f81 100644 --- a/src/account/PluginManagerInternals.sol +++ b/src/account/PluginManagerInternals.sol @@ -11,19 +11,12 @@ import { ManifestFunction, ManifestAssociatedFunctionType, ManifestAssociatedFunction, - ManifestExternalCallPermission, PluginManifest } from "../interfaces/IPlugin.sol"; import {ExecutionHook} from "../interfaces/IAccountLoupe.sol"; import {FunctionReference, IPluginManager} from "../interfaces/IPluginManager.sol"; -import { - AccountStorage, - getAccountStorage, - SelectorData, - toSetValue, - PermittedExternalCallData -} from "./AccountStorage.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; @@ -211,11 +204,6 @@ abstract contract PluginManagerInternals is IPluginManager { // Update components according to the manifest. - // 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; ++i) { bytes4 selector = manifest.executionFunctions[i].executionSelector; @@ -232,31 +220,6 @@ abstract contract PluginManagerInternals is IPluginManager { _storage.callPermitted[plugin][manifest.permittedExecutionSelectors[i]] = true; } - // Add the permitted external calls to the account. - if (manifest.permitAnyExternalAddress) { - _storage.pluginData[plugin].anyExternalExecPermitted = true; - } else { - // Only store the specific permitted external calls if "permit any" flag was not set. - length = manifest.permittedExternalCalls.length; - for (uint256 i = 0; i < length; ++i) { - ManifestExternalCallPermission memory externalCallPermission = manifest.permittedExternalCalls[i]; - - PermittedExternalCallData storage permittedExternalCallData = - _storage.permittedExternalCalls[IPlugin(plugin)][externalCallPermission.externalAddress]; - - permittedExternalCallData.addressPermitted = true; - - if (externalCallPermission.permitAnySelector) { - permittedExternalCallData.anySelectorPermitted = true; - } else { - uint256 externalContractSelectorsLength = externalCallPermission.selectors.length; - for (uint256 j = 0; j < externalContractSelectorsLength; ++j) { - permittedExternalCallData.permittedSelectors[externalCallPermission.selectors[j]] = true; - } - } - } - } - length = manifest.validationFunctions.length; for (uint256 i = 0; i < length; ++i) { ManifestAssociatedFunction memory mv = manifest.validationFunctions[i]; @@ -350,34 +313,6 @@ abstract contract PluginManagerInternals is IPluginManager { ); } - // remove external call permissions - - if (manifest.permitAnyExternalAddress) { - // Only clear if it was set during install time - _storage.pluginData[plugin].anyExternalExecPermitted = false; - } else { - // Only clear the specific permitted external calls if "permit any" flag was not set. - length = manifest.permittedExternalCalls.length; - for (uint256 i = 0; i < length; ++i) { - ManifestExternalCallPermission memory externalCallPermission = manifest.permittedExternalCalls[i]; - - PermittedExternalCallData storage permittedExternalCallData = - _storage.permittedExternalCalls[IPlugin(plugin)][externalCallPermission.externalAddress]; - - permittedExternalCallData.addressPermitted = false; - - // Only clear this flag if it was set in the constructor. - if (externalCallPermission.permitAnySelector) { - permittedExternalCallData.anySelectorPermitted = false; - } else { - uint256 externalContractSelectorsLength = externalCallPermission.selectors.length; - for (uint256 j = 0; j < externalContractSelectorsLength; ++j) { - permittedExternalCallData.permittedSelectors[externalCallPermission.selectors[j]] = false; - } - } - } - } - length = manifest.permittedExecutionSelectors.length; for (uint256 i = 0; i < length; ++i) { _storage.callPermitted[plugin][manifest.permittedExecutionSelectors[i]] = false; diff --git a/src/account/UpgradeableModularAccount.sol b/src/account/UpgradeableModularAccount.sol index c603b0ca..169b17a3 100644 --- a/src/account/UpgradeableModularAccount.sol +++ b/src/account/UpgradeableModularAccount.sol @@ -15,7 +15,6 @@ 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 {IPluginExecutor} from "../interfaces/IPluginExecutor.sol"; import {FunctionReference, IPluginManager} from "../interfaces/IPluginManager.sol"; import {IStandardExecutor, Call} from "../interfaces/IStandardExecutor.sol"; import {AccountExecutor} from "./AccountExecutor.sol"; @@ -39,7 +38,6 @@ contract UpgradeableModularAccount is BaseAccount, IERC165, IERC1271, - IPluginExecutor, IStandardExecutor, PluginManagerInternals, PluginManager2, @@ -185,88 +183,7 @@ contract UpgradeableModularAccount is } } - /// @inheritdoc IPluginExecutor - function executeFromPlugin(bytes calldata data) external payable override returns (bytes memory) { - bytes4 selector = bytes4(data[:4]); - address callingPlugin = msg.sender; - - AccountStorage storage _storage = getAccountStorage(); - - if (!_storage.callPermitted[callingPlugin][selector]) { - revert ExecFromPluginNotPermitted(callingPlugin, selector); - } - - address execFunctionPlugin = _storage.selectorData[selector].plugin; - - if (execFunctionPlugin == address(0)) { - revert UnrecognizedFunction(selector); - } - - PostExecToRun[] memory postExecHooks = _doPreExecHooks(selector, data); - - (bool success, bytes memory returnData) = execFunctionPlugin.call(data); - - if (!success) { - assembly ("memory-safe") { - revert(add(returnData, 32), mload(returnData)) - } - } - - _doCachedPostExecHooks(postExecHooks); - - return returnData; - } - - /// @inheritdoc IPluginExecutor - function executeFromPluginExternal(address target, uint256 value, bytes calldata data) - external - payable - returns (bytes memory) - { - 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. - // This first checks that the intended target is permitted at all. If it is, then it checks if any selector - // is permitted. If any selector is permitted, then it skips the selector-level permission check. - // If only a subset of selectors are permitted, then it also checks the selector-level permission. - // By checking in the order of [address specified with any selector allowed], [any address allowed], - // [address specified and selector specified], along with the extra bool `permittedCall`, we can - // reduce the number of `sload`s in the worst-case from 3 down to 2. - bool targetContractPermittedCall = _storage.permittedExternalCalls[IPlugin(msg.sender)][target] - .addressPermitted - && ( - _storage.permittedExternalCalls[IPlugin(msg.sender)][target].anySelectorPermitted - || _storage.permittedExternalCalls[IPlugin(msg.sender)][target].permittedSelectors[selector] - ); - - // If the target contract is not permitted, check if the caller plugin is permitted to make any external - // calls. - if (!(targetContractPermittedCall || _storage.pluginData[msg.sender].anyExternalExecPermitted)) { - revert ExecFromPluginExternalNotPermitted(msg.sender, target, value, data); - } - - // Run any pre exec hooks for this selector - PostExecToRun[] memory postExecHooks = - _doPreExecHooks(IPluginExecutor.executeFromPluginExternal.selector, msg.data); - - // Perform the external call - bytes memory returnData = _exec(target, value, data); - - // Run any post exec hooks for this selector - _doCachedPostExecHooks(postExecHooks); - - return returnData; - } - - /// @inheritdoc IPluginExecutor + /// @inheritdoc IStandardExecutor function executeWithAuthorization(bytes calldata data, bytes calldata authorization) external payable diff --git a/src/helpers/KnownSelectors.sol b/src/helpers/KnownSelectors.sol index 6d737172..e5244d2c 100644 --- a/src/helpers/KnownSelectors.sol +++ b/src/helpers/KnownSelectors.sol @@ -10,7 +10,6 @@ import {IPaymaster} from "@eth-infinitism/account-abstraction/interfaces/IPaymas import {IAccountLoupe} from "../interfaces/IAccountLoupe.sol"; import {IExecutionHook} from "../interfaces/IExecutionHook.sol"; import {IPlugin} from "../interfaces/IPlugin.sol"; -import {IPluginExecutor} from "../interfaces/IPluginExecutor.sol"; import {IPluginManager} from "../interfaces/IPluginManager.sol"; import {IStandardExecutor} from "../interfaces/IStandardExecutor.sol"; import {IValidation} from "../interfaces/IValidation.sol"; @@ -32,10 +31,7 @@ library KnownSelectors { || selector == UUPSUpgradeable.upgradeToAndCall.selector // check against IStandardExecutor methods || selector == IStandardExecutor.execute.selector || selector == IStandardExecutor.executeBatch.selector - // check against IPluginExecutor methods - || selector == IPluginExecutor.executeFromPlugin.selector - || selector == IPluginExecutor.executeFromPluginExternal.selector - || selector == IPluginExecutor.executeWithAuthorization.selector + || selector == IStandardExecutor.executeWithAuthorization.selector // check against IAccountLoupe methods || selector == IAccountLoupe.getExecutionFunctionHandler.selector || selector == IAccountLoupe.getValidations.selector diff --git a/src/interfaces/IPlugin.sol b/src/interfaces/IPlugin.sol index b34e924f..3241e497 100644 --- a/src/interfaces/IPlugin.sol +++ b/src/interfaces/IPlugin.sol @@ -47,12 +47,6 @@ struct ManifestExecutionHook { bool isPostHook; } -struct ManifestExternalCallPermission { - address externalAddress; - bool permitAnySelector; - bytes4[] selectors; -} - struct SelectorPermission { bytes4 functionSelector; string permissionDescription; @@ -81,12 +75,6 @@ struct PluginManifest { uint8[] signatureValidationFunctions; // Plugin execution functions already installed on the MSCA that this plugin will be able to call. bytes4[] permittedExecutionSelectors; - // Boolean to indicate whether the plugin can call any external address. - bool permitAnyExternalAddress; - // Boolean to indicate whether the plugin needs access to spend native tokens of the account. If false, the - // plugin MUST still be able to spend up to the balance that it sends to the account in the same call. - bool canSpendNativeToken; - ManifestExternalCallPermission[] permittedExternalCalls; // List of ERC-165 interface IDs to add to account to support introspection checks. This MUST NOT include // IPlugin's interface ID. bytes4[] interfaceIds; diff --git a/src/interfaces/IPluginExecutor.sol b/src/interfaces/IPluginExecutor.sol deleted file mode 100644 index 2ff5ed11..00000000 --- a/src/interfaces/IPluginExecutor.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 -pragma solidity ^0.8.25; - -interface IPluginExecutor { - /// @notice Execute a call from a plugin to another plugin, via an execution function installed on the account. - /// @dev Plugins are not allowed to call native functions on the account. Permissions must be granted to the - /// calling plugin for the call to go through. - /// @param data The calldata to send to the plugin. - /// @return The return data from the call. - function executeFromPlugin(bytes calldata data) external payable returns (bytes memory); - - /// @notice Execute a call from a plugin to a non-plugin address. - /// @dev If the target is a plugin, the call SHOULD revert. Permissions must be granted to the calling plugin - /// for the call to go through. - /// @param target The address to be called. - /// @param value The value to send with the call. - /// @param data The calldata to send to the target. - /// @return The return data from the call. - function executeFromPluginExternal(address target, uint256 value, bytes calldata data) - external - payable - returns (bytes memory); - - /// @notice Execute a call using a specified runtime validation, as given in the first 21 bytes of - /// `authorization`. - /// @param data The calldata to send to the account. - /// @param authorization The authorization data to use for the call. The first 21 bytes specifies which runtime - /// validation to use, and the rest is sent as a parameter to runtime validation. - function executeWithAuthorization(bytes calldata data, bytes calldata authorization) - external - payable - returns (bytes memory); -} diff --git a/src/interfaces/IStandardExecutor.sol b/src/interfaces/IStandardExecutor.sol index 30b6deee..fbeb89c4 100644 --- a/src/interfaces/IStandardExecutor.sol +++ b/src/interfaces/IStandardExecutor.sol @@ -25,4 +25,14 @@ interface IStandardExecutor { /// @param calls The array of calls. /// @return An array containing the return data from the calls. function executeBatch(Call[] calldata calls) external payable returns (bytes[] memory); + + /// @notice Execute a call using a specified runtime validation, as given in the first 21 bytes of + /// `authorization`. + /// @param data The calldata to send to the account. + /// @param authorization The authorization data to use for the call. The first 21 bytes specifies which runtime + /// validation to use, and the rest is sent as a parameter to runtime validation. + function executeWithAuthorization(bytes calldata data, bytes calldata authorization) + external + payable + returns (bytes memory); } diff --git a/test/account/AccountExecHooks.t.sol b/test/account/AccountExecHooks.t.sol index 842cf84c..6a3b7d8c 100644 --- a/test/account/AccountExecHooks.t.sol +++ b/test/account/AccountExecHooks.t.sol @@ -24,8 +24,8 @@ contract AccountExecHooksTest is AccountTestBase { uint8 internal constant _POST_HOOK_FUNCTION_ID_2 = 2; uint8 internal constant _BOTH_HOOKS_FUNCTION_ID_3 = 3; - PluginManifest public m1; - PluginManifest public m2; + PluginManifest internal _m1; + PluginManifest internal _m2; event PluginInstalled(address indexed plugin, bytes32 manifestHash, FunctionReference[] dependencies); event PluginUninstalled(address indexed plugin, bool indexed callbacksSucceeded); @@ -35,7 +35,7 @@ contract AccountExecHooksTest is AccountTestBase { function setUp() public { _transferOwnershipToTest(); - m1.executionFunctions.push( + _m1.executionFunctions.push( ManifestExecutionFunction({ executionSelector: _EXEC_SELECTOR, isPublic: true, @@ -163,8 +163,8 @@ contract AccountExecHooksTest is AccountTestBase { } function _installPlugin1WithHooks(ManifestExecutionHook memory execHooks) internal { - m1.executionHooks.push(execHooks); - mockPlugin1 = new MockPlugin(m1); + _m1.executionHooks.push(execHooks); + mockPlugin1 = new MockPlugin(_m1); manifestHash1 = keccak256(abi.encode(mockPlugin1.pluginManifest())); vm.expectEmit(true, true, true, true); diff --git a/test/account/AccountReturnData.t.sol b/test/account/AccountReturnData.t.sol index b3d2419a..8e8f3215 100644 --- a/test/account/AccountReturnData.t.sol +++ b/test/account/AccountReturnData.t.sol @@ -99,16 +99,16 @@ contract AccountReturnDataTest is AccountTestBase { assertEq(result2, keccak256("foo")); } - // Tests the ability to read data via executeFromPlugin routing to fallback functions + // Tests the ability to read data via routing to fallback functions function test_returnData_execFromPlugin_fallback() public { - bool result = ResultConsumerPlugin(address(account1)).checkResultEFPFallback(keccak256("bar")); + bool result = ResultConsumerPlugin(address(account1)).checkResultFallback(keccak256("bar")); assertTrue(result); } - // Tests the ability to read data via executeFromPluginExternal - function test_returnData_execFromPlugin_execute() public { - bool result = ResultConsumerPlugin(address(account1)).checkResultEFPExternal( + // Tests the ability to read data via executeWithAuthorization + function test_returnData_authorized_exec() public { + bool result = ResultConsumerPlugin(address(account1)).checkResultExecuteWithAuthorization( address(regularResultContract), keccak256("bar") ); diff --git a/test/account/ExecuteFromPluginPermissions.t.sol b/test/account/ExecuteFromPluginPermissions.t.sol deleted file mode 100644 index 6a95ba18..00000000 --- a/test/account/ExecuteFromPluginPermissions.t.sol +++ /dev/null @@ -1,210 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.19; - -import {console} from "forge-std/Test.sol"; - -import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; -import {FunctionReference} from "../../src/helpers/FunctionReferenceLib.sol"; - -import {Counter} from "../mocks/Counter.sol"; -import {ResultCreatorPlugin} from "../mocks/plugins/ReturnDataPluginMocks.sol"; -import {EFPCallerPlugin, EFPCallerPluginAnyExternal} from "../mocks/plugins/ExecFromPluginPermissionsMocks.sol"; -import {AccountTestBase} from "../utils/AccountTestBase.sol"; - -contract ExecuteFromPluginPermissionsTest is AccountTestBase { - Counter public counter1; - Counter public counter2; - Counter public counter3; - ResultCreatorPlugin public resultCreatorPlugin; - - EFPCallerPlugin public efpCallerPlugin; - EFPCallerPluginAnyExternal public efpCallerPluginAnyExternal; - - function setUp() public { - _transferOwnershipToTest(); - - // Initialize the interaction targets - counter1 = new Counter(); - counter2 = new Counter(); - counter3 = new Counter(); - resultCreatorPlugin = new ResultCreatorPlugin(); - - // Initialize the EFP caller plugins, which will attempt to use the permissions system to authorize calls. - efpCallerPlugin = new EFPCallerPlugin(address(counter1), address(counter2), address(counter3)); - efpCallerPluginAnyExternal = new EFPCallerPluginAnyExternal(); - - // Add the result creator plugin to the account - bytes32 resultCreatorManifestHash = keccak256(abi.encode(resultCreatorPlugin.pluginManifest())); - vm.prank(address(entryPoint)); - account1.installPlugin({ - plugin: address(resultCreatorPlugin), - manifestHash: resultCreatorManifestHash, - pluginInstallData: "", - dependencies: new FunctionReference[](0) - }); - // Add the EFP caller plugin to the account - bytes32 efpCallerManifestHash = keccak256(abi.encode(efpCallerPlugin.pluginManifest())); - vm.prank(address(entryPoint)); - account1.installPlugin({ - plugin: address(efpCallerPlugin), - manifestHash: efpCallerManifestHash, - pluginInstallData: "", - dependencies: new FunctionReference[](0) - }); - - // Add the EFP caller plugin with any external permissions to the account - bytes32 efpCallerAnyExternalManifestHash = - keccak256(abi.encode(efpCallerPluginAnyExternal.pluginManifest())); - vm.prank(address(entryPoint)); - account1.installPlugin({ - plugin: address(efpCallerPluginAnyExternal), - manifestHash: efpCallerAnyExternalManifestHash, - pluginInstallData: "", - dependencies: new FunctionReference[](0) - }); - } - - // Report the addresses to be used in the address constants in ExecFromPluginPermissionsMocks.sol - function test_getPermissionsTestAddresses() public view { - // solhint-disable no-console - console.log("counter1 address: %s", address(counter1)); - console.log("counter2 address: %s", address(counter2)); - console.log("counter3 address: %s", address(counter3)); - console.log("resultCreatorPlugin address: %s", address(resultCreatorPlugin)); - // solhint-enable no-console - } - - function test_executeFromPluginAllowed() public { - bytes memory result = EFPCallerPlugin(address(account1)).useEFPPermissionAllowed(); - bytes32 actual = abi.decode(result, (bytes32)); - - assertEq(actual, keccak256("bar")); - } - - function test_executeFromPluginNotAllowed() public { - vm.expectRevert( - abi.encodeWithSelector( - UpgradeableModularAccount.ExecFromPluginNotPermitted.selector, - address(efpCallerPlugin), - ResultCreatorPlugin.bar.selector - ) - ); - EFPCallerPlugin(address(account1)).useEFPPermissionNotAllowed(); - } - - function test_executeFromPluginExternal_Allowed_IndividualSelectors() public { - EFPCallerPlugin(address(account1)).setNumberCounter1(17); - uint256 retrievedNumber = EFPCallerPlugin(address(account1)).getNumberCounter1(); - - assertEq(retrievedNumber, 17); - } - - function test_executeFromPluginExternal_NotAlowed_IndividualSelectors() public { - EFPCallerPlugin(address(account1)).setNumberCounter1(17); - - // Call to increment should fail - vm.expectRevert( - abi.encodeWithSelector( - UpgradeableModularAccount.ExecFromPluginExternalNotPermitted.selector, - address(efpCallerPlugin), - address(counter1), - 0, - abi.encodePacked(Counter.increment.selector) - ) - ); - EFPCallerPlugin(address(account1)).incrementCounter1(); - - uint256 retrievedNumber = EFPCallerPlugin(address(account1)).getNumberCounter1(); - - assertEq(retrievedNumber, 17); - } - - function test_executeFromPluginExternal_Allowed_AllSelectors() public { - EFPCallerPlugin(address(account1)).setNumberCounter2(17); - EFPCallerPlugin(address(account1)).incrementCounter2(); - uint256 retrievedNumber = EFPCallerPlugin(address(account1)).getNumberCounter2(); - - assertEq(retrievedNumber, 18); - } - - function test_executeFromPluginExternal_NotAllowed_AllSelectors() public { - vm.expectRevert( - abi.encodeWithSelector( - UpgradeableModularAccount.ExecFromPluginExternalNotPermitted.selector, - address(efpCallerPlugin), - address(counter3), - 0, - abi.encodeWithSelector(Counter.setNumber.selector, uint256(17)) - ) - ); - EFPCallerPlugin(address(account1)).setNumberCounter3(17); - - // Call to increment should fail - vm.expectRevert( - abi.encodeWithSelector( - UpgradeableModularAccount.ExecFromPluginExternalNotPermitted.selector, - address(efpCallerPlugin), - address(counter3), - 0, - abi.encodePacked(Counter.increment.selector) - ) - ); - EFPCallerPlugin(address(account1)).incrementCounter3(); - - vm.expectRevert( - abi.encodeWithSelector( - UpgradeableModularAccount.ExecFromPluginExternalNotPermitted.selector, - address(efpCallerPlugin), - address(counter3), - 0, - abi.encodePacked(bytes4(keccak256("number()"))) - ) - ); - EFPCallerPlugin(address(account1)).getNumberCounter3(); - - // Validate no state changes - assert(counter3.number() == 0); - } - - function test_executeFromPluginExternal_Allowed_AnyContract() public { - // Run full workflow for counter 1 - - EFPCallerPluginAnyExternal(address(account1)).passthroughExecute( - address(counter1), 0, abi.encodeCall(Counter.setNumber, (17)) - ); - uint256 retrievedNumber = counter1.number(); - assertEq(retrievedNumber, 17); - - EFPCallerPluginAnyExternal(address(account1)).passthroughExecute( - address(counter1), 0, abi.encodeCall(Counter.increment, ()) - ); - retrievedNumber = counter1.number(); - assertEq(retrievedNumber, 18); - - bytes memory result = EFPCallerPluginAnyExternal(address(account1)).passthroughExecute( - address(counter1), 0, abi.encodePacked(bytes4(keccak256("number()"))) - ); - retrievedNumber = abi.decode(result, (uint256)); - assertEq(retrievedNumber, 18); - - // Run full workflow for counter 2 - - EFPCallerPluginAnyExternal(address(account1)).passthroughExecute( - address(counter2), 0, abi.encodeCall(Counter.setNumber, (17)) - ); - retrievedNumber = counter2.number(); - assertEq(retrievedNumber, 17); - - EFPCallerPluginAnyExternal(address(account1)).passthroughExecute( - address(counter2), 0, abi.encodeCall(Counter.increment, ()) - ); - retrievedNumber = counter2.number(); - assertEq(retrievedNumber, 18); - - result = EFPCallerPluginAnyExternal(address(account1)).passthroughExecute( - address(counter2), 0, abi.encodePacked(bytes4(keccak256("number()"))) - ); - retrievedNumber = abi.decode(result, (uint256)); - assertEq(retrievedNumber, 18); - } -} diff --git a/test/account/PermittedCallPermissions.t.sol b/test/account/PermittedCallPermissions.t.sol new file mode 100644 index 00000000..517b2080 --- /dev/null +++ b/test/account/PermittedCallPermissions.t.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; +import {FunctionReference} from "../../src/helpers/FunctionReferenceLib.sol"; + +import {ResultCreatorPlugin} from "../mocks/plugins/ReturnDataPluginMocks.sol"; +import {PermittedCallerPlugin} from "../mocks/plugins/PermittedCallMocks.sol"; +import {AccountTestBase} from "../utils/AccountTestBase.sol"; + +contract PermittedCallPermissionsTest is AccountTestBase { + ResultCreatorPlugin public resultCreatorPlugin; + + PermittedCallerPlugin public permittedCallerPlugin; + + function setUp() public { + _transferOwnershipToTest(); + resultCreatorPlugin = new ResultCreatorPlugin(); + + // Initialize the permitted caller plugins, which will attempt to use the permissions system to authorize + // calls. + permittedCallerPlugin = new PermittedCallerPlugin(); + + // Add the result creator plugin to the account + bytes32 resultCreatorManifestHash = keccak256(abi.encode(resultCreatorPlugin.pluginManifest())); + vm.prank(address(entryPoint)); + account1.installPlugin({ + plugin: address(resultCreatorPlugin), + manifestHash: resultCreatorManifestHash, + pluginInstallData: "", + dependencies: new FunctionReference[](0) + }); + // Add the permitted caller plugin to the account + bytes32 permittedCallerManifestHash = keccak256(abi.encode(permittedCallerPlugin.pluginManifest())); + vm.prank(address(entryPoint)); + account1.installPlugin({ + plugin: address(permittedCallerPlugin), + manifestHash: permittedCallerManifestHash, + pluginInstallData: "", + dependencies: new FunctionReference[](0) + }); + } + + function test_permittedCall_Allowed() public { + bytes memory result = PermittedCallerPlugin(address(account1)).usePermittedCallAllowed(); + bytes32 actual = abi.decode(result, (bytes32)); + + assertEq(actual, keccak256("bar")); + } + + function test_permittedCall_NotAllowed() public { + vm.expectRevert( + abi.encodeWithSelector( + UpgradeableModularAccount.ExecFromPluginNotPermitted.selector, + address(permittedCallerPlugin), + ResultCreatorPlugin.bar.selector + ) + ); + PermittedCallerPlugin(address(account1)).usePermittedCallNotAllowed(); + } +} diff --git a/test/account/UpgradeableModularAccount.t.sol b/test/account/UpgradeableModularAccount.t.sol index 15ad262e..e3d09e7f 100644 --- a/test/account/UpgradeableModularAccount.t.sol +++ b/test/account/UpgradeableModularAccount.t.sol @@ -37,7 +37,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { address public ethRecipient; Counter public counter; - PluginManifest public manifest; + PluginManifest internal _manifest; FunctionReference public ownerValidation; @@ -258,7 +258,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { assertEq(plugins[1], address(tokenReceiverPlugin)); } - function test_installPlugin_ExecuteFromPlugin_PermittedExecSelectorNotInstalled() public { + function test_installPlugin_PermittedCallSelectorNotInstalled() public { vm.startPrank(address(entryPoint)); PluginManifest memory m; @@ -385,7 +385,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { dependencies: new FunctionReference[](0) }); - // Attempt to uninstall with a blank manifest + // Attempt to uninstall with a blank _manifest PluginManifest memory blankManifest; vm.expectRevert(abi.encodeWithSelector(PluginManagerInternals.InvalidPluginManifest.selector)); @@ -403,7 +403,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { function _installPluginWithExecHooks() internal returns (MockPlugin plugin) { vm.startPrank(address(entryPoint)); - plugin = new MockPlugin(manifest); + plugin = new MockPlugin(_manifest); bytes32 manifestHash = keccak256(abi.encode(plugin.pluginManifest())); IPluginManager(account1).installPlugin({ diff --git a/test/mocks/plugins/BadTransferOwnershipPlugin.sol b/test/mocks/plugins/BadTransferOwnershipPlugin.sol deleted file mode 100644 index dcb9a935..00000000 --- a/test/mocks/plugins/BadTransferOwnershipPlugin.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.19; - -import {ManifestExecutionFunction, PluginManifest, PluginMetadata} from "../../../src/interfaces/IPlugin.sol"; -import {BasePlugin} from "../../../src/plugins/BasePlugin.sol"; -import {ISingleOwnerPlugin} from "../../../src/plugins/owner/ISingleOwnerPlugin.sol"; -import {IPluginExecutor} from "../../../src/interfaces/IPluginExecutor.sol"; - -contract BadTransferOwnershipPlugin is BasePlugin { - string public constant NAME = "Evil Transfer Ownership Plugin"; - string public constant VERSION = "1.0.0"; - string public constant AUTHOR = "ERC-6900 Authors"; - - // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ - // ┃ Execution functions ┃ - // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - - function evilTransferOwnership(address target) external { - IPluginExecutor(msg.sender).executeFromPlugin( - abi.encodeCall(ISingleOwnerPlugin.transferOwnership, (target)) - ); - } - - // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ - // ┃ Plugin interface functions ┃ - // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - - function onInstall(bytes calldata) external override {} - - function onUninstall(bytes calldata) external override {} - - function pluginManifest() external pure override returns (PluginManifest memory) { - PluginManifest memory manifest; - - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction({ - executionSelector: this.evilTransferOwnership.selector, - isPublic: true, - allowDefaultValidation: false - }); - - manifest.permittedExecutionSelectors = new bytes4[](1); - manifest.permittedExecutionSelectors[0] = ISingleOwnerPlugin.transferOwnership.selector; - - 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 deleted file mode 100644 index 1d9f566f..00000000 --- a/test/mocks/plugins/ExecFromPluginPermissionsMocks.sol +++ /dev/null @@ -1,209 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.19; - -import { - ManifestExecutionFunction, - ManifestExternalCallPermission, - PluginManifest, - PluginMetadata -} from "../../../src/interfaces/IPlugin.sol"; -import {IPluginExecutor} from "../../../src/interfaces/IPluginExecutor.sol"; - -import {BasePlugin} from "../../../src/plugins/BasePlugin.sol"; -import {ResultCreatorPlugin} from "./ReturnDataPluginMocks.sol"; -import {Counter} from "../Counter.sol"; - -contract EFPCallerPlugin is BasePlugin { - // Store the counters as immutables, and use the view -> pure cast to get the manifest - // solhint-disable private-vars-leading-underscore, immutable-vars-naming - address private immutable counter1; - address private immutable counter2; - address private immutable counter3; - // solhint-enable private-vars-leading-underscore, immutable-vars-naming - - constructor(address _counter1, address _counter2, address _counter3) { - counter1 = _counter1; - counter2 = _counter2; - counter3 = _counter3; - } - - function onInstall(bytes calldata) external override {} - - function onUninstall(bytes calldata) external override {} - - function _getManifest() internal view returns (PluginManifest memory) { - PluginManifest memory manifest; - - manifest.executionFunctions = new ManifestExecutionFunction[](11); - manifest.executionFunctions[0].executionSelector = this.useEFPPermissionAllowed.selector; - manifest.executionFunctions[1].executionSelector = this.useEFPPermissionNotAllowed.selector; - manifest.executionFunctions[2].executionSelector = this.setNumberCounter1.selector; - manifest.executionFunctions[3].executionSelector = this.getNumberCounter1.selector; - manifest.executionFunctions[4].executionSelector = this.incrementCounter1.selector; - manifest.executionFunctions[5].executionSelector = this.setNumberCounter2.selector; - manifest.executionFunctions[6].executionSelector = this.getNumberCounter2.selector; - manifest.executionFunctions[7].executionSelector = this.incrementCounter2.selector; - manifest.executionFunctions[8].executionSelector = this.setNumberCounter3.selector; - manifest.executionFunctions[9].executionSelector = this.getNumberCounter3.selector; - manifest.executionFunctions[10].executionSelector = this.incrementCounter3.selector; - - for (uint256 i = 0; i < manifest.executionFunctions.length; i++) { - manifest.executionFunctions[i].isPublic = true; - } - - // Request permission only for "foo", but not "bar", from ResultCreatorPlugin - manifest.permittedExecutionSelectors = new bytes4[](1); - manifest.permittedExecutionSelectors[0] = ResultCreatorPlugin.foo.selector; - - // Request permission for: - // - `setNumber` and `number` on counter 1 - // - All selectors on counter 2 - // - None on counter 3 - manifest.permittedExternalCalls = new ManifestExternalCallPermission[](2); - - bytes4[] memory selectorsCounter1 = new bytes4[](2); - selectorsCounter1[0] = Counter.setNumber.selector; - selectorsCounter1[1] = bytes4(keccak256("number()")); // Public vars don't automatically get exported - // selectors - - manifest.permittedExternalCalls[0] = ManifestExternalCallPermission({ - externalAddress: counter1, - permitAnySelector: false, - selectors: selectorsCounter1 - }); - - manifest.permittedExternalCalls[1] = ManifestExternalCallPermission({ - externalAddress: counter2, - permitAnySelector: true, - selectors: new bytes4[](0) - }); - - return manifest; - } - - function _castToPure(function() internal view returns (PluginManifest memory) fnIn) - internal - pure - returns (function() internal pure returns (PluginManifest memory) fnOut) - { - assembly ("memory-safe") { - fnOut := fnIn - } - } - - function pluginManifest() external pure override returns (PluginManifest memory) { - return _castToPure(_getManifest)(); - } - - function pluginMetadata() external pure override returns (PluginMetadata memory) {} - - // The manifest requested access to use the plugin-defined method "foo" - function useEFPPermissionAllowed() external returns (bytes memory) { - return IPluginExecutor(msg.sender).executeFromPlugin(abi.encodeCall(ResultCreatorPlugin.foo, ())); - } - - // The manifest has not requested access to use the plugin-defined method "bar", so this should revert. - function useEFPPermissionNotAllowed() external returns (bytes memory) { - return IPluginExecutor(msg.sender).executeFromPlugin(abi.encodeCall(ResultCreatorPlugin.bar, ())); - } - - // Should be allowed - function setNumberCounter1(uint256 number) external { - IPluginExecutor(msg.sender).executeFromPluginExternal( - counter1, 0, abi.encodeWithSelector(Counter.setNumber.selector, number) - ); - } - - // Should be allowed - function getNumberCounter1() external returns (uint256) { - bytes memory returnData = IPluginExecutor(msg.sender).executeFromPluginExternal( - counter1, 0, abi.encodePacked(bytes4(keccak256("number()"))) - ); - - return abi.decode(returnData, (uint256)); - } - - // Should not be allowed - function incrementCounter1() external { - IPluginExecutor(msg.sender).executeFromPluginExternal( - counter1, 0, abi.encodeWithSelector(Counter.increment.selector) - ); - } - - // Should be allowed - function setNumberCounter2(uint256 number) external { - IPluginExecutor(msg.sender).executeFromPluginExternal( - counter2, 0, abi.encodeWithSelector(Counter.setNumber.selector, number) - ); - } - - // Should be allowed - function getNumberCounter2() external returns (uint256) { - bytes memory returnData = IPluginExecutor(msg.sender).executeFromPluginExternal( - counter2, 0, abi.encodePacked(bytes4(keccak256("number()"))) - ); - - return abi.decode(returnData, (uint256)); - } - - // Should be allowed - function incrementCounter2() external { - IPluginExecutor(msg.sender).executeFromPluginExternal( - counter2, 0, abi.encodeWithSelector(Counter.increment.selector) - ); - } - - // Should not be allowed - function setNumberCounter3(uint256 number) external { - IPluginExecutor(msg.sender).executeFromPluginExternal( - counter3, 0, abi.encodeWithSelector(Counter.setNumber.selector, number) - ); - } - - // Should not be allowed - function getNumberCounter3() external returns (uint256) { - bytes memory returnData = IPluginExecutor(msg.sender).executeFromPluginExternal( - counter3, 0, abi.encodePacked(bytes4(keccak256("number()"))) - ); - - return abi.decode(returnData, (uint256)); - } - - // Should not be allowed - function incrementCounter3() external { - IPluginExecutor(msg.sender).executeFromPluginExternal( - counter3, 0, abi.encodeWithSelector(Counter.increment.selector) - ); - } -} - -contract EFPCallerPluginAnyExternal is BasePlugin { - function onInstall(bytes calldata) external override {} - - function onUninstall(bytes calldata) external override {} - - function pluginManifest() external pure override returns (PluginManifest memory) { - PluginManifest memory manifest; - - manifest.executionFunctions = new ManifestExecutionFunction[](1); - manifest.executionFunctions[0] = ManifestExecutionFunction({ - executionSelector: this.passthroughExecute.selector, - isPublic: true, - allowDefaultValidation: false - }); - - manifest.permitAnyExternalAddress = true; - - return manifest; - } - - function pluginMetadata() external pure override returns (PluginMetadata memory) {} - - function passthroughExecute(address target, uint256 value, bytes calldata data) - external - payable - returns (bytes memory) - { - return IPluginExecutor(msg.sender).executeFromPluginExternal(target, value, data); - } -} diff --git a/test/mocks/plugins/PermittedCallMocks.sol b/test/mocks/plugins/PermittedCallMocks.sol new file mode 100644 index 00000000..450a70fb --- /dev/null +++ b/test/mocks/plugins/PermittedCallMocks.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import {ManifestExecutionFunction, PluginManifest, PluginMetadata} from "../../../src/interfaces/IPlugin.sol"; + +import {BasePlugin} from "../../../src/plugins/BasePlugin.sol"; +import {ResultCreatorPlugin} from "./ReturnDataPluginMocks.sol"; + +contract PermittedCallerPlugin is BasePlugin { + function onInstall(bytes calldata) external override {} + + function onUninstall(bytes calldata) external override {} + + function pluginManifest() external pure override returns (PluginManifest memory) { + PluginManifest memory manifest; + + manifest.executionFunctions = new ManifestExecutionFunction[](2); + manifest.executionFunctions[0].executionSelector = this.usePermittedCallAllowed.selector; + manifest.executionFunctions[1].executionSelector = this.usePermittedCallNotAllowed.selector; + + for (uint256 i = 0; i < manifest.executionFunctions.length; i++) { + manifest.executionFunctions[i].isPublic = true; + } + + // Request permission only for "foo", but not "bar", from ResultCreatorPlugin + manifest.permittedExecutionSelectors = new bytes4[](1); + manifest.permittedExecutionSelectors[0] = ResultCreatorPlugin.foo.selector; + + return manifest; + } + + function pluginMetadata() external pure override returns (PluginMetadata memory) {} + + // The manifest requested access to use the plugin-defined method "foo" + function usePermittedCallAllowed() external view returns (bytes memory) { + return abi.encode(ResultCreatorPlugin(msg.sender).foo()); + } + + // The manifest has not requested access to use the plugin-defined method "bar", so this should revert. + function usePermittedCallNotAllowed() external view returns (bytes memory) { + return abi.encode(ResultCreatorPlugin(msg.sender).bar()); + } +} diff --git a/test/mocks/plugins/ReturnDataPluginMocks.sol b/test/mocks/plugins/ReturnDataPluginMocks.sol index 5ab3a811..dae2c8e4 100644 --- a/test/mocks/plugins/ReturnDataPluginMocks.sol +++ b/test/mocks/plugins/ReturnDataPluginMocks.sol @@ -1,13 +1,18 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; +import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; + import { ManifestExecutionFunction, - ManifestExternalCallPermission, + ManifestAssociatedFunctionType, + ManifestAssociatedFunction, + ManifestFunction, PluginManifest, PluginMetadata } from "../../../src/interfaces/IPlugin.sol"; -import {IPluginExecutor} from "../../../src/interfaces/IPluginExecutor.sol"; +import {IValidation} from "../../../src/interfaces/IValidation.sol"; +import {IStandardExecutor} from "../../../src/interfaces/IStandardExecutor.sol"; import {BasePlugin} from "../../../src/plugins/BasePlugin.sol"; @@ -55,33 +60,51 @@ contract ResultCreatorPlugin is BasePlugin { function pluginMetadata() external pure override returns (PluginMetadata memory) {} } -contract ResultConsumerPlugin is BasePlugin { +contract ResultConsumerPlugin is BasePlugin, IValidation { ResultCreatorPlugin public immutable RESULT_CREATOR; RegularResultContract public immutable REGULAR_RESULT_CONTRACT; + error NotAuthorized(); + constructor(ResultCreatorPlugin _resultCreator, RegularResultContract _regularResultContract) { RESULT_CREATOR = _resultCreator; REGULAR_RESULT_CONTRACT = _regularResultContract; } - // Check the return data through the executeFromPlugin fallback case - function checkResultEFPFallback(bytes32 expected) external returns (bool) { - // This result should be allowed based on the manifest permission request - IPluginExecutor(msg.sender).executeFromPlugin(abi.encodeCall(ResultCreatorPlugin.foo, ())); + // Validation function implementations. We only care about the runtime validation function, to authorize + // itself. + + function validateUserOp(uint8, PackedUserOperation calldata, bytes32) external pure returns (uint256) { + revert NotImplemented(); + } + + function validateRuntime(uint8, address sender, uint256, bytes calldata, bytes calldata) external view { + if (sender != address(this)) { + revert NotAuthorized(); + } + } + + function validateSignature(uint8, address, bytes32, bytes calldata) external pure returns (bytes4) { + revert NotImplemented(); + } + // Check the return data through the fallback + function checkResultFallback(bytes32 expected) external view returns (bool) { + // This result should be allowed based on the manifest permission request bytes32 actual = ResultCreatorPlugin(msg.sender).foo(); return actual == expected; } - // Check the rturn data through the executeFromPlugin std exec case - function checkResultEFPExternal(address target, bytes32 expected) external returns (bool) { + // Check the return data through the execute with authorization case + function checkResultExecuteWithAuthorization(address target, bytes32 expected) external returns (bool) { // This result should be allowed based on the manifest permission request - bytes memory returnData = IPluginExecutor(msg.sender).executeFromPluginExternal( - target, 0, abi.encodeCall(RegularResultContract.foo, ()) + bytes memory returnData = IStandardExecutor(msg.sender).executeWithAuthorization( + abi.encodeCall(IStandardExecutor.execute, (target, 0, abi.encodeCall(RegularResultContract.foo, ()))), + abi.encodePacked(this, uint8(0), uint8(0)) // Validation function of self, selector-associated ); - bytes32 actual = abi.decode(returnData, (bytes32)); + bytes32 actual = abi.decode(abi.decode(returnData, (bytes)), (bytes32)); return actual == expected; } @@ -91,36 +114,26 @@ contract ResultConsumerPlugin is BasePlugin { function onUninstall(bytes calldata) external override {} function pluginManifest() external pure override returns (PluginManifest memory) { - // We want to return the address of the immutable RegularResultContract in the permitted external calls - // area of the manifest. - // However, reading from immutable values is not permitted in pure functions. So we use this hack to get - // around that. - // In regular, non-mock plugins, external call targets in the plugin manifest should be constants, not just - // immutbales. - // But to make testing easier, we do this. - - function() internal pure returns (PluginManifest memory) pureManifestGetter; - - function() internal view returns (PluginManifest memory) viewManifestGetter = _innerPluginManifest; - - assembly ("memory-safe") { - pureManifestGetter := viewManifestGetter - } - - return pureManifestGetter(); - } - - function _innerPluginManifest() internal view returns (PluginManifest memory) { PluginManifest memory manifest; + manifest.validationFunctions = new ManifestAssociatedFunction[](1); + manifest.validationFunctions[0] = ManifestAssociatedFunction({ + executionSelector: IStandardExecutor.execute.selector, + associatedFunction: ManifestFunction({ + functionType: ManifestAssociatedFunctionType.SELF, + functionId: uint8(0), + dependencyIndex: 0 + }) + }); + manifest.executionFunctions = new ManifestExecutionFunction[](2); manifest.executionFunctions[0] = ManifestExecutionFunction({ - executionSelector: this.checkResultEFPFallback.selector, + executionSelector: this.checkResultFallback.selector, isPublic: true, allowDefaultValidation: false }); manifest.executionFunctions[1] = ManifestExecutionFunction({ - executionSelector: this.checkResultEFPExternal.selector, + executionSelector: this.checkResultExecuteWithAuthorization.selector, isPublic: true, allowDefaultValidation: false }); @@ -128,16 +141,6 @@ contract ResultConsumerPlugin is BasePlugin { manifest.permittedExecutionSelectors = new bytes4[](1); manifest.permittedExecutionSelectors[0] = ResultCreatorPlugin.foo.selector; - manifest.permittedExternalCalls = new ManifestExternalCallPermission[](1); - - bytes4[] memory allowedSelectors = new bytes4[](1); - allowedSelectors[0] = RegularResultContract.foo.selector; - manifest.permittedExternalCalls[0] = ManifestExternalCallPermission({ - externalAddress: address(REGULAR_RESULT_CONTRACT), - permitAnySelector: false, - selectors: allowedSelectors - }); - return manifest; }