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 integer over/underflow in `unchecked` blocks, downcasting losses, fixed-point precision errors, division-before-multiplication, signed/unsigned mixing. Activate on any arithmetic in `unchecked { }`, `SafeCast`, `uintN(uintM(x))` casts, division and modulo,
$ npx -y skills add omermaksutii/RugProof --skill integer-issues --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/integer-issuesContext preview
The summary Claude sees to decide when to auto-load this skill.
Detect integer over/underflow in `unchecked` blocks, downcasting losses, fixed-point precision errors, division-before-multiplication, signed/unsigned mixing. Activate on any arithmetic in `unchecked { }`, `SafeCast`, `uintN(uintM(x))` casts, division and modulo,
name: integer-issues
description: Detect integer over/underflow in `unchecked` blocks, downcasting losses, fixed-point precision errors, division-before-multiplication, signed/unsigned mixing. Activate on any arithmetic in `unchecked { }`, `SafeCast`, `uintN(uintM(x))` casts, division and modulo, percentage/basis-points math, AMM share/asset math.unchecked {
balance[to] += amount; // ← if amount controlled, can overflow back to 0
}`unchecked` is fine for proven-safe accumulators (e.g. `++i` in bounded loops), not for value math.
uint256 fee = (amount / 100) * feeBps; // ← truncation; do (amount * feeBps) / 100
USDC = 6 decimals, WETH = 18, WBTC = 8. Mixing without scaling produces silent 1e10–1e12 errors.
uint256 wethValue = amountUsdc * price; // ← USDC 6dp × price 8dp = 14dp, need 18dp
uint128 sharesU128 = uint128(shares); // ← silently truncates if shares > 2^128
Use OZ `SafeCast`.
Compounding interest done as `principal * (1 + rate)^t` with too-few-decimal `rate`. Use ray (1e27) or wad (1e18) math via PRBMath / Solady.
ERC-4626 must round shares *down* on deposit (favor vault) and *up* on withdraw (favor vault). Reversed direction = donations-style drain. Use OZ `Math.mulDiv(_, _, _, Rounding.Down/Up)`.
int256 delta = int256(a) - int256(b); // a or b might be > 2^255, becomes negative silently
`block.timestamp` granularity differs (2s on Optimism, 250ms on Arbitrum). Slot-based deadlines can be off.
Custom `sqrt` implementations are notorious. Use Solady/PRBMath.
`fee_bps` should be capped (`fee_bps <= 10_000`).
| Pattern | Severity | |---|---| | Unchecked overflow on user input | **High** | | ERC-4626 round-direction wrong | **High** | | Decimal-mismatch in price/balance math | **High** | | Downcast losing high bits silently | **High** | | Division before multiplication on financial-critical path | **High** | | Custom sqrt/log without overflow proof | **Medium** | | Bps fee with no cap | **Low** | | Loop index underflow in pre-0.8 code | **High** | | Modulo-zero on attacker-controlled divisor | **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…