Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions contracts/foundry.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"lib/forge-std": {
"rev": "1801b0541f4fda118a10798fd3486bb7051c5dd6"
},
"lib/openzeppelin-contracts": {
"tag": {
"name": "v5.5.0",
"rev": "fcbae5394ae8ad52d8e580a3477db99814b9d565"
}
}
}
38 changes: 35 additions & 3 deletions contracts/signature-validators.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,21 +162,49 @@ Default validator supporting standard ECDSA signatures. Automatically tries both

---

## SmartWalletValidator

**Location:** `src/sigValidators/SmartWalletValidator.sol`

### Description

Validator supporting smart contract wallet signatures through ERC-4337 account abstraction standards. Enables contract-based accounts to sign states.

### Signature Format

Variable length signature that depends on the smart contract wallet's implementation. The validator handles both deployed and undeployed contracts.

### Validation Logic

1. Try ERC-6492 validation first (supports undeployed contracts via counterfactual verification)
2. If contract is deployed, use ERC-1271 validation (`isValidSignature` method)
3. Return `VALIDATION_SUCCESS` if signature is valid according to the contract's logic, `VALIDATION_FAILURE` otherwise
Comment on lines +178 to +181
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Documentation describes validation order incorrectly.

The doc states ERC-6492 is tried first, then ERC-1271. The actual code in SwSignatureUtils.validateSmartWalletSigner does the opposite: it checks ERC-1271 first (for deployed wallets), then falls back to ERC-6492.

📝 Proposed fix to match the actual code
 ### Validation Logic
 
-1. Try ERC-6492 validation first (supports undeployed contracts via counterfactual verification)
-2. If contract is deployed, use ERC-1271 validation (`isValidSignature` method)
+1. If contract is deployed, try ERC-1271 validation (`isValidSignature` method)
+2. If signature is in ERC-6492 format, try ERC-6492 validation (supports undeployed contracts via counterfactual deployment)
 3. Return `VALIDATION_SUCCESS` if signature is valid according to the contract's logic, `VALIDATION_FAILURE` otherwise
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/signature-validators.md` around lines 178 - 181, The
documentation's described validation order is wrong — update the docs to match
the actual implementation in SwSignatureUtils.validateSmartWalletSigner which
checks ERC-1271 first for deployed wallets and only falls back to ERC-6492
(counterfactual) afterwards; change the numbered steps to reflect: 1) Try
ERC-1271 (`isValidSignature`) for deployed contracts, 2) If not applicable, try
ERC-6492 counterfactual verification, 3) Return VALIDATION_SUCCESS or
VALIDATION_FAILURE based on the contract verification result.


### Use Cases

- Smart contract wallets (Gnosis Safe, Argent, etc.)
- ERC-4337 account abstraction wallets
- Multi-signature contract accounts
- Social recovery wallets
- Any contract implementing ERC-1271

---

## SessionKeyValidator

**Location:** `src/sigValidators/SessionKeyValidator.sol`

### Description

Enables delegation to temporary session keys. Useful for hot wallets, time-limited access, and gasless transactions.
Enables delegation to temporary session keys. Useful for hot wallets, time-limited access, and gasless transactions. Supports both EOA and smart contract wallet signatures through ERC-4337 (via ERC-1271 and ERC-6492).

### Signature Format

```solidity
struct SessionKeyAuthorization {
address sessionKey; // Delegated signer
bytes32 metadataHash; // Hashed expiration, permissions, etc.
bytes authSignature; // Participant's authorization (65 bytes)
bytes authSignature; // Participant's authorization signature
}

bytes sigBody = abi.encode(SessionKeyAuthorization, bytes sessionKeySignature)
Expand All @@ -189,7 +217,11 @@ bytes sigBody = abi.encode(SessionKeyAuthorization, bytes sessionKeySignature)
1. Participant authorized the session key: `authData = abi.encode(sessionKey, metadataHash)`
2. Session key signed the state

Both use EIP-191 first, then raw ECDSA if that fails.
Both authorization and session key signatures support multiple formats:
- EIP-191 (standard wallet signatures)
- Raw ECDSA (tried if EIP-191 fails)
- ERC-1271 (smart contract wallet signatures)
- ERC-6492 (undeployed contract signatures)

