example-fork-detection
TEMPLATE — replace with the description of your rule. Should activate on the specific code patterns your fork has. Activate on `<your trigger keywords or…
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
$ npx -y skills add omermaksutii/RugProof --skill erc1271-contract-signatures --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/erc1271-contract-signaturesContext preview
The summary Claude sees to decide when to auto-load this skill.
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
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 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).
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);
}require(IERC1271(signer).isValidSignature(hash, sig) == 0x1626ba7c); // ← typo: should be 0x1626ba7e
Some old impls return `0x20c13b0b` (the legacy bytes-based variant). Spec is hash-based `0x1626ba7e`. Mixing → reject valid sigs.
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.
If owner rotates, previously-validated signatures may now be valid by different signer logic. Depends on wallet impl.
ERC-1271 returns `bytes4`. Naive callers using `staticcall` + manual returndata parsing can mis-decode.
Smart wallet impl can spend unbounded gas in `isValidSignature` → relayer griefing.
Permit2 must handle contract signers. Apps that wrap Permit2 must too.
| 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** |
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
Repo: omermaksutii/RugProof
TEMPLATE — replace with the description of your rule. Should activate on the specific code patterns your fork has. Activate on `<your trigger keywords or…
Detect unsafe assumptions about Solady's gas-optimized ERC20/ERC2612 permit and DN404 metadata. Solady's ERC20 uses custom storage slots, returns bools via…
Detect front-runnable ownership initialization in Solady Ownable / OwnableRoles. Solady's `_initializeOwner` is a guarded one-time setter (it reverts with…
Detect Solady SafeTransferLib calls that assume the token has code. SafeTransferLib.safeTransfer/safeTransferFrom/safeApprove deliberately skip the EXTCODESIZE…
Detect Uniswap V4 hooks that fail to settle currency deltas with the PoolManager. Every credit/debit a hook creates (BeforeSwapDelta, afterSwap hookDelta,…
Detect Uniswap V4 hooks whose address-encoded permission flags don't match the callbacks the hook actually implements. In V4 the hook's permissions live in the…