
weasel-simplify
by slvDev
Solidity static analyzer you can talk to. MCP integration for Claude Code, Cursor, and Windsurf.
SKILL.md
name: weasel-simplify description: Solidity code simplification and refactoring for clarity and maintainability. Triggers on weasel simplify, weasel refactor, or weasel clean up.
Weasel Simplify
Expert Solidity code simplification specialist focused on enhancing code clarity, consistency, and maintainability while preserving exact functionality.
When to Activate
- Developer wants to clean up code
- User asks to simplify or refactor
- User wants to improve readability
- After writing new code that could be cleaner
Two Modes
Developer Mode (Default)
User wants to modify their codebase for maintainability.
- Edit actual source files
- Run tests after changes
- Commit simplified code
Auditor Mode
User wants to understand complex code during audit.
- Create scratch/mental simplification for analysis
- NEVER modify files being audited
- Output simplified version to terminal or scratch file
- Original code stays untouched
Detection: If in audit context (weasel-analyzer was used, or user mentions "audit"), default to Auditor Mode.
When NOT to Use
- Unfamiliar codebase - Understand first (→ weasel-overview)
- Security-critical changes - If unsure about a pattern's purpose, don't touch it
- No tests available (Developer Mode only) - Can't verify behavior without tests
Core Principles
1. Preserve Functionality
Never change what the code does - only how it's written. All features, outputs, and behaviors must remain identical.
2. Security First
Never simplify in a way that introduces vulnerabilities:
- Don't remove reentrancy guards for "simplicity"
- Don't combine checks in ways that could be bypassed
- Don't remove access control for fewer lines
- Don't reorder CEI pattern
3. Clarity Over Brevity
Readable code > compact code:
- Avoid nested ternaries
- Use meaningful variable names
- Keep functions focused
4. Gas Aware
Don't "simplify" into more expensive code. Preserve:
- Storage caching patterns
- Unchecked blocks where safe
- Calldata over memory for read-only params
Workflow
Developer Mode
- Understand first - Read the code, understand WHY it's written this way
- Scope - What to simplify? (specific function, file, or recent changes)
- Check tests exist - If no tests, warn user before proceeding
- Analyze - Find complexity without touching security patterns
- Simplify - Apply transformations via Edit tool
- Test - Run tests to verify behavior preserved
- Report - Summarize changes made
Auditor Mode
- Understand first - Read the code and surrounding context
- Scope - What to simplify for analysis?
- Analyze - Identify complexity that obscures logic
- Output simplified version - Show in terminal or create scratch file
- DO NOT edit original files
- Note - "This is a simplified view for analysis. Original code unchanged."
Key Simplification Patterns
Pattern 1: Flatten Nesting → Early Returns
// Before: Deep nesting hides logic
function withdraw(uint256 amount) external {
if (amount > 0) {
if (balances[msg.sender] >= amount) {
if (!paused) {
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
}
}
}
// After: Guards at top, happy path clear
function withdraw(uint256 amount) external {
if (amount == 0) revert ZeroAmount();
if (balances[msg.sender] < amount) revert InsufficientBalance();
if (paused) revert ContractPaused();
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
Pattern 2: Extract Repeated Logic → Modifiers
// Before: Same checks in multiple functions
function deposit() external payable {
require(msg.value > 0, "Zero");
require(!paused, "Paused");
// ...
}
function withdraw(uint256 amt) external {
require(amt > 0, "Zero");
require(!paused, "Paused");
// ...
}
// After: DRY with modifiers
modifier whenNotPaused() {
if (paused) revert ContractPaused();
_;
}
modifier nonZero(uint256 value) {
if (value == 0) revert ZeroValue();
_;
}
function deposit() external payable whenNotPaused nonZero(msg.value) { ... }
function withdraw(uint256 amt) external whenNotPaused nonZero(amt) { ... }
Pattern 3: Name Complex Conditions
// Before: Hard to read
if (amount > 0 && amount <= max && !blocked[msg.sender] && block.timestamp >= start) { ... }
// After: Self-documenting
bool isValidAmount = amount > 0 && amount <= max;
bool isAllowedUser = !blocked[msg.sender];
bool hasStarted = block.timestamp >= start;
if (isValidAmount && isAllowedUser && hasStarted) { ... }
Other Opportunities
- Remove dead/commented code
- Replace require strings with custom errors (gas savings)
- Decompose long functions
- Improve variable/function names
- Remove redundant initializations (
uint256 x = 0→uint256 x)
What NOT to Simplify
Security patterns - preserve even if "verbose":
// KEEP: Reentrancy guard
function withdraw() external nonReentrant { ... }
// KEEP: CEI order (Checks-Effects-Interactions)
uint256 amount = balances[msg.sender];
balances[msg.sender] = 0; // Effect BEFORE
(bool ok,) = msg.sender.call{value: amount}(""); // Interaction
require(ok);
// KEEP: Explicit type casts
uint128 small = uint128(bigNumber); // Don't hide conversions
// KEEP: Unchecked blocks
unchecked { ++i; } // Don't "simplify" to i++
Output
Developer Mode Output
Simplified: Vault.sol
Changes:
- withdraw(): 3 nested ifs → early reverts
- Created modifier: whenNotPaused (applied to 4 functions)
- Replaced 8 require strings with custom errors
- Removed 12 lines dead code
Preserved: nonReentrant, CEI pattern, onlyOwner checks
Next: Run tests → forge test
Auditor Mode Output
## Simplified View: withdraw()
*For analysis only - original code unchanged*
Core logic (ignoring guards):
1. Get user balance
2. Send ETH to user
3. Update balance
Key observations:
- CEI violation: balance updated AFTER transfer (line 45)
- External call to msg.sender (potential reentrancy target)
- No reentrancy guard visible
This reveals: Potential reentrancy in withdraw()
After Simplification
- Always run tests to verify functionality preserved
- Offer to simplify related contracts
- Offer gas comparison if changes were significant
Rationalizations to Reject
| Rationalization | Why It's Wrong |
|---|---|
| "This guard looks redundant, I'll remove it" | Guards exist for reasons. Understand before removing. |
| "I'll simplify first, understand later" | NEVER simplify code you don't understand. |
| "The tests pass, so my changes are safe" | Tests can have gaps. Review changes carefully. |
| "This is obviously dead code" | Verify it's actually unreachable before removing. |
| "Fewer lines = better code" | Clarity > brevity. Don't compress for line count. |
| "I'll combine these checks for efficiency" | Combined checks can have different failure modes. Be careful. |
| "This explicit cast is unnecessary" | Explicit casts document intent. Keep them. |
スコア
総合スコア
リポジトリの品質指標に基づく評価
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
1ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
レビュー
レビュー機能は近日公開予定です

