example-fork-detection
TEMPLATE — replace with the description of your rule. Should activate on the specific code patterns your fork has. Activate on…
Detect signature-replay, EIP-712 / EIP-2612 mistakes, malleable signatures, cross-chain replay, missing nonces. Activate on `ecrecover`, `permit`, meta-transactions, signed orders, signed approvals, EIP-712 domain construction, gasless transaction relayers.
Claude Code
$ npx -y skills add omermaksutii/RugProof --skill signature-replay --agent claude-code
Codex
$ npx skills add omermaksutii/RugProof --skill signature-replay -a codex -y
Cursor
$ npx skills add omermaksutii/RugProof --skill signature-replay -a cursor -y
Gemini CLI
$ npx skills add omermaksutii/RugProof --skill signature-replay -a gemini-cli -y
GitHub Copilot
$ npx skills add omermaksutii/RugProof --skill signature-replay -a github-copilot -y
OpenCode
$ npx skills add omermaksutii/RugProof --skill signature-replay -a opencode -y
Windsurf
$ npx skills add omermaksutii/RugProof --skill signature-replay -a windsurf -y
name: signature-replay description: Detect signature-replay, EIP-712 / EIP-2612 mistakes, malleable signatures, cross-chain replay, missing nonces. Activate on `ecrecover`, `permit`, meta-transactions, signed orders, signed approvals, EIP-712 domain construction, gasless transaction relayers.
bytes32 digest = keccak256(abi.encode(sender, amount)); // ← no nonce, infinitely replayable require(ecrecover(digest, v, r, s) == sender);
EIP-712 domain MUST include `chainId`. Without it, signing on Ethereum replays on Optimism/Arbitrum/etc.
bytes32 domain = keccak256(abi.encode(EIP712_DOMAIN, name, version, /* no chainId */ , verifyingContract));
DOMAIN_SEPARATOR = _hashDomain(block.chainid); // ← cached in constructor, breaks after fork
Re-compute when `block.chainid` differs.
ECDSA accepts both `(r, s)` and `(r, n-s)` for valid signatures. If you use the digest as a uniqueness key, attacker can flip s and replay. Enforce `s ≤ secp256k1n/2` and `v ∈ {27, 28}`. Or use OpenZeppelin's `ECDSA.tryRecover` which already does this.
address signer = ecrecover(digest, v, r, s); // returns 0 on bad sig require(roles[signer]); // ← if roles[address(0)] is ever true (default mapping behavior), it bypasses
Always `require(signer != address(0))` after ecrecover, or use OZ ECDSA.
Missing `address(this)` / `verifyingContract` in the signed payload. Same admin sig usable on multiple deployments.
See [[mev-frontrunning]] §permit.
Off-chain signed orders where the maker can replay across fills if the order doesn't include `salt` + `nonce` + cancellation mechanism.
Mixing Permit2's `SignatureTransfer` (one-shot) vs `AllowanceTransfer` (persistent). Read the contract's docs carefully.
| Pattern | Severity | |---|---| | Missing nonce in signed payload | **Critical** | | Missing chainId — cross-chain replay possible | **Critical** | | `ecrecover` without `signer != address(0)` check | **High** | | Malleable signature accepted (no s-bound check) | **High** | | Cached DOMAIN_SEPARATOR without fork-aware re-compute | **High** | | Signed payload omits `verifyingContract` | **High** | | Order salt missing, no cancellation mechanism | **High** | | Off-by-one chainId for L2 chains (e.g. Polygon = 137 not 1) | **High** | | Permit gas-grief on revert reverts in batch | **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
TEMPLATE — replace with the description of your rule. Should activate on the specific code patterns your fork has. Activate on…
Detect unsafe assumptions about Solady's gas-optimized ERC20/ERC2612 permit and DN404 metadata. Solady's ERC20 uses custom…
Detect front-runnable ownership initialization in Solady Ownable / OwnableRoles. Solady's `_initializeOwner` is a guarded…
Detect Solady SafeTransferLib calls that assume the token has code. SafeTransferLib.safeTransfer/safeTransferFrom/safeApprove…
Detect Uniswap V4 hooks that fail to settle currency deltas with the PoolManager. Every credit/debit a hook creates…
Detect Uniswap V4 hooks whose address-encoded permission flags don't match the callbacks the hook actually implements. In V4 the…
Use for authorized security assessment of REST, GraphQL, WebSocket, or SOAP APIs, including discovery, authentication,…
Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys)…
Clean and finalize authorized natural-language text intended for readers by auditing suspicious invisible Unicode and rewriting…