Skip to content
Security
Skill

/erc1271-contract-signatures

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 plugin
rugproof
1052 skills23 agents45 commands4 hooks

Claude Code

$ npx -y skills add omermaksutii/RugProof --skill erc1271-contract-signatures --agent claude-code

SKILL.md

erc1271-contract-signatures.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:

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)

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:

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)

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)
Read more
@omermaksutii
Ships withrugproof

Rugproof your code before someone else does. 🌐 Live site: omermaksutii.github.io/RugProof 📦 Latest: v1.0.0 — 45 commands · 23 agents · 45 skills · 13 MCP servers · tested, offline-first, with rule packs, a benchmark, non-EVM coverage, and post-deploy

1052 skills23 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
10
Star history of omermaksutii/RugProof on GitHub, a chart by star-history.com

Other skills on rugproof.

More skills from other plugins.

api-security

api-security

Use for authorized security assessment of REST, GraphQL, WebSocket, or SOAP APIs, including discovery, authentication,…

@zhaoxuya520@zhaoxuya520Install Skill
nemoclaw-user-guide

nemoclaw-user-guide

Find official NemoClaw documentation for installation, configuration, operation, or troubleshooting. Also handles requested docs…

nemoclaw11d23k
@nvidia@nvidiaInstall Skill

Questions about erc1271-contract-signatures.

Which coding agents can use erc1271-contract-signatures?
erc1271-contract-signatures installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.