### Metadata

Expand Down
6 changes: 3 additions & 3 deletions contracts/src/ChannelHub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ contract ChannelHub is IVault, ReentrancyGuard {
address user,
address node,
uint256 approvedSignatureValidators
) internal view {
) internal {
(ISignatureValidator userValidator, bytes calldata userSigData) =
_extractValidator(state.userSig, node, approvedSignatureValidators);
_validateSignature(channelId, state, userSigData, user, userValidator);
Expand All @@ -854,7 +854,7 @@ contract ChannelHub is IVault, ReentrancyGuard {
bytes calldata sigData,
address participant,
ISignatureValidator validator
) internal view {
) internal {
bytes memory signingData = Utils.toSigningData(state);
ValidationResult result = validator.validateSignature(channelId, signingData, sigData, participant);
require(ValidationResult.unwrap(result) != ValidationResult.unwrap(VALIDATION_FAILURE), IncorrectSignature());
Expand Down Expand Up @@ -906,7 +906,7 @@ contract ChannelHub is IVault, ReentrancyGuard {
address user,
address node,
ParticipantIndex challengerIdx
) internal view {
) internal {
bytes memory signingData = Utils.toSigningData(state);
bytes memory challengerSigningData = abi.encodePacked(signingData, "challenge");
address challenger = challengerIdx == ParticipantIndex.USER ? user : node;
Expand Down
3 changes: 2 additions & 1 deletion contracts/src/interfaces/ISignatureValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ ValidationResult constant VALIDATION_SUCCESS = ValidationResult.wrap(1);
interface ISignatureValidator {
/**
* @notice Validates a participant's signature
* @dev Some validators (e.g., SmartWalletValidator with ERC-6492) may modify state by deploying contracts
* @param channelId The channel identifier to be included in the signed message
* @param signingData The encoded state data (without channelId or signatures)
* @param signature The signature to validate
Expand All @@ -35,5 +36,5 @@ interface ISignatureValidator {
bytes calldata signingData,
bytes calldata signature,
address participant
) external view returns (ValidationResult);
) external returns (ValidationResult);
}
7 changes: 7 additions & 0 deletions contracts/src/sigValidators/EcdsaSignatureUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ library EcdsaSignatureUtils {
* @notice Validates that a signature was created by an expected signer
* @dev Tries EIP-191 recovery first (with Ethereum signed message prefix), then raw ECDSA if that fails.
* Hashes the message internally before recovery.
* Returns false for invalid signature formats (e.g., wrong length).
* @param message The message that was signed (will be hashed internally)
* @param signature The signature to validate (65 bytes ECDSA: r, s, v)
* @param expectedSigner The address that should have signed the message
Expand All @@ -28,6 +29,12 @@ library EcdsaSignatureUtils {
pure
returns (bool)
{
// ECDSA signatures must be exactly 65 bytes (r: 32, s: 32, v: 1)
// Return false for other lengths (e.g., ERC-6492 wrapped signatures)
if (signature.length != 65) {
return false;
}

bytes32 eip191Digest = message.toEthSignedMessageHash();
address recovered = eip191Digest.recover(signature);

Expand Down
36 changes: 31 additions & 5 deletions contracts/src/sigValidators/SessionKeyValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
VALIDATION_FAILURE
} from "../interfaces/ISignatureValidator.sol";
import {EcdsaSignatureUtils} from "./EcdsaSignatureUtils.sol";
import {SwSignatureUtils} from "./SwSignatureUtils.sol";
import {Utils} from "../Utils.sol";

/**
Expand Down Expand Up @@ -36,6 +37,7 @@ function toSigningData(SessionKeyAuthorization memory skAuth) pure returns (byte
* @notice Validator supporting session key delegation for temporary signing authority
* @dev Enables a participant to delegate signing authority to a session key with metadata.
* Useful for hot wallets, time-limited access, or gasless transactions.
* Supports both EOA (ECDSA) and smart contract wallet (ERC-1271/ERC-6492) signatures.
*
* Authorization Flow:
* 1. Participant signs a SessionKeyAuthorization to delegate to a session key
Expand All @@ -45,7 +47,10 @@ function toSigningData(SessionKeyAuthorization memory skAuth) pure returns (byte
* Signature Format:
* bytes sigBody = abi.encode(SessionKeyAuthorization skAuthorization, bytes signature)
*
* Where signature is a standard 65-byte EIP-191 or raw ECDSA signature of the packed state.
* Where signature can be:
* - Standard 65-byte EIP-191 or raw ECDSA signature (for EOAs)
* - ERC-1271 signature (for deployed smart wallets)
* - ERC-6492 signature (for undeployed smart wallets)
*
* Security Model:
* - Off-chain enforcement (Clearnode) should validate session key expiration and usage limits
Expand All @@ -58,7 +63,8 @@ contract SessionKeyValidator is ISignatureValidator {
* @dev Validates:
* 1. participant signed the SessionKeyAuthorization (with channelId binding)
* 2. sessionKey signed the full state message (channelId + signingData)
* Tries EIP-191 recovery first, then raw ECDSA for both signatures.
* Supports both EOA (ECDSA) and smart wallet (ERC-1271/ERC-6492) signatures.
* Tries ECDSA validation first, then smart wallet validation for both signatures.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inaccurate "tries ECDSA first" description in two NatSpec comments.

Both the validateSignature NatSpec (line 67) and the _validateSigner NatSpec (line 102) state "Tries ECDSA validation first, then smart wallet validation", implying a sequential attempt-then-fallback pattern. The actual implementation is a conditional router: it takes the smart-wallet path when signer.code.length != 0 or an ERC-6492 magic suffix is detected, and only otherwise falls through to ECDSA. No speculative ECDSA attempt is made for smart wallets.

✏️ Suggested fixes
- *      Tries ECDSA validation first, then smart wallet validation for both signatures.
+ *      Routes to smart wallet validation (ERC-1271/ERC-6492) if the signer has deployed code
+ *      or the signature carries the ERC-6492 magic suffix; otherwise uses ECDSA.
- * `@dev` Tries ECDSA validation first, then smart wallet validation
+ * `@dev` Routes to ERC-1271/ERC-6492 validation if the signer has deployed code or the signature
+ *      is ERC-6492 formatted; otherwise falls back to ECDSA validation.

Also applies to: 102-102

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/src/sigValidators/SessionKeyValidator.sol` at line 67, Update the
NatSpec for validateSignature and _validateSigner to accurately describe the
actual conditional routing: explain that the implementation selects the
smart-wallet validation path when the signer has code (signer.code.length != 0)
or when the signature has the ERC-6492 magic suffix, and otherwise uses ECDSA
validation; do not imply an attempted-then-fallback flow or that ECDSA is tried
first—document the decision criteria and the mutually exclusive branches
instead.

* @param channelId The channel identifier to include in state messages
* @param signingData The encoded state data (without channelId or signatures)
* @param signature Encoded as abi.encode(SessionKeyAuthorization, bytes signature)
Expand All @@ -70,24 +76,44 @@ contract SessionKeyValidator is ISignatureValidator {
bytes calldata signingData,
bytes calldata signature,
address participant
) external pure returns (ValidationResult) {
) external returns (ValidationResult) {
(SessionKeyAuthorization memory skAuth, bytes memory skSignature) =
abi.decode(signature, (SessionKeyAuthorization, bytes));

// Step 1: Verify participant authorized this session key
bytes memory authMessage = toSigningData(skAuth);
bool authResult = EcdsaSignatureUtils.validateEcdsaSigner(authMessage, skAuth.authSignature, participant);
bool authResult = _validateSigner(authMessage, skAuth.authSignature, participant);

if (!authResult) {
return VALIDATION_FAILURE;
}

// Step 2: Verify session key signed the full state message
bytes memory stateMessage = Utils.pack(channelId, signingData);
if (EcdsaSignatureUtils.validateEcdsaSigner(stateMessage, skSignature, skAuth.sessionKey)) {
if (_validateSigner(stateMessage, skSignature, skAuth.sessionKey)) {
return VALIDATION_SUCCESS;
} else {
return VALIDATION_FAILURE;
}
}

/**
* @notice Validates a signature for a given signer (EOA or smart wallet)
* @dev Tries ECDSA validation first, then smart wallet validation
* @param message The message that was signed
* @param signature The signature to validate
* @param signer The expected signer's address
* @return bool True if signature is valid, false otherwise
*/
function _validateSigner(bytes memory message, bytes memory signature, address signer)
private
returns (bool)
{
if (signer.code.length != 0 || SwSignatureUtils.isERC6492Signature(signature)) {
// If signer has code or signature is ERC-6492, treat as smart wallet
return SwSignatureUtils.validateSmartWalletSigner(message, signature, signer);
}

return EcdsaSignatureUtils.validateEcdsaSigner(message, signature, signer);
}
}
46 changes: 46 additions & 0 deletions contracts/src/sigValidators/SmartWalletValidator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;

import {
ISignatureValidator,
ValidationResult,
VALIDATION_SUCCESS,
VALIDATION_FAILURE
} from "../interfaces/ISignatureValidator.sol";
import {SwSignatureUtils} from "./SwSignatureUtils.sol";
import {Utils} from "../Utils.sol";

/**
* @title SmartWalletValidator
* @notice Signature validator supporting smart contract wallets via ERC-4337 standards
* @dev Supports ERC-1271 and ERC-6492 signatures.
*
* The validator prepends channelId to the signingData to construct the full message,
* then attempts validation in the order listed above.
*/
Comment on lines +13 to +20
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

NatDoc mentions EOA support but the validator only handles smart wallets.

Line 23 says "Validates a signature from either an EOA or smart contract wallet" but the implementation only calls SwSignatureUtils.validateSmartWalletSigner, which only supports ERC-1271/ERC-6492 — no ECDSA recovery for EOAs. Also, Line 15 references "ERC-4337 standards" but the actual standards used are ERC-1271 and ERC-6492, which are distinct from ERC-4337.

📝 Fix misleading documentation
 /**
  * `@title` SmartWalletValidator
- * `@notice` Signature validator supporting smart contract wallets via ERC-4337 standards
+ * `@notice` Signature validator supporting smart contract wallets via ERC-1271 and ERC-6492 standards
  * `@dev` Supports ERC-1271 and ERC-6492 signatures.
  *
...
     /**
-     * `@notice` Validates a signature from either an EOA or smart contract wallet
+     * `@notice` Validates a signature from a smart contract wallet
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/src/sigValidators/SmartWalletValidator.sol` around lines 13 - 20,
The NatSpec is misleading: update the contract-level and function-level comments
in SmartWalletValidator to accurately state that it validates only smart
contract wallets via ERC-1271 and ERC-6492 (remove or correct the ERC-4337
reference), and either (A) implement EOA signature support by adding ECDSA
recovery validation (e.g., add a validateEoaSigner flow alongside
SwSignatureUtils.validateSmartWalletSigner and call both in validateSignature),
or (B) explicitly document that SmartWalletValidator only supports smart
contract wallets and instruct callers to use a separate EOA validator; reference
SwSignatureUtils.validateSmartWalletSigner and the validateSignature entry point
when making these changes so the implementation and docs remain consistent.

contract SmartWalletValidator is ISignatureValidator {
/**
* @notice Validates a signature from either an EOA or smart contract wallet
* @dev Constructs the full message by prepending channelId to signingData,
* then tries validation in order: ERC-1271, ERC-6492
* @param channelId The channel identifier to include in the signed message
* @param signingData The encoded state data (without channelId or signatures)
* @param signature The signature to validate (format varies by wallet type)
* @param participant The expected signer's address
* @return result VALIDATION_SUCCESS if valid, VALIDATION_FAILURE otherwise
*/
function validateSignature(
bytes32 channelId,
bytes calldata signingData,
bytes calldata signature,
address participant
) external returns (ValidationResult) {
bytes memory message = Utils.pack(channelId, signingData);

if (SwSignatureUtils.validateSmartWalletSigner(message, signature, participant)) {
return VALIDATION_SUCCESS;
} else {
return VALIDATION_FAILURE;
}
}
}
125 changes: 125 additions & 0 deletions contracts/src/sigValidators/SwSignatureUtils.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;

import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";

/**
* @title SwSignatureUtils
* @notice Utility library for Smart Wallet signature validation
*/
library SwSignatureUtils {
using ECDSA for bytes32;
using MessageHashUtils for bytes;

bytes4 private constant ERC1271_MAGIC_VALUE = 0x1626ba7e;

bytes32 private constant ERC6492_MAGIC_SUFFIX = 0x6492649264926492649264926492649264926492649264926492649264926492;

/**
* @notice Thrown when ERC-6492 contract deployment fails
* @param factory The factory address that failed to deploy
* @param factoryCalldata The calldata that was used for deployment
*/
error ERC6492DeploymentFailed(address factory, bytes factoryCalldata);

/**
* @notice Thrown when deployed contract has no code after ERC-6492 deployment
* @param expectedSigner The address that should have been deployed
*/
error ERC6492NoCode(address expectedSigner);

/**
* @notice Validates a signature from a smart contract wallet only (no ECDSA)
* @dev Attempts validation in order: ERC-1271 (deployed), ERC-6492 (non-deployed)
* @param message The message that was signed (will be hashed internally)
* @param signature The signature to validate (format varies by wallet type)
* @param expectedSigner The smart contract wallet address
* @return bool True if signature is valid according to ERC-1271 or ERC-6492
*/
function validateSmartWalletSigner(bytes memory message, bytes memory signature, address expectedSigner)
internal
returns (bool)
{
bytes32 messageHash = keccak256(message);

if (expectedSigner.code.length > 0) {
if (isValidErc1271Signature(expectedSigner, messageHash, signature)) {
return true;
}
}

if (isERC6492Signature(signature)) {
return isValidERC6492Signature(messageHash, signature, expectedSigner);
}

return false;
}

/**
* @notice Validates an ERC-1271 signature for a deployed smart contract wallet
* @param signer The smart contract wallet address
* @param hash The hash of the signed message
* @param signature The signature bytes
* @return bool True if the contract returns the ERC-1271 magic value
*/
function isValidErc1271Signature(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
try IERC1271(signer).isValidSignature(hash, signature) returns (bytes4 magicValue) {
return magicValue == ERC1271_MAGIC_VALUE;
} catch {
return false;
}
}

/**
* @notice Checks if a signature is wrapped in ERC-6492 format
* @dev ERC-6492 signatures end with the magic suffix
* @param signature The signature to check
* @return bool True if signature contains ERC-6492 magic suffix
*/
function isERC6492Signature(bytes memory signature) internal pure returns (bool) {
if (signature.length < 32) {
return false;
}

bytes32 suffix;
assembly {
suffix := mload(add(signature, mload(signature)))
}

return suffix == ERC6492_MAGIC_SUFFIX;
}

/**
* @notice Checks the validity of a smart contract signature. If the expected signer has no code, it is deployed using the provided factory and calldata from the signature.
* Otherwise, it checks the signature using the ERC-1271 standard.
* @param msgHash The hash of the message to verify the signature against
* @param sig The signature to verify
* @param expectedSigner The address of the expected signer
* @return True if the signature is valid, false otherwise or if signer is not a contract
*/
function isValidERC6492Signature(bytes32 msgHash, bytes memory sig, address expectedSigner)
internal
returns (bool)
{
// Extract the signature data (remove the magic suffix)
uint256 dataLength = sig.length - 32;
bytes memory signatureData = new bytes(dataLength);

for (uint256 i = 0; i < dataLength; i++) {
signatureData[i] = sig[i];
}
Comment on lines +107 to +112
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Manual byte-by-byte copying in memory is very gas-inefficient in Solidity. Consider using assembly or a more optimized approach to slice the signature.


(address create2Factory, bytes memory factoryCalldata, bytes memory originalSig) =
abi.decode(signatureData, (address, bytes, bytes));

if (expectedSigner.code.length == 0) {
(bool success,) = create2Factory.call(factoryCalldata);
require(success, ERC6492DeploymentFailed(create2Factory, factoryCalldata));
require(expectedSigner.code.length != 0, ERC6492NoCode(expectedSigner));
}

return IERC1271(expectedSigner).isValidSignature(msgHash, originalSig) == ERC1271_MAGIC_VALUE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This call to isValidSignature should be wrapped in a try/catch block or use a low-level call. If the target contract reverts (e.g., it doesn't implement ERC-1271), the entire validation will revert, which can block protocol operations like challenges. For consistency, it should behave like isValidErc1271Signature on line 67.

        try IERC1271(expectedSigner).isValidSignature(msgHash, originalSig) returns (bytes4 magicValue) {
            return magicValue == ERC1271_MAGIC_VALUE;
        } catch {
            return false;
        }

}
Comment on lines +102 to +124
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Missing try/catch around the ERC-1271 call makes isValidERC6492Signature revert instead of returning false.

isValidErc1271Signature (Line 68) wraps the external call in try/catch, gracefully returning false on revert. But isValidERC6492Signature (Line 123) calls IERC1271.isValidSignature directly — if the deployed contract reverts (e.g., doesn't implement ERC-1271, or has an internal error), the entire transaction reverts instead of returning false.

This asymmetry means a malformed ERC-6492 signature pointing to an incompatible contract will revert the whole on-chain operation (channel creation, deposit, etc.) rather than just failing validation.

🐛 Proposed fix: wrap in try/catch like the ERC-1271 path
-        return IERC1271(expectedSigner).isValidSignature(msgHash, originalSig) == ERC1271_MAGIC_VALUE;
+        return isValidErc1271Signature(expectedSigner, msgHash, originalSig);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function isValidERC6492Signature(bytes32 msgHash, bytes memory sig, address expectedSigner)
internal
returns (bool)
{
// Extract the signature data (remove the magic suffix)
uint256 dataLength = sig.length - 32;
bytes memory signatureData = new bytes(dataLength);
for (uint256 i = 0; i < dataLength; i++) {
signatureData[i] = sig[i];
}
(address create2Factory, bytes memory factoryCalldata, bytes memory originalSig) =
abi.decode(signatureData, (address, bytes, bytes));
if (expectedSigner.code.length == 0) {
(bool success,) = create2Factory.call(factoryCalldata);
require(success, ERC6492DeploymentFailed(create2Factory, factoryCalldata));
require(expectedSigner.code.length != 0, ERC6492NoCode(expectedSigner));
}
return IERC1271(expectedSigner).isValidSignature(msgHash, originalSig) == ERC1271_MAGIC_VALUE;
}
function isValidERC6492Signature(bytes32 msgHash, bytes memory sig, address expectedSigner)
internal
returns (bool)
{
// Extract the signature data (remove the magic suffix)
uint256 dataLength = sig.length - 32;
bytes memory signatureData = new bytes(dataLength);
for (uint256 i = 0; i < dataLength; i++) {
signatureData[i] = sig[i];
}
(address create2Factory, bytes memory factoryCalldata, bytes memory originalSig) =
abi.decode(signatureData, (address, bytes, bytes));
if (expectedSigner.code.length == 0) {
(bool success,) = create2Factory.call(factoryCalldata);
require(success, ERC6492DeploymentFailed(create2Factory, factoryCalldata));
require(expectedSigner.code.length != 0, ERC6492NoCode(expectedSigner));
}
return isValidErc1271Signature(expectedSigner, msgHash, originalSig);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/src/sigValidators/SwSignatureUtils.sol` around lines 102 - 124, The
ERC-1271 call inside isValidERC6492Signature currently invokes
IERC1271(expectedSigner).isValidSignature directly and can bubble up a revert;
wrap that call in a try/catch similar to isValidErc1271Signature so any revert
returns false instead of reverting the whole transaction. Specifically, replace
the direct IERC1271(expectedSigner).isValidSignature(msgHash, originalSig)
invocation with a try IERC1271(expectedSigner).isValidSignature(msgHash,
originalSig) returns (bytes4 res) { return res == ERC1271_MAGIC_VALUE; } catch {
return false; } to mirror the safe behavior of isValidErc1271Signature.

}
Loading
Loading