@@ -9,13 +9,20 @@ import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.so
99import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol " ;
1010import {ISingleOwnerPlugin} from "../../src/plugins/owner/ISingleOwnerPlugin.sol " ;
1111import {SingleOwnerPlugin} from "../../src/plugins/owner/SingleOwnerPlugin.sol " ;
12+ import {
13+ ManifestAssociatedFunctionType,
14+ ManifestExecutionHook,
15+ ManifestFunction,
16+ PluginManifest
17+ } from "../../src/interfaces/IPlugin.sol " ;
1218import {IPluginLoupe} from "../../src/interfaces/IPluginLoupe.sol " ;
1319import {IPluginManager} from "../../src/interfaces/IPluginManager.sol " ;
1420import {IStandardExecutor} from "../../src/interfaces/IStandardExecutor.sol " ;
1521import {FunctionReference, FunctionReferenceLib} from "../../src/libraries/FunctionReferenceLib.sol " ;
1622
1723import {MSCAFactoryFixture} from "../mocks/MSCAFactoryFixture.sol " ;
1824import {ComprehensivePlugin} from "../mocks/plugins/ComprehensivePlugin.sol " ;
25+ import {MockPlugin} from "../mocks/MockPlugin.sol " ;
1926
2027contract ModularAccountLoupeTest is Test {
2128 EntryPoint public entryPoint;
@@ -189,6 +196,104 @@ contract ModularAccountLoupeTest is Test {
189196 );
190197 }
191198
199+ function test_pluginLoupe_getHooks_multiple () public {
200+ // Add a second set of execution hooks to the account, and validate that it can return all hooks applied
201+ // over the function.
202+
203+ PluginManifest memory mockPluginManifest;
204+
205+ mockPluginManifest.executionHooks = new ManifestExecutionHook [](1 );
206+ mockPluginManifest.executionHooks[0 ] = ManifestExecutionHook ({
207+ executionSelector: ComprehensivePlugin.foo.selector ,
208+ preExecHook: ManifestFunction ({
209+ functionType: ManifestAssociatedFunctionType.SELF,
210+ functionId: 0 ,
211+ dependencyIndex: 0
212+ }),
213+ postExecHook: ManifestFunction ({
214+ functionType: ManifestAssociatedFunctionType.SELF,
215+ functionId: 0 ,
216+ dependencyIndex: 0
217+ })
218+ });
219+
220+ mockPluginManifest.permittedCallHooks = new ManifestExecutionHook [](2 );
221+ // Copy over the same hooks from executionHooks.
222+ mockPluginManifest.permittedCallHooks[0 ] = mockPluginManifest.executionHooks[0 ];
223+ mockPluginManifest.permittedCallHooks[1 ] = ManifestExecutionHook ({
224+ executionSelector: ComprehensivePlugin.foo.selector ,
225+ preExecHook: ManifestFunction ({
226+ functionType: ManifestAssociatedFunctionType.SELF,
227+ functionId: 1 ,
228+ dependencyIndex: 0
229+ }),
230+ postExecHook: ManifestFunction ({
231+ functionType: ManifestAssociatedFunctionType.SELF,
232+ functionId: 1 ,
233+ dependencyIndex: 0
234+ })
235+ });
236+
237+ MockPlugin mockPlugin = new MockPlugin (mockPluginManifest);
238+ bytes32 manifestHash = keccak256 (abi.encode (mockPlugin.pluginManifest ()));
239+
240+ account1.installPlugin (
241+ address (mockPlugin), manifestHash, "" , new FunctionReference [](0 ), new IPluginManager.InjectedHook [](0 )
242+ );
243+
244+ // Assert that the returned execution hooks are what is expected
245+
246+ IPluginLoupe.ExecutionHooks[] memory hooks = account1.getExecutionHooks (comprehensivePlugin.foo.selector );
247+
248+ assertEq (hooks.length , 2 );
249+ assertEq (
250+ FunctionReference.unwrap (hooks[0 ].preExecHook),
251+ FunctionReference.unwrap (
252+ FunctionReferenceLib.pack (
253+ address (comprehensivePlugin), uint8 (ComprehensivePlugin.FunctionId.PRE_EXECUTION_HOOK)
254+ )
255+ )
256+ );
257+ assertEq (
258+ FunctionReference.unwrap (hooks[0 ].postExecHook),
259+ FunctionReference.unwrap (
260+ FunctionReferenceLib.pack (
261+ address (comprehensivePlugin), uint8 (ComprehensivePlugin.FunctionId.POST_EXECUTION_HOOK)
262+ )
263+ )
264+ );
265+ assertEq (
266+ FunctionReference.unwrap (hooks[1 ].preExecHook),
267+ FunctionReference.unwrap (FunctionReferenceLib.pack (address (mockPlugin), uint8 (0 )))
268+ );
269+ assertEq (
270+ FunctionReference.unwrap (hooks[1 ].postExecHook),
271+ FunctionReference.unwrap (FunctionReferenceLib.pack (address (mockPlugin), uint8 (0 )))
272+ );
273+
274+ // Assert that the returned permitted call hooks are what is expected
275+
276+ hooks = account1.getPermittedCallHooks (address (mockPlugin), comprehensivePlugin.foo.selector );
277+
278+ assertEq (hooks.length , 2 );
279+ assertEq (
280+ FunctionReference.unwrap (hooks[0 ].preExecHook),
281+ FunctionReference.unwrap (FunctionReferenceLib.pack (address (mockPlugin), uint8 (0 )))
282+ );
283+ assertEq (
284+ FunctionReference.unwrap (hooks[0 ].postExecHook),
285+ FunctionReference.unwrap (FunctionReferenceLib.pack (address (mockPlugin), uint8 (0 )))
286+ );
287+ assertEq (
288+ FunctionReference.unwrap (hooks[1 ].preExecHook),
289+ FunctionReference.unwrap (FunctionReferenceLib.pack (address (mockPlugin), uint8 (1 )))
290+ );
291+ assertEq (
292+ FunctionReference.unwrap (hooks[1 ].postExecHook),
293+ FunctionReference.unwrap (FunctionReferenceLib.pack (address (mockPlugin), uint8 (1 )))
294+ );
295+ }
296+
192297 function test_pluginLoupe_getPreUserOpValidationHooks () public {
193298 FunctionReference[] memory hooks = account1.getPreUserOpValidationHooks (comprehensivePlugin.foo.selector );
194299
0 commit comments