example-fork-detection
TEMPLATE — replace with the description of your rule. Should activate on the specific code patterns your fork has. Activate on…
Detect Permit2 / EIP-2612 lifecycle bugs — signature lifecycle, allowance transfer vs signature transfer confusion, nonce reuse, deadline manipulation, witness-data misuse. Activate on `permit`, `permitTransferFrom`, `IPermit2`, `SignatureTransfer`, `AllowanceTransfer`,
Claude Code
$ npx -y skills add omermaksutii/RugProof --skill permit2-patterns --agent claude-code
Codex
$ npx skills add omermaksutii/RugProof --skill permit2-patterns -a codex -y
Cursor
$ npx skills add omermaksutii/RugProof --skill permit2-patterns -a cursor -y
Gemini CLI
$ npx skills add omermaksutii/RugProof --skill permit2-patterns -a gemini-cli -y
GitHub Copilot
$ npx skills add omermaksutii/RugProof --skill permit2-patterns -a github-copilot -y
OpenCode
$ npx skills add omermaksutii/RugProof --skill permit2-patterns -a opencode -y
Windsurf
$ npx skills add omermaksutii/RugProof --skill permit2-patterns -a windsurf -y
name: permit2-patterns description: Detect Permit2 / EIP-2612 lifecycle bugs — signature lifecycle, allowance transfer vs signature transfer confusion, nonce reuse, deadline manipulation, witness-data misuse. Activate on `permit`, `permitTransferFrom`, `IPermit2`, `SignatureTransfer`, `AllowanceTransfer`, `PermitWitnessTransferFrom`, `PermitBatchTransferFrom`.
EIP-2612 (`permit`) — token-native gasless approval, per-token nonce. Permit2 (Uniswap) — canonical contract bridging legacy ERC20s into the permit world; two APIs:
permit2.permitTransferFrom(permit, transferDetails, owner, signature); // uses `transferDetails.requestedAmount` — caller-controlled
Caller can request `permit.permitted.amount` (the max), regardless of intent. App must enforce the actual transfer amount.
`permitWitnessTransferFrom` includes a user-signed `witness` blob. App must validate it matches the intended action; otherwise sig can be reused with different context.
SignatureTransfer is one-shot. AllowanceTransfer is persistent with nonce + expiration. Mixing → over-approval or replay.
Some implementations using AllowanceTransfer don't increment nonce after consumption.
Permit sigs without deadline are bearer instruments forever.
try IERC20Permit(token).permit(...) {} catch {}
token.transferFrom(...); // ← if permit fails, falls back to stale allowanceAcceptable IFF the app then validates allowance is sufficient.
Submitting `permit` in one tx then `transferFrom` in another lets a searcher front-run the permit and grief.
Some EIP-2612 impls cache DOMAIN_SEPARATOR in constructor. Post-chain-fork, this is wrong. Re-derive based on `block.chainid`. See [[signature-replay]].
DAI uses a non-standard permit signature (allowed-bool, no amount). Apps that hit DAI with standard EIP-2612 ABI will revert.
USDC uses `transferWithAuthorization` / `receiveWithAuthorization` instead of permit on most chains. Apps assuming permit-on-USDC break.
Custom permit impls that use a global nonce instead of per-signer nonce → cross-signer collision.
Permit2 uses a bitmap for nonces (word index + bit). Custom forks sometimes simplify this and break.
| Pattern | Severity | |---|---| | `permitTransferFrom` with caller-controlled requestedAmount | **Critical** | | AllowanceTransfer not invalidating nonce on one-shot use | **High** | | Sig without deadline | **High** | | Cached DOMAIN_SEPARATOR not fork-aware | **High** | | Witness ignored in permitWitnessTransferFrom | **High** | | Failed permit swallowed, allowance not re-checked | **Medium** | | Permit + tx unbundled (MEV grief) | **Medium** | | DAI/USDC-specific sig variant mishandled | **High** | | Global nonce instead of per-signer | **High** |
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…