Skip to content
Back to skills

Erc1271 Contract Signatures

ASecurity

Detect ERC-1271 contract-signature bugs — magic-value handling, signature validation edge cases, smart-wallet interactions (Safe, Argent), replay-via-signature-update. Activate on `isValidSignature`, ERC1271 imports, smart-wallet integration, signed orders that may originate from contracts.

  • 36 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 4, 2026
blockchaingit

Security analysis

A100/100

Scanned October 4, 2026

npx -y skills add iktok90-design/ai-smart-contract-auditor --skill erc1271-contract-signatures --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Erc1271 Contract Signatures?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Erc1271 Contract Signatures
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/iktok90-design-erc1271-contract-signatures/badge)](https://www.skillsdirectory.com/skills/iktok90-design-erc1271-contract-signatures)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: erc1271-contract-signatures
description: Detect ERC-1271 contract-signature bugs — magic-value handling, signature validation edge cases, smart-wallet interactions (Safe, Argent), replay-via-signature-update. Activate on `isValidSignature`, ERC1271 imports, smart-wallet integration, signed orders that may originate from contracts.
---

# ERC-1271 contract signatures detection

## Background

ERC-1271 lets contract accounts (smart wallets, multisigs) sign messages. Verification call:
```solidity
IERC1271(signer).isValidSignature(hash, sig) returns (bytes4 magicValue);
// magicValue must equal 0x1626ba7e
```

Without ERC-1271, smart-wallet users can't sign anything (no private key).

## When this applies

- Off-chain order signing (Seaport, Blur, X2Y2)
- Permit2 with smart-wallet senders
- EIP-712 verification paths
- Any `ecrecover(...) == signer` check that might accept contract signers

## Detection patterns

### Bypass via `ecrecover` for smart wallet (HIGH)
```solidity
require(ecrecover(hash, v, r, s) == signer, "bad sig");
// ← signer is a smart wallet, ecrecover returns address(0), check fails legitimately
```
The bug: contract owners can't sign at all. Add an ERC-1271 fallback:
```solidity
if (signer.code.length > 0) {
    require(IERC1271(signer).isValidSignature(hash, abi.encodePacked(r, s, v)) == 0x1626ba7e);
} else {
    require(ecrecover(hash, v, r, s) == signer);
}
```

### Wrong magic value check (HIGH)
```solidity
require(IERC1271(signer).isValidSignature(hash, sig) == 0x1626ba7c);   // ← typo: should be 0x1626ba7e
```

### Pre-EIP-1271 magic value (HIGH)
Some old impls return `0x20c13b0b` (the legacy bytes-based variant). Spec is hash-based `0x1626ba7e`. Mixing → reject valid sigs.

### Replay via signature-update on smart wallet (HIGH)
A Safe's `isValidSignature` checks owner approvals. If signature is approved via on-chain `approveHash` then consumed, can it be re-approved later? Replay risk.

### Smart wallet rotation breaks past sigs (LOW-MEDIUM)
If owner rotates, previously-validated signatures may now be valid by different signer logic. Depends on wallet impl.

### Returning data length issues (HIGH)
ERC-1271 returns `bytes4`. Naive callers using `staticcall` + manual returndata parsing can mis-decode.

### Gas griefing in isValidSignature (MEDIUM)
Smart wallet impl can spend unbounded gas in `isValidSignature` → relayer griefing.

### ERC-1271 + Permit2 (HIGH)
Permit2 must handle contract signers. Apps that wrap Permit2 must too.

## Severity rubric

| Pattern | Severity |
|---|---|
| App rejects smart-wallet users entirely (no 1271 fallback) | **High** *(usability — but also gives an exploitable bypass if mixed)* |
| Wrong magic value | **High** |
| Pre-EIP magic value not handled | **High** |
| Replay via approve-on-chain on Safe | **High** |
| Returning data length not validated | **High** |
| Unbounded gas in isValidSignature | **Medium** |

## Remediation patterns

- Use OZ `SignatureChecker.isValidSignatureNow(signer, hash, sig)` — handles both EOA and contract paths cleanly.
- Validate `magicValue == 0x1626ba7e` exactly.
- For Safe integration: use `SignMessageLib` and pre-approval flow.
- Bound gas: `(bool ok, bytes memory ret) = signer.staticcall{gas: 100_000}(...)`.

## False-positive notes

- Apps that explicitly don't support contract wallets (e.g. anti-Sybil) may intentionally reject. Confirm intent.

## Related

- [[signature-replay]]
- [[permit2-patterns]]
- [[aa-specialist]] (subagent)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…