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 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`,
$ npx -y skills add omermaksutii/RugProof --skill permit2-patterns --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/permit2-patternsContext preview
The summary Claude sees to decide when to auto-load this skill.
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`,
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
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…