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-20 token compatibility issues — fee-on-transfer, rebasing, non-standard return values, missing decimals(), low-decimal tokens, blacklistable tokens (USDC), pausable tokens. Activate on any ERC-20 integration, `transfer`/`transferFrom` use, balance-based accounting,
$ npx -y skills add omermaksutii/RugProof --skill token-compatibility --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/token-compatibilityContext preview
The summary Claude sees to decide when to auto-load this skill.
Detect ERC-20 token compatibility issues — fee-on-transfer, rebasing, non-standard return values, missing decimals(), low-decimal tokens, blacklistable tokens (USDC), pausable tokens. Activate on any ERC-20 integration, `transfer`/`transferFrom` use, balance-based accounting,
name: token-compatibility description: Detect ERC-20 token compatibility issues — fee-on-transfer, rebasing, non-standard return values, missing decimals(), low-decimal tokens, blacklistable tokens (USDC), pausable tokens. Activate on any ERC-20 integration, `transfer`/`transferFrom` use, balance-based accounting, decimal scaling.
uint256 before = token.balanceOf(address(this)); token.transferFrom(user, address(this), amount); shares = amount * X / Y; // ← uses `amount`, not actual received
Tokens like USDT (when fee enabled), SafeMoon, etc. take a fee. Use `balanceOf(this) - before` as the effective amount.
stETH, aUSDC, AMPL — balances change without `transfer`. Vaults assuming `balanceOf` ≡ deposit will mis-account. Either don't accept rebasing tokens, or use share-based accounting (wstETH-style wrappers).
USDT's `transfer` does NOT return bool (pre-`SafeERC20` use breaks):
bool ok = IERC20(usdt).transfer(to, amt); // ← reverts: ABI mismatch
Use OZ `SafeERC20` which uses low-level call + return-data inspection.
USDC, USDT can blacklist addresses. If a user gets blacklisted after deposit, the protocol may be unable to return funds → other users' funds stuck if pooled.
USDC, USDT can pause transfers. Protocol functions that must succeed (liquidations) may revert.
GUSD has 2 decimals. Math assuming 18 decimals causes huge rounding errors.
shares = assets * 1e18 / something; // ← shares now astronomical or zero
Reentrancy surface (see [[reentrancy]]). Many protocols implicitly assume vanilla ERC-20.
TUSD historically had two valid addresses. `transferFrom` could be invoked from either. Approval to one didn't bind the other.
Some tokens (early USDT) require `approve(spender, 0)` before `approve(spender, X)`. Use `safeApprove` or `forceApprove`. See [[approval-issues]].
Non-standard tokens may lack `decimals()`. Guard with try/catch and default to 18.
LEND, others. Cap-by-zero guards needed.
| Pattern | Severity | |---|---| | Vault accepts fee-on-transfer with no balance-delta accounting | **High** | | Protocol accepts rebasing token without share-wrapper | **High** | | Naive ERC-20 transfer (no SafeERC20) | **High** | | Pooled funds with blacklistable token + no escape hatch | **High** | | Low-decimal token with 18-decimal-assumed math | **High** | | Pausable token in liquidation path | **High** | | Approve-non-zero revert ignored | **High** | | Zero-amount-revert in batch flow | **Medium** | | Missing `decimals()` graceful handling | **Low** |
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…