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 reentrancy vulnerabilities — classic, cross-function, and cross-contract (especially read-only reentrancy). Activate whenever Solidity/Vyper code performs external calls, low-level call/transfer/send, ERC-721 safeTransfer with a receiver hook, or any pattern where control
$ npx -y skills add omermaksutii/RugProof --skill reentrancy --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/reentrancyContext preview
The summary Claude sees to decide when to auto-load this skill.
Detect reentrancy vulnerabilities — classic, cross-function, and cross-contract (especially read-only reentrancy). Activate whenever Solidity/Vyper code performs external calls, low-level call/transfer/send, ERC-721 safeTransfer with a receiver hook, or any pattern where control
name: reentrancy description: Detect reentrancy vulnerabilities — classic, cross-function, and cross-contract (especially read-only reentrancy). Activate whenever Solidity/Vyper code performs external calls, low-level call/transfer/send, ERC-721 safeTransfer with a receiver hook, or any pattern where control flow leaves the contract before state finalization.
Trigger on any of:
function withdraw() external {
uint256 amt = balance[msg.sender];
(bool ok,) = msg.sender.call{value: amt}(""); // ← external call
require(ok);
balance[msg.sender] = 0; // ← state update AFTER call
}**Signal:** state mutation after external call. CEI (Checks-Effects-Interactions) violated.
Two functions sharing state where one calls externally and the other reads/mutates the same state. Attacker re-enters via the second function.
Contract A updates state, calls B; B calls back into a *different* contract C that reads A's stale state.
Victim contract reads `getReserves()` / `getPrice()` from a pool mid-callback, before the pool finalizes its state. Example: Curve pools, Balancer vaults, Uniswap V2 mid-`removeLiquidity`.
// Pool callback hits this view function before pool state is consistent.
function priceOf(address token) external view returns (uint256) {
return pool.getVirtualPrice(); // ← stale during reentrant call
}`_safeTransfer` calls `onERC721Received` on the recipient — if recipient is a contract, it can re-enter.
| Pattern | Severity | Notes | |---|---|---| | Funds-draining classic reentrancy | **Critical** | Direct loss of funds, no preconditions | | Cross-function with shared balance state | **High** | Requires specific call sequence | | Read-only reentrancy on price/oracle read | **High** | Common pattern, often missed | | Reentrancy gated by `onlyOwner` / trusted role | **Medium** | Centralization-bounded | | ERC-777 hook with no state-after-call writes | **Low** | Defense-in-depth issue | | Single-actor self-reentrancy with no value flow | **Info** | |
1. **CEI ordering** — effects before interactions, always. 2. **`nonReentrant` modifier** (`ReentrancyGuard` from OpenZeppelin). Add per-function. 3. **For read-only reentrancy** — guard the *view* function too, or use a separate "settled price" cache that only updates outside callbacks. Curve's solution: `withdraw_admin_fees` lock, Balancer's `ensureNotInVaultContext`. 4. **Pull over push payments** — let users withdraw rather than pushing transfers. 5. **Token whitelist** — avoid ERC-777 and rebasing tokens in untested paths.
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…