Skip to content

Commit c1b00b4

Browse files
ep0chzer0dguidoclaude
authored
Fix dead-code detector incorrectly flagging library functions (#2905)
* fix: exclude library functions from dead-code detector The dead-code detector incorrectly flagged library functions as dead code. This fix updates the type annotation and set comprehension to properly track library function canonical names. Also adds test case and snapshot for library function usage. Fixes #1265 * fix: address PR review feedback - Remove unused Contract import from dead_code.py - Fix misleading comment in test file that claimed unused library function should be flagged (library functions are excluded from dead-code detection) Co-Authored-By: Claude Opus 4.5 <[email protected]> --------- Co-authored-by: ep0chzer0 <[email protected]> Co-authored-by: Dan Guido <[email protected]> Co-authored-by: Claude Opus 4.5 <[email protected]>
1 parent d58413c commit c1b00b4

File tree

5 files changed

+49
-5
lines changed

5 files changed

+49
-5
lines changed

slither/detectors/functions/dead_code.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Module detecting dead code
33
"""
44

5-
from slither.core.declarations import Function, FunctionContract, Contract
5+
from slither.core.declarations import Function, FunctionContract
66
from slither.detectors.abstract_detector import (
77
AbstractDetector,
88
DetectorClassification,
@@ -53,12 +53,10 @@ def _detect(self) -> list[Output]:
5353
f.canonical_name for f in all_functions_called if isinstance(f, Function)
5454
}
5555
all_libss_called = [f.all_library_calls() for f in contract.functions_entry_points]
56-
all_libs_called: list[tuple[Contract, Function]] = [
56+
all_libs_called: list[Function] = [
5757
item.function for sublist in all_libss_called for item in sublist
5858
]
59-
functions_used |= {
60-
lib[1].canonical_name for lib in all_libs_called if isinstance(lib, tuple)
61-
}
59+
functions_used |= {f.canonical_name for f in all_libs_called if isinstance(f, Function)}
6260
for function in sorted(self.compilation_unit.functions, key=lambda x: x.canonical_name):
6361
if (
6462
function.visibility in ["public", "external"]

tests/e2e/detectors/snapshots/detectors__detector_DeadCode_0_8_0_dead_code_library_sol__0.txt

Whitespace-only changes.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
// Library with internal functions
5+
library MyLibrary {
6+
struct Data {
7+
uint256 value;
8+
}
9+
10+
// This function IS used via `using MyLibrary for Data`
11+
// Should NOT be flagged as dead code
12+
function getValue(Data storage self) internal view returns (uint256) {
13+
return self.value;
14+
}
15+
16+
// This function IS used via `using MyLibrary for Data`
17+
// Should NOT be flagged as dead code
18+
function setValue(Data storage self, uint256 newValue) internal {
19+
self.value = newValue;
20+
}
21+
22+
// This function is NOT used anywhere but library functions are excluded
23+
// from dead-code detection, so it should NOT be flagged
24+
function unusedLibraryFunction(Data storage self) internal pure returns (uint256) {
25+
return 42;
26+
}
27+
}
28+
29+
contract UsingLibrary {
30+
using MyLibrary for MyLibrary.Data;
31+
32+
MyLibrary.Data private data;
33+
34+
function store(uint256 value) external {
35+
data.setValue(value);
36+
}
37+
38+
function retrieve() external view returns (uint256) {
39+
return data.getValue();
40+
}
41+
}
Binary file not shown.

tests/e2e/detectors/test_detectors.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,11 @@ def id_test(test_item: Test):
13611361
"dead-code.sol",
13621362
"0.8.0",
13631363
),
1364+
Test(
1365+
all_detectors.DeadCode,
1366+
"dead-code-library.sol",
1367+
"0.8.0",
1368+
),
13641369
Test(
13651370
all_detectors.WriteAfterWrite,
13661371
"write-after-write.sol",

0 commit comments

Comments
 (0)