Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 77 additions & 24 deletions docs/src/Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,36 +126,89 @@ Some options can be set through a json configuration file. By default, `slither.

Options passed via the CLI have priority over options set in the configuration file.

The following flags are supported:
Run `slither --list-config` to generate the supported configuration keys and their default values from the current Slither and `crytic-compile` defaults:

```sh
```json
{
"brownie_ignore_compile": false,
"buidler_cache_directory": "cache",
"buidler_ignore_compile": false,
"buidler_skip_directory_name_fix": false,
"codex": false,
"codex_contracts": "all",
"codex_log": false,
"codex_max_tokens": 300,
"codex_model": "text-davinci-003",
"codex_temperature": 0,
"compile_custom_build": null,
"compile_force_framework": null,
"compile_libraries": null,
"compile_remove_metadata": false,
"dapp_ignore_compile": false,
"detectors_to_exclude": null,
"detectors_to_include": null,
"detectors_to_run": "all",
"printers_to_run": None,
"detectors_to_exclude": None,
"detectors_to_include": None,
"exclude_dependencies": False,
"exclude_informational": False,
"exclude_optimization": False,
"exclude_low": False,
"exclude_medium": False,
"exclude_high": False,
"fail_on": FailOnLevel.PEDANTIC,
"json": None,
"sarif": None,
"disable_color": False,
"filter_paths": None,
"include_paths": None,
"generate_patches": False,
"skip_assembly": False,
"legacy_ast": False,
"zip": None,
"zip_type": "lzma",
"show_ignored_findings": False,
"disable_color": false,
"embark_ignore_compile": false,
"embark_overwrite_config": false,
"etherlime_compile_arguments": null,
"etherlime_ignore_compile": false,
"etherscan_api_key": null,
"etherscan_export_directory": "etherscan-contracts",
"etherscan_only_bytecode": false,
"etherscan_only_source_code": false,
"exclude_dependencies": false,
"exclude_high": false,
"exclude_informational": false,
"exclude_location": false,
"exclude_low": false,
"exclude_medium": false,
"exclude_optimization": false,
"export_dir": "crytic-export",
"fail_on": "pedantic",
"filter_paths": null,
"foundry_compile_all": false,
"foundry_ignore_compile": false,
"foundry_out_directory": null,
"generate_patches": false,
"hardhat_artifacts_directory": null,
"hardhat_cache_directory": null,
"hardhat_ignore_compile": false,
"ignore_compile": false,
"include_paths": null,
"json": null,
"json-types": "detectors,printers",
"legacy_ast": false,
"no_fail": false,
"npx_disable": false,
"printers_to_run": null,
"sarif": null,
"sarif_input": "export.sarif",
"sarif_triage": "export.sarif.sarifexplorer",
"show_ignored_findings": false,
"skip_assembly": false,
"skip_clean": false,
"solc": "solc",
"solc_args": null,
"solc_disable_warnings": false,
"solc_force_legacy_json": false,
"solc_remaps": null,
"solc_solcs_bin": null,
"solc_solcs_select": null,
"solc_standard_json": false,
"solc_working_dir": null,
"triage_database": "slither.db.json",
"truffle_build_directory": "build/contracts",
"truffle_ignore_compile": false,
"truffle_overwrite_config": false,
"truffle_overwrite_version": null,
"truffle_version": null,
"waffle_config_file": null,
"waffle_ignore_compile": false,
"warn_unused_ignores": false,
"zip": null,
"zip_type": "lzma"
}
```

For flags related to the compilation, see the [`crytic-compile` configuration](https://github.com/crytic/crytic-compile/blob/master/crytic_compile/cryticparser/defaults.py)
For details about the compilation-related flags, see the [`crytic-compile` configuration](https://github.com/crytic/crytic-compile/blob/master/crytic_compile/cryticparser/defaults.py).
15 changes: 15 additions & 0 deletions slither/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
defaults_flag_in_config,
output_detectors,
output_detectors_json,
output_config_json,
output_printers,
output_printers_json,
output_results_to_markdown,
Expand Down Expand Up @@ -614,6 +615,14 @@ def parse_args(
default=None,
)

group_misc.add_argument(
"--list-config",
help="List supported configuration file options with their default values",
action=ListConfig,
nargs=0,
default=False,
)

group_misc.add_argument(
"--change-line-prefix",
help="Change the line prefix (default #) for the displayed source codes (i.e. file.sol#1).",
Expand Down Expand Up @@ -743,6 +752,12 @@ def __call__(self, parser: Any, *args: Any, **kwargs: Any) -> None:
parser.exit()


class ListConfig(argparse.Action):
def __call__(self, parser: Any, *args: Any, **kwargs: Any) -> None:
print(json.dumps(output_config_json(), indent=4))
parser.exit()


class ListPrinters(argparse.Action):
def __call__(self, parser: Any, *args: Any, **kwargs: Any) -> None:
_, printers = get_detectors_and_printers()
Expand Down
20 changes: 18 additions & 2 deletions slither/utils/command_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import re
import logging
from collections import defaultdict
from typing import Any

from crytic_compile.cryticparser.defaults import (
DEFAULTS_FLAG_IN_CONFIG as DEFAULTS_FLAG_IN_CONFIG_CRYTIC_COMPILE,
Expand Down Expand Up @@ -79,6 +80,19 @@ class FailOnLevel(enum.Enum):
}


def _convert_config_default(value: Any) -> Any:
if isinstance(value, enum.Enum):
return value.value
return value


def output_config_json() -> dict[str, Any]:
return {
key: _convert_config_default(value)
for key, value in sorted(defaults_flag_in_config.items())
}


def read_config_file(args: argparse.Namespace) -> None:
# No config file was provided as an argument
if args.config_file is None:
Expand All @@ -99,8 +113,10 @@ def read_config_file(args: argparse.Namespace) -> None:
yellow(f"{args.config_file} has an unknown key: {key} : {elem}")
)
continue
if getattr(args, key) == defaults_flag_in_config[key]:
setattr(args, key, elem)
arg_key = key.replace("-", "_")
current_value = getattr(args, arg_key, defaults_flag_in_config[key])
if current_value == defaults_flag_in_config[key]:
setattr(args, arg_key, elem)
except json.decoder.JSONDecodeError as e:
logger.error(red(f"Impossible to read {args.config_file}, please check the file {e}"))
else:
Expand Down
48 changes: 48 additions & 0 deletions tests/unit/utils/test_command_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import argparse

from slither.utils.command_line import (
defaults_flag_in_config,
output_config_json,
read_config_file,
)


def test_output_config_json_serializes_defaults() -> None:
config = output_config_json()

assert config["fail_on"] == "pedantic"
assert config["json-types"] == "detectors,printers"
assert config.keys() == defaults_flag_in_config.keys()


def test_read_config_file_supports_hyphenated_keys(tmp_path) -> None:
config_file = tmp_path / "slither.config.json"
config_file.write_text('{"json-types": "detectors"}', encoding="utf8")
args = argparse.Namespace(
config_file=str(config_file),
json_types=defaults_flag_in_config["json-types"],
)

read_config_file(args)

assert args.json_types == "detectors"


def test_read_config_file_preserves_cli_override_for_hyphenated_keys(tmp_path) -> None:
config_file = tmp_path / "slither.config.json"
config_file.write_text('{"json-types": "detectors"}', encoding="utf8")
args = argparse.Namespace(config_file=str(config_file), json_types="printers")

read_config_file(args)

assert args.json_types == "printers"


def test_read_config_file_accepts_supported_key_absent_from_namespace(tmp_path) -> None:
config_file = tmp_path / "slither.config.json"
config_file.write_text('{"codex": true}', encoding="utf8")
args = argparse.Namespace(config_file=str(config_file))

read_config_file(args)

assert args.codex is True