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 selfdestruct misuse and EIP-6780 implications post-Cancun — bricked contracts, broken `assert(balance == X)` invariants, factory patterns relying on redeploy, deployment-tx-only selfdestruct corner cases. Activate on `selfdestruct`, `suicide`, `CREATE2` factories,
$ npx -y skills add omermaksutii/RugProof --skill selfdestruct-eip6780 --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/selfdestruct-eip6780Context preview
The summary Claude sees to decide when to auto-load this skill.
Detect selfdestruct misuse and EIP-6780 implications post-Cancun — bricked contracts, broken `assert(balance == X)` invariants, factory patterns relying on redeploy, deployment-tx-only selfdestruct corner cases. Activate on `selfdestruct`, `suicide`, `CREATE2` factories,
name: selfdestruct-eip6780 description: Detect selfdestruct misuse and EIP-6780 implications post-Cancun — bricked contracts, broken `assert(balance == X)` invariants, factory patterns relying on redeploy, deployment-tx-only selfdestruct corner cases. Activate on `selfdestruct`, `suicide`, `CREATE2` factories, contracts asserting on `address(this).balance`.
After Cancun (March 2024), `selfdestruct` no longer deletes the contract's code or storage *unless* called in the same transaction as the contract's deployment. It does still transfer all ether to the recipient. This changes the security model substantially:
require(address(this).balance == expected); // ← attacker can `selfdestruct` ether to break this
Track expected balance in a state variable, not via `address(this).balance`.
// Pattern: deploy logic to deterministic addr, selfdestruct to "upgrade", redeploy. // ← Post-6780, code persists. Redeploy at same address fails or reverts.
Migrate to true proxy patterns.
A constructor that selfdestructs in the deploy tx truly deletes code+storage. Some "metamorphic" tricks abuse this.
Pre-6780-deployed diamond facets with selfdestruct paths remain dangerous. Even post-6780, a facet selfdestruct that orphans ether still costs.
Selfdestruct still forwards ether — recipient cannot revert on receive (selfdestruct bypasses fallback). So this isn't a DoS for the destructor, but can leave the recipient with unexpected balance.
Sometimes a useful pattern — note intent.
| Pattern | Severity | |---|---| | `address(this).balance == X` invariant | **High** | | Public `selfdestruct` path on deployed contract | **High** | | CREATE2 redeploy/upgrade pattern (post-Cancun broken) | **High** | | Diamond facet selfdestruct reachable | **High** | | Constructor metamorphic selfdestruct | **High** *(may be intentional, document)* | | `selfdestruct` to known revert-on-receive recipient | **Low** | | `selfdestruct` as legitimate recovery, properly guarded | **Info** |
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…