Skip to content

Add detector for unused custom error definitions#2902

Open
ep0chzer0 wants to merge 5 commits intocrytic:masterfrom
ep0chzer0:feature/unused-custom-errors
Open

Add detector for unused custom error definitions#2902
ep0chzer0 wants to merge 5 commits intocrytic:masterfrom
ep0chzer0:feature/unused-custom-errors

Conversation

@ep0chzer0
Copy link
Contributor

Summary

Implements a new detector (unused-error) that identifies custom error definitions that are declared but never used in revert statements.

Fixes #2587

Features

  • Detects unused contract-level custom errors
  • Detects unused top-level (file-level) custom errors
  • Handles errors with and without parameters
  • Skips interface contracts (signature-only)

Example

contract VendingMachine {
    error Unauthorized();  // WARNING: declared but never used
    address payable owner = payable(msg.sender);

    function withdraw() public {
        // Missing: if (msg.sender != owner) revert Unauthorized();
        owner.transfer(address(this).balance);
    }
}

The detector will report: Unauthorized is declared but never used in VendingMachine

Test

Added test case in tests/e2e/detectors/test_data/unused-error/0.8.4/unused_custom_error.sol covering:

  • Contract-level unused errors (with and without parameters)
  • Top-level unused errors
  • Used errors (should not be flagged)
  • Interface errors (should not be flagged)

Checklist

  • Detector implementation
  • Test file
  • Registered in all_detectors.py
  • Added to test suite
  • Wiki documentation (to be added after merge)

🤖 Generated with Claude Code

@ep0chzer0 ep0chzer0 requested a review from smonicas as a code owner January 16, 2026 10:30
@ep0chzer0 ep0chzer0 force-pushed the feature/unused-custom-errors branch from 80e1b7b to 204452f Compare January 16, 2026 10:32
@ep0chzer0
Copy link
Contributor Author

Hi maintainers, could someone please approve the CI workflow runs when you get a chance? This PR is ready for review. Thanks!

@ep0chzer0
Copy link
Contributor Author

Note: I noticed there's an existing PR #2565 for similar functionality. However, this PR addresses the review feedback given on #2565:

  1. Instance comparison vs name comparison: feat: add detector for unused custom errors #2565 compares errors by name, which can cause false negatives when different contracts define errors with the same name. This PR compares actual CustomError instances using ir.function.custom_error, avoiding name collisions.

  2. Individual findings: feat: add detector for unused custom errors #2565 groups all unused errors into a single finding. This PR generates individual findings for each unused error, making it easier to track and fix each one separately.

  3. Cleaner output: Each finding includes the contract context (e.g., "Unauthorized is declared but never used in VendingMachine").

Happy to close this if maintainers prefer to continue with #2565, or this could serve as an alternative implementation addressing the review concerns.

@ep0chzer0 ep0chzer0 force-pushed the feature/unused-custom-errors branch 8 times, most recently from 43e7743 to 4ab2e28 Compare January 22, 2026 14:48
@ep0chzer0 ep0chzer0 force-pushed the feature/unused-custom-errors branch from 4ab2e28 to 2bd1306 Compare January 23, 2026 18:03
Implements a new detector (unused-error) that identifies custom error
definitions that are declared but never used in revert statements.

Features:
- Detects unused contract-level custom errors
- Detects unused top-level custom errors
- Handles errors with and without parameters
- Skips interface contracts (signature-only)

Fixes crytic#2587
@ep0chzer0 ep0chzer0 force-pushed the feature/unused-custom-errors branch from 2bd1306 to 2a8ebe0 Compare February 23, 2026 17:54
ep0chzer0 added a commit to ep0chzer0/slither that referenced this pull request Feb 23, 2026
Add two new informational detectors to identify dead code:

- `unused-events`: Detects events declared but never emitted anywhere
  in the compilation unit. Skips interface contracts and dependencies.

- `unused-modifiers`: Detects modifiers declared but never applied to
  any function. Handles inheritance correctly by skipping virtual
  modifiers that are overridden in child contracts.

Both detectors include comprehensive test contracts covering:
- Basic unused/used elements
- Inheritance chains (base events emitted by children)
- Virtual modifier override patterns
- Interface event declarations

Closes crytic#2782 (partial - errors covered by crytic#2902)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add detection for Unused User-Defined Error types

1 participant