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 centralization and trust-assumption risks — admin powers, single-key risk, missing timelocks, upgrade authority, treasury keys, pause permanence, blacklisting authority, oracle authority. Activate on `onlyOwner`, `onlyRole`, `AccessControl`, upgrade authorizations,
$ npx -y skills add omermaksutii/RugProof --skill centralization-risk --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/centralization-riskContext preview
The summary Claude sees to decide when to auto-load this skill.
Detect centralization and trust-assumption risks — admin powers, single-key risk, missing timelocks, upgrade authority, treasury keys, pause permanence, blacklisting authority, oracle authority. Activate on `onlyOwner`, `onlyRole`, `AccessControl`, upgrade authorizations,
name: centralization-risk description: Detect centralization and trust-assumption risks — admin powers, single-key risk, missing timelocks, upgrade authority, treasury keys, pause permanence, blacklisting authority, oracle authority. Activate on `onlyOwner`, `onlyRole`, `AccessControl`, upgrade authorizations, pause/unpause functions, mint/burn caps, treasury/fee setters.
Centralization findings are non-exploits in the traditional sense, but they're the most common reason audits flag a protocol as "rugpullable". The protocol can be the attacker. Investors deserve a clear inventory.
contract X is Ownable {
function upgradeTo(address impl) external onlyOwner { ... }
function setFee(uint256 fee) external onlyOwner { ... }
// ← one key, can pull rug
}Findings:
`onlyOwner` upgrades / fee changes / oracle changes that take effect immediately. Add a Timelock (OZ TimelockController), document the delay.
`pause()` with no auto-unpause. Owner can permanently freeze user funds.
function mint(address to, uint256 amt) external onlyMinter { _mint(to, amt); } // ← no cap, inflation riskA `blacklist(address)` function with no public criteria = "the protocol's discretion to freeze you".
function setOracle(address o) external onlyOwner { oracle = IOracle(o); }Admin → switches to malicious oracle → liquidates everyone.
`recoverERC20(token)` that can sweep user deposits.
Users should have a window after upgrade announcement to withdraw if they disagree. Without it, governance can rug by upgrade.
Ownable renounced but `DEFAULT_ADMIN_ROLE` retained. Or admin role transferred to a smart contract that has its own backdoor.
Marketed as "multi-sig" but `threshold == 1` defeats the purpose.
Single sequencer / centralized validator set. Document for bridges + L2 deployments.
Owner can drain treasury immediately.
See [[selfdestruct-eip6780]].
| Pattern | Severity | |---|---| | EOA controls upgrade + treasury + oracle | **Critical** *(for trust report)* | | Pause with no auto-unpause | **High** | | Mint with no cap | **High** | | Unrestricted blacklist | **High** | | No timelock on key params | **High** | | Sweep includes user deposits | **High** | | Multisig threshold = 1 | **High** | | Renounce + retained admin role | **High** | | Timelock < 24h on high-impact ops | **Medium** | | Single-sequencer L2 | **Medium-Info** *(contextual)* |
Centralization findings should produce a **"Trust report"** section in `/report`:
> **Admin powers:** > - `setOracle` — can replace price oracle → drain liquidations (no timelock). > - `upgradeTo` — can swap implementation (UUPS, no timelock). > - `recoverERC20` — can sweep any token, including user deposits. > - `pause` — can freeze withdrawals indefinitely (no auto-unpause). > - `setFee` — can set fee to 100% (no cap). > > **Mitigations in place:** > - Owner is a Gnosis Safe at `0x…` with 3/5 threshold. > - 24h Timelock at `0x…` mediates `setOracle` and `upgradeTo`. > > **Trust assumption:** Users must trust the multi-sig signers and the 24h timelock window.
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…