@@ -52,6 +52,12 @@ contract ReferenceModularAccount is
5252 ModuleEntity postExecHook;
5353 }
5454
55+ enum ValidationCheckingType {
56+ GLOBAL,
57+ SELECTOR,
58+ EITHER
59+ }
60+
5561 IEntryPoint private immutable _ENTRY_POINT;
5662
5763 // As per the EIP-165 spec, no interface should ever match 0xffffffff
@@ -187,7 +193,11 @@ contract ReferenceModularAccount is
187193
188194 // Check if the runtime validation function is allowed to be called
189195 bool isGlobalValidation = uint8 (authorization[24 ]) == 1 ;
190- _checkIfValidationAppliesCallData (data, runtimeValidationFunction, isGlobalValidation);
196+ _checkIfValidationAppliesCallData (
197+ data,
198+ runtimeValidationFunction,
199+ isGlobalValidation ? ValidationCheckingType.GLOBAL : ValidationCheckingType.SELECTOR
200+ );
191201
192202 _doRuntimeValidation (runtimeValidationFunction, data, authorization[25 :]);
193203
@@ -343,7 +353,11 @@ contract ReferenceModularAccount is
343353 ModuleEntity userOpValidationFunction = ModuleEntity.wrap (bytes24 (userOp.signature[:24 ]));
344354 bool isGlobalValidation = uint8 (userOp.signature[24 ]) == 1 ;
345355
346- _checkIfValidationAppliesCallData (userOp.callData, userOpValidationFunction, isGlobalValidation);
356+ _checkIfValidationAppliesCallData (
357+ userOp.callData,
358+ userOpValidationFunction,
359+ isGlobalValidation ? ValidationCheckingType.GLOBAL : ValidationCheckingType.SELECTOR
360+ );
347361
348362 // Check if there are permission hooks associated with the validator, and revert if the call isn't to
349363 // `executeUserOp`
@@ -549,7 +563,7 @@ contract ReferenceModularAccount is
549563 ModuleEntity directCallValidationKey =
550564 ModuleEntityLib.pack (msg .sender , DIRECT_CALL_VALIDATION_ENTITYID);
551565
552- _checkIfValidationAppliesCallData (msg .data , directCallValidationKey, false );
566+ _checkIfValidationAppliesCallData (msg .data , directCallValidationKey, ValidationCheckingType.EITHER );
553567
554568 // Direct call is allowed, run associated permission & validation hooks
555569
@@ -645,7 +659,7 @@ contract ReferenceModularAccount is
645659 function _checkIfValidationAppliesCallData (
646660 bytes calldata callData ,
647661 ModuleEntity validationFunction ,
648- bool isGlobal
662+ ValidationCheckingType checkingType
649663 ) internal view {
650664 bytes4 outerSelector = bytes4 (callData[:4 ]);
651665 if (outerSelector == this .executeUserOp.selector ) {
@@ -655,7 +669,7 @@ contract ReferenceModularAccount is
655669 outerSelector = bytes4 (callData[:4 ]);
656670 }
657671
658- _checkIfValidationAppliesSelector (outerSelector, validationFunction, isGlobal );
672+ _checkIfValidationAppliesSelector (outerSelector, validationFunction, checkingType );
659673
660674 if (outerSelector == IModularAccount.execute.selector ) {
661675 (address target ,,) = abi.decode (callData[4 :], (address , uint256 , bytes ));
@@ -689,26 +703,50 @@ contract ReferenceModularAccount is
689703 revert SelfCallRecursionDepthExceeded ();
690704 }
691705
692- _checkIfValidationAppliesSelector (nestedSelector, validationFunction, isGlobal );
706+ _checkIfValidationAppliesSelector (nestedSelector, validationFunction, checkingType );
693707 }
694708 }
695709 }
696710 }
697711
698- function _checkIfValidationAppliesSelector (bytes4 selector , ModuleEntity validationFunction , bool isGlobal )
699- internal
700- view
701- {
712+ function _checkIfValidationAppliesSelector (
713+ bytes4 selector ,
714+ ModuleEntity validationFunction ,
715+ ValidationCheckingType checkingType
716+ ) internal view {
702717 // Check that the provided validation function is applicable to the selector
703- if (isGlobal) {
704- if (! _globalValidationAllowed (selector) || ! _isValidationGlobal (validationFunction)) {
718+
719+ if (checkingType == ValidationCheckingType.GLOBAL) {
720+ if (! _globalValidationApplies (selector, validationFunction)) {
721+ revert ValidationFunctionMissing (selector);
722+ }
723+ } else if (checkingType == ValidationCheckingType.SELECTOR) {
724+ if (! _selectorValidationApplies (selector, validationFunction)) {
705725 revert ValidationFunctionMissing (selector);
706726 }
707727 } else {
708- // Not global validation, but per-selector
709- if (! getAccountStorage ().validationData[validationFunction].selectors.contains (toSetValue (selector))) {
728+ if (
729+ ! _globalValidationApplies (selector, validationFunction)
730+ && ! _selectorValidationApplies (selector, validationFunction)
731+ ) {
710732 revert ValidationFunctionMissing (selector);
711733 }
712734 }
713735 }
736+
737+ function _globalValidationApplies (bytes4 selector , ModuleEntity validationFunction )
738+ internal
739+ view
740+ returns (bool )
741+ {
742+ return _globalValidationAllowed (selector) && _isValidationGlobal (validationFunction);
743+ }
744+
745+ function _selectorValidationApplies (bytes4 selector , ModuleEntity validationFunction )
746+ internal
747+ view
748+ returns (bool )
749+ {
750+ return getAccountStorage ().validationData[validationFunction].selectors.contains (toSetValue (selector));
751+ }
714752}
0 commit comments