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 Diamond (EIP-2535) bugs — facet selector collisions, init-vs-upgrade safety, storage-namespace collisions, facet selfdestruct paths, missing facet cuts. Activate on Diamond imports, DiamondCut, IDiamondLoupe, IDiamondCut, LibDiamond, facet patterns.
$ npx -y skills add omermaksutii/RugProof --skill diamond-eip2535 --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/diamond-eip2535Context preview
The summary Claude sees to decide when to auto-load this skill.
Detect Diamond (EIP-2535) bugs — facet selector collisions, init-vs-upgrade safety, storage-namespace collisions, facet selfdestruct paths, missing facet cuts. Activate on Diamond imports, DiamondCut, IDiamondLoupe, IDiamondCut, LibDiamond, facet patterns.
name: diamond-eip2535 description: Detect Diamond (EIP-2535) bugs — facet selector collisions, init-vs-upgrade safety, storage-namespace collisions, facet selfdestruct paths, missing facet cuts. Activate on Diamond imports, DiamondCut, IDiamondLoupe, IDiamondCut, LibDiamond, facet patterns.
Two facets implementing the same 4-byte selector (e.g. `function foo()` and `function bar(uint256)` that hash to the same selector). Diamond routes to the last-cut facet, but during a cut, the *old* version may be reachable.
Two facets using the same `bytes32 STORAGE_POSITION` slot prefix.
library LibA { bytes32 constant POS = keccak256("rugproof.a"); }
library LibB { bytes32 constant POS = keccak256("rugproof.a"); } // ← collisionUse unique namespace strings per facet.
Diamond init runs once via `delegatecall` to an Init contract. Re-running init after diamond-cut → can re-initialize values or run dangerous code. See [[initialization]].
function diamondCut(FacetCut[] calldata cuts, address init, bytes calldata data) external {
// ← no owner check
}Anyone can add/remove/replace facets.
Facet contract removed from blockchain (selfdestructed pre-6780, or simply deauthorized), but selectors still point to the old address → reverts.
A malicious facet replacement can hijack the entire diamond. Centralization risk depends on `diamondCut` authority.
Pre-Cancun: a facet calling `selfdestruct` deletes itself, breaking the diamond. Post-Cancun (EIP-6780): only delete-in-deploy-tx. Existing facets still risky if deployed before. See [[selfdestruct-eip6780]].
Without Loupe, off-chain consumers can't introspect facets. Soft requirement.
Internal functions in a facet aren't callable through the diamond (only externals are routed). Devs sometimes mistake the contracts.
`init` delegate-call during diamond-cut can reenter. Lock during cut.
If multiple facets share a storage struct, modifying struct fields requires coordinated upgrades. Refactoring one facet's view of the struct breaks others.
| Pattern | Severity | |---|---| | `diamondCut` lacks owner check | **Critical** | | Selector collision (or missed verification) | **Critical** | | Storage namespace collision | **Critical** | | Init function callable post-deploy | **High** | | Removing facet leaves dangling selectors | **High** | | Facet selfdestruct path (pre-6780 deploy) | **High** | | Missing Loupe | **Medium** | | Internal function mis-exposed | **Medium** |
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…