@@ -112,6 +112,12 @@ contract WeightedECDSASigner is EIP712, SignerBase, IStatelessValidator, IStatel
112112 return _validateUserOpSignature (id, userOp, userOpHash, userOp.signature, msg .sender );
113113 }
114114
115+ /// @notice Validate an ERC-1271 signature
116+ /// @dev The `sender` parameter (requesting protocol) is intentionally unused.
117+ /// This signer authenticates the SIGNERS (guardians), not the requesting protocol.
118+ /// WARNING: Because sender is ignored, any protocol can request signature
119+ /// validation. If you need to restrict which protocols can request signatures,
120+ /// pair this signer with a CallerPolicy.
115121 function checkSignature (bytes32 id , address , bytes32 hash , bytes calldata sig )
116122 external
117123 view
@@ -148,6 +154,15 @@ contract WeightedECDSASigner is EIP712, SignerBase, IStatelessValidator, IStatel
148154 /**
149155 * @notice Internal function to validate user operation signatures
150156 * @dev Shared logic for both installed and stateless validator modes
157+ *
158+ * SECURITY: Split Signature Scheme
159+ * The first N-1 signatures verify a proposalHash (EIP-712 typed data covering
160+ * account, id, callData, and nonce). The last signature MUST verify the full
161+ * userOpHash to bind the complete UserOp (including gas fields).
162+ * This prevents a scenario where guardians approve a proposal but an attacker
163+ * manipulates gas parameters in the final UserOp.
164+ * A double-counting check ensures a guardian who signed both the proposalHash
165+ * and userOpHash only has their weight counted once.
151166 */
152167 function _validateUserOpSignature (
153168 bytes32 id ,
0 commit comments