# Static signatures bound to caller revert under ERC-4337, causing DoS

Bug Deep Dive #31 · 3 January 2026

Bug Deep Dives · [The Contest Academy](https://0xsimao.com/the-contest-academy) · 0xSimao

---

| Title | Static signatures bound to caller revert under ERC-4337, causing DoS |
| Reward | $1416, 3 Dups |
| Contest | Sequence - 7 October 2025 on Code4rena |
| Author | Agontuk |
| Context | ERC4337 |

Sequence wallets support ERC-4337 by validating signatures inside `validateUserOp()` in `ERC4337v07`. The function enforces that `msg.sender` is the entry point, then verifies the signature through an external self-call: `this.isValidSignature(userOpHash, userOp.signature)`.

Because of that external call, the `msg.sender` seen inside `isValidSignature()`, implemented in `BaseAuth`, is the wallet itself rather than the entry point. The static signature validation in `BaseAuth.signatureValidation()`, which enforces a caller binding, therefore fails whenever a non-zero expected caller is set to the entry point.

```solidity
// ERC4337v07
function validateUserOp(
  PackedUserOperation calldata userOp,
  bytes32 userOpHash,
  uint256 missingAccountFunds
) external returns (uint256 validationData) {
  if (entrypoint == address(0)) {
    revert ERC4337Disabled();
  }

  if (msg.sender != entrypoint) {
    revert InvalidEntryPoint(msg.sender);
  }

  // userOp.nonce is validated by the entrypoint

  if (missingAccountFunds != 0) {
    IEntryPoint(entrypoint).depositTo{ value: missingAccountFunds }(address(this));
  }

  if (this.isValidSignature(userOpHash, userOp.signature) != IERC1271_MAGIC_VALUE_HASH) { //@audit this will cause the msg.sender in isValidSignature to be ERC4337v07
    return SIG_VALIDATION_FAILED;
  }

  return 0;
}

// BaseAuth.sol

function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4) {
    Payload.Decoded memory payload = Payload.fromDigest(_hash);

    (bool isValid,) = signatureValidation(payload, _signature);
    if (!isValid) {
      return bytes4(0);
    }

    return IERC1271_MAGIC_VALUE_HASH;
}

function signatureValidation(
  Payload.Decoded memory _payload,
  bytes calldata _signature
) internal view virtual returns (bool isValid, bytes32 opHash) {
  // Read first bit to determine if static signature is used
  bytes1 signatureFlag = _signature[0];

  if (signatureFlag & 0x80 == 0x80) {
    opHash = _payload.hash();

    (address addr, uint256 timestamp) = _getStaticSignature(opHash);
    if (timestamp <= block.timestamp) {
      revert InvalidStaticSignatureExpired(opHash, timestamp);
    }

    if (addr != address(0) && addr != msg.sender) {
      revert InvalidStaticSignatureWrongCaller(opHash, msg.sender, addr);
    }

    return (true, opHash);
  }
```

**Alpha:** calling through `this` makes `msg.sender` become `address(this)` — check that this is intended.

**Conclusion**

This finding would earn you **\$1416**. Verify that `msg.sender` is the one the code expects.

[**Full Report**](https://code4rena.com/reports/2025-10-sequence#m-02-static-signatures-bound-to-caller-revert-under-erc-4337-causing-dos)\
[**Codebase**](https://github.com/code-423n4/2025-10-sequence/tree/b0e5fb15bf6735ec9aaba02f5eca28a7882d815d?tab=readme-ov-file)

---

Newer: [Factory deploy reverts instead of returning address when account already exists](https://0xsimao.com/the-contest-academy/bug-deep-dive-32) · Older: [Partial signature replay/frontrunning attack on session calls](https://0xsimao.com/the-contest-academy/bug-deep-dive-30)
