mirror of https://github.com/crytic/slither
Merge pull request #2392 from crytic/feat/unused-import
feat: add detector for unused importspull/2406/head
commit
beb3f38045
@ -0,0 +1,75 @@ |
||||
from typing import List |
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification, Output |
||||
|
||||
# pylint: disable=protected-access,too-many-nested-blocks |
||||
class UnusedImport(AbstractDetector): |
||||
""" |
||||
Detector unused imports. |
||||
""" |
||||
|
||||
ARGUMENT = "unused-import" |
||||
HELP = "Detects unused imports" |
||||
IMPACT = DetectorClassification.INFORMATIONAL |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#unused-imports" |
||||
|
||||
WIKI_TITLE = "Unused Imports" |
||||
WIKI_DESCRIPTION = "Importing a file that is not used in the contract likely indicates a mistake. The import should be removed until it is needed." |
||||
|
||||
# region wiki_exploit_scenario |
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
import {A} from "./A.sol"; |
||||
contract B {} |
||||
``` |
||||
B either should import from A and it was forgotten or the import is not needed and should be removed. |
||||
""" |
||||
# endregion wiki_exploit_scenario |
||||
WIKI_RECOMMENDATION = ( |
||||
"Remove the unused import. If the import is needed later, it can be added back." |
||||
) |
||||
|
||||
def _detect(self) -> List[Output]: |
||||
results: List[Output] = [] |
||||
# This is computed lazily and then memoized so we need to trigger the computation. |
||||
self.slither._compute_offsets_to_ref_impl_decl() |
||||
|
||||
for unit in self.slither.compilation_units: |
||||
for filename, scope in unit.scopes.items(): |
||||
unused = [] |
||||
for i in scope.imports: |
||||
# `scope.imports` contains all transitive imports so we need to filter out imports not explicitly imported in the file. |
||||
# Otherwise, we would recommend removing an import that is used by a leaf contract and cause compilation errors. |
||||
if i.scope != scope: |
||||
continue |
||||
|
||||
import_path = self.slither.crytic_compile.filename_lookup(i.filename) |
||||
|
||||
use_found = False |
||||
# Search through all references to the imported file |
||||
for _, refs in self.slither._offset_to_references[import_path].items(): |
||||
for ref in refs: |
||||
# If there is a reference in this file to the imported file, it is used. |
||||
if ref.filename == filename: |
||||
use_found = True |
||||
break |
||||
|
||||
if use_found: |
||||
break |
||||
|
||||
if not use_found: |
||||
unused.append(f"{i.source_mapping.content} ({i.source_mapping})") |
||||
|
||||
if len(unused) > 0: |
||||
unused_list = "\n\t-" + "\n\t-".join(unused) |
||||
|
||||
results.append( |
||||
self.generate_result( |
||||
[ |
||||
f"The following unused import(s) in {filename.used} should be removed: {unused_list}\n", |
||||
] |
||||
) |
||||
) |
||||
|
||||
return results |
@ -0,0 +1,6 @@ |
||||
The following unused import(s) in tests/e2e/detectors/test_data/unused-imports/0.8.16/B.sol should be removed: |
||||
-import "./A.sol"; (tests/e2e/detectors/test_data/unused-imports/0.8.16/B.sol#4) |
||||
|
||||
The following unused import(s) in tests/e2e/detectors/test_data/unused-imports/0.8.16/C.sol should be removed: |
||||
-import "./B.sol"; (tests/e2e/detectors/test_data/unused-imports/0.8.16/C.sol#4) |
||||
|
@ -0,0 +1,10 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
library A |
||||
{ |
||||
function a() public |
||||
{ |
||||
|
||||
} |
||||
} |
@ -0,0 +1,9 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./A.sol"; |
||||
|
||||
contract B |
||||
{ |
||||
|
||||
} |
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./B.sol"; |
||||
|
||||
contract C |
||||
{ |
||||
constructor() |
||||
{ |
||||
A.a(); |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,7 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
library ConstantContractLevel |
||||
{ |
||||
uint constant public CONSTANT = 0; |
||||
} |
@ -0,0 +1,9 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./ConstantContractLevel.sol"; |
||||
|
||||
contract ConstantContractLevelUsedInContractTest |
||||
{ |
||||
uint private v = ConstantContractLevel.CONSTANT; |
||||
} |
Binary file not shown.
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./ConstantContractLevel.sol"; |
||||
|
||||
uint constant __ = ConstantContractLevel.CONSTANT; |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy |
||||
{ |
||||
|
||||
} |
Binary file not shown.
@ -0,0 +1,10 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
uint constant ConstantTopLevel = 0; |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy |
||||
{ |
||||
|
||||
} |
@ -0,0 +1,9 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./ConstantTopLevel.sol"; |
||||
|
||||
contract ConstantTopLevelUsedInContractTest |
||||
{ |
||||
uint private v = ConstantTopLevel; |
||||
} |
Binary file not shown.
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./ConstantTopLevel.sol"; |
||||
|
||||
uint constant __ = ConstantTopLevel; |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy_ |
||||
{ |
||||
|
||||
} |
Binary file not shown.
@ -0,0 +1,7 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
contract Contract |
||||
{ |
||||
|
||||
} |
@ -0,0 +1,9 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./Contract.sol"; |
||||
|
||||
contract ContractUsedInContractTest1 |
||||
{ |
||||
Contract c; |
||||
} |
Binary file not shown.
@ -0,0 +1,9 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./Contract.sol"; |
||||
|
||||
contract ContractUsedInContractTest2 is Contract |
||||
{ |
||||
|
||||
} |
Binary file not shown.
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./Contract.sol"; |
||||
|
||||
Contract constant c = Contract(address(0x0)); |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy |
||||
{ |
||||
|
||||
} |
Binary file not shown.
@ -0,0 +1,10 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
error err(); |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy |
||||
{ |
||||
|
||||
} |
@ -0,0 +1,17 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomErrorTopLevel.sol"; |
||||
|
||||
contract CustomErrorTopLevelUsedInContractTest |
||||
{ |
||||
constructor() |
||||
{ |
||||
f(); |
||||
} |
||||
|
||||
function f() private pure |
||||
{ |
||||
revert err(); |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,7 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
library CustomEventContractLevel |
||||
{ |
||||
event CustomEvent(); |
||||
} |
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomEventContractLevel.sol"; |
||||
|
||||
contract CustomEventContractLevelUsedInContractTest |
||||
{ |
||||
function f() public |
||||
{ |
||||
emit CustomEventContractLevel.CustomEvent(); |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,15 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomEventContractLevel.sol"; |
||||
|
||||
function f() |
||||
{ |
||||
emit CustomEventContractLevel.CustomEvent(); |
||||
} |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy |
||||
{ |
||||
|
||||
} |
Binary file not shown.
@ -0,0 +1,7 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
contract CustomTypeContractLevel |
||||
{ |
||||
type CustomType is uint; |
||||
} |
@ -0,0 +1,9 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeContractLevel.sol"; |
||||
|
||||
contract CustomTypeContractLevelUsedInContractTest1 |
||||
{ |
||||
CustomTypeContractLevel.CustomType private v; |
||||
} |
Binary file not shown.
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeContractLevel.sol"; |
||||
|
||||
contract CustomTypeContractLevelUsedInContractTest2 |
||||
{ |
||||
function f(CustomTypeContractLevel.CustomType) public |
||||
{ |
||||
|
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,13 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeContractLevel.sol"; |
||||
|
||||
contract CustomTypeContractLevelUsedInContractTest3 |
||||
{ |
||||
modifier m() |
||||
{ |
||||
CustomTypeContractLevel.CustomType ___; |
||||
_; |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeContractLevel.sol"; |
||||
|
||||
contract CustomTypeContractLevelUsedInContractTest4 |
||||
{ |
||||
struct CustomStruct |
||||
{ |
||||
CustomTypeContractLevel.CustomType ___; |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,15 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeContractLevel.sol"; |
||||
|
||||
struct CustomTypeContractLevelUsedTopLevelTest1 |
||||
{ |
||||
CustomTypeContractLevel.CustomType __; |
||||
} |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy |
||||
{ |
||||
|
||||
} |
Binary file not shown.
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeContractLevel.sol"; |
||||
|
||||
CustomTypeContractLevel.CustomType constant __ = CustomTypeContractLevel.CustomType.wrap(0); |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy |
||||
{ |
||||
|
||||
} |
Binary file not shown.
@ -0,0 +1,10 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
type CustomType is uint; |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy |
||||
{ |
||||
|
||||
} |
@ -0,0 +1,9 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeTopLevel.sol"; |
||||
|
||||
contract CustomTypeTopLevelUsedInContractTest1 |
||||
{ |
||||
CustomType private v; |
||||
} |
Binary file not shown.
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeTopLevel.sol"; |
||||
|
||||
contract CustomTypeTopLevelUsedInContractTest2 |
||||
{ |
||||
function f(CustomType) public |
||||
{ |
||||
|
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,13 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeTopLevel.sol"; |
||||
|
||||
contract CustomTypeTopLevelUsedInContractTest3 |
||||
{ |
||||
modifier m() |
||||
{ |
||||
CustomType v; |
||||
_; |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeTopLevel.sol"; |
||||
|
||||
contract CustomTypeTopLevelUsedInContractTest4 |
||||
{ |
||||
struct CustomStruct |
||||
{ |
||||
CustomType ___; |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,15 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeTopLevel.sol"; |
||||
|
||||
struct CustomTypeTopLevelUsedTopLevelTest1 |
||||
{ |
||||
CustomType __; |
||||
} |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy_ |
||||
{ |
||||
|
||||
} |
Binary file not shown.
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./CustomTypeTopLevel.sol"; |
||||
|
||||
CustomType constant __ = CustomType.wrap(0); |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy_ |
||||
{ |
||||
|
||||
} |
Binary file not shown.
@ -0,0 +1,10 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
contract EnumContractLevel |
||||
{ |
||||
enum CustomEnum |
||||
{ |
||||
__ |
||||
} |
||||
} |
@ -0,0 +1,9 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./EnumContractLevel.sol"; |
||||
|
||||
contract EnumContractLevelUsedInContractTest |
||||
{ |
||||
uint private v = uint(EnumContractLevel.CustomEnum.__); |
||||
} |
Binary file not shown.
@ -0,0 +1,12 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
import "./EnumContractLevel.sol"; |
||||
|
||||
uint constant __ = uint(EnumContractLevel.CustomEnum.__); |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy |
||||
{ |
||||
|
||||
} |
Binary file not shown.
@ -0,0 +1,13 @@ |
||||
// SPDX-License-Identifier: Unlicense |
||||
pragma solidity 0.8.16; |
||||
|
||||
enum EnumTopLevel |
||||
{ |
||||
__ |
||||
} |
||||
|
||||
// dummy contract, so that "No contract were found ..." message is not being thrown by Slither |
||||
contract Dummy |
||||
{ |
||||
|
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue