mirror of https://github.com/crytic/slither
parent
5faddb4e7f
commit
16393d51fe
@ -0,0 +1,18 @@ |
|||||||
|
from typing import Callable, List |
||||||
|
from dataclasses import dataclass |
||||||
|
|
||||||
|
from slither.tools.doctor.checks.platform import compile_project, detect_platform |
||||||
|
from slither.tools.doctor.checks.versions import show_versions |
||||||
|
|
||||||
|
|
||||||
|
@dataclass |
||||||
|
class Check: |
||||||
|
title: str |
||||||
|
function: Callable[..., None] |
||||||
|
|
||||||
|
|
||||||
|
ALL_CHECKS: List[Check] = [ |
||||||
|
Check("Software versions", show_versions), |
||||||
|
Check("Project platform", detect_platform), |
||||||
|
Check("Project compilation", compile_project), |
||||||
|
] |
@ -0,0 +1,59 @@ |
|||||||
|
import logging |
||||||
|
from pathlib import Path |
||||||
|
|
||||||
|
import crytic_compile.crytic_compile as crytic_compile |
||||||
|
|
||||||
|
from slither.tools.doctor.utils import snip_section |
||||||
|
from slither.utils.colors import red, yellow, green |
||||||
|
|
||||||
|
|
||||||
|
def detect_platform(project: str, **kwargs) -> None: |
||||||
|
path = Path(project) |
||||||
|
if path.is_file(): |
||||||
|
print( |
||||||
|
yellow( |
||||||
|
f"{project!r} is a file. Using it as target will manually compile your code with solc and _not_ use a compilation framework. Is that what you meant to do?" |
||||||
|
) |
||||||
|
) |
||||||
|
return |
||||||
|
|
||||||
|
print(f"Trying to detect project type for {project!r}") |
||||||
|
|
||||||
|
supported_platforms = crytic_compile.get_platforms() |
||||||
|
skip_platforms = {"solc", "solc-json", "archive", "standard", "etherscan"} |
||||||
|
detected_platforms = { |
||||||
|
platform.NAME: platform.is_supported(project, **kwargs) |
||||||
|
for platform in supported_platforms |
||||||
|
if platform.NAME.lower() not in skip_platforms |
||||||
|
} |
||||||
|
platform_qty = len([platform for platform, state in detected_platforms.items() if state]) |
||||||
|
|
||||||
|
print("Is this project using...") |
||||||
|
for platform, state in detected_platforms.items(): |
||||||
|
print(f" => {platform + '?':<15}{state and green('Yes') or red('No')}") |
||||||
|
print() |
||||||
|
|
||||||
|
if platform_qty == 0: |
||||||
|
print(red("No platform was detected! This doesn't sound right.")) |
||||||
|
print( |
||||||
|
yellow( |
||||||
|
"Are you trying to analyze a folder with standalone solidity files, without using a compilation framework? If that's the case, then this is okay." |
||||||
|
) |
||||||
|
) |
||||||
|
elif platform_qty > 1: |
||||||
|
print(red("More than one platform was detected! This doesn't sound right.")) |
||||||
|
print( |
||||||
|
red("Please use `--compile-force-framework` in Slither to force the correct framework.") |
||||||
|
) |
||||||
|
else: |
||||||
|
print(green("A single platform was detected."), yellow("Is it the one you expected?")) |
||||||
|
|
||||||
|
|
||||||
|
def compile_project(project: str, **kwargs): |
||||||
|
print("Invoking crytic-compile on the project, please wait...") |
||||||
|
|
||||||
|
try: |
||||||
|
crytic_compile.CryticCompile(project, **kwargs) |
||||||
|
except Exception as e: |
||||||
|
with snip_section("Project compilation failed :( The following error was generated:"): |
||||||
|
logging.exception(e) |
@ -0,0 +1,58 @@ |
|||||||
|
from importlib import metadata |
||||||
|
import json |
||||||
|
from typing import Optional |
||||||
|
from packaging.version import parse, LegacyVersion, Version |
||||||
|
import urllib |
||||||
|
|
||||||
|
from slither.utils.colors import yellow, green |
||||||
|
|
||||||
|
|
||||||
|
def get_installed_version(name: str) -> Optional[LegacyVersion | Version]: |
||||||
|
try: |
||||||
|
return parse(metadata.version(name)) |
||||||
|
except metadata.PackageNotFoundError: |
||||||
|
return None |
||||||
|
|
||||||
|
|
||||||
|
def get_github_version(name: str) -> Optional[LegacyVersion | Version]: |
||||||
|
try: |
||||||
|
with urllib.request.urlopen( |
||||||
|
f"https://api.github.com/repos/crytic/{name}/releases/latest" |
||||||
|
) as response: |
||||||
|
text = response.read() |
||||||
|
data = json.loads(text) |
||||||
|
return parse(data["tag_name"]) |
||||||
|
except: |
||||||
|
return None |
||||||
|
|
||||||
|
|
||||||
|
def show_versions(**kwargs) -> None: |
||||||
|
versions = { |
||||||
|
"Slither": (get_installed_version("slither-analyzer"), get_github_version("slither")), |
||||||
|
"crytic-compile": ( |
||||||
|
get_installed_version("crytic-compile"), |
||||||
|
get_github_version("crytic-compile"), |
||||||
|
), |
||||||
|
"solc-select": (get_installed_version("solc-select"), get_github_version("solc-select")), |
||||||
|
} |
||||||
|
|
||||||
|
outdated = { |
||||||
|
name |
||||||
|
for name, (installed, latest) in versions.items() |
||||||
|
if not installed or not latest or latest > installed |
||||||
|
} |
||||||
|
|
||||||
|
for name, (installed, latest) in versions.items(): |
||||||
|
color = yellow if name in outdated else green |
||||||
|
print(f"{name + ':':<16}{color(installed or 'N/A'):<16} (latest is {latest or 'Unknown'})") |
||||||
|
|
||||||
|
if len(outdated) > 0: |
||||||
|
print() |
||||||
|
print( |
||||||
|
yellow( |
||||||
|
f"Please update {', '.join(outdated)} to the latest release before creating a bug report." |
||||||
|
) |
||||||
|
) |
||||||
|
else: |
||||||
|
print() |
||||||
|
print(green("Your tools are up to date.")) |
@ -1,24 +0,0 @@ |
|||||||
from importlib import metadata |
|
||||||
import json |
|
||||||
from typing import Optional |
|
||||||
from packaging.version import parse, LegacyVersion, Version |
|
||||||
import urllib |
|
||||||
|
|
||||||
|
|
||||||
def get_installed_version(name: str) -> Optional[LegacyVersion | Version]: |
|
||||||
try: |
|
||||||
return parse(metadata.version(name)) |
|
||||||
except metadata.PackageNotFoundError: |
|
||||||
return None |
|
||||||
|
|
||||||
|
|
||||||
def get_github_version(name: str) -> Optional[LegacyVersion | Version]: |
|
||||||
try: |
|
||||||
with urllib.request.urlopen( |
|
||||||
f"https://api.github.com/repos/crytic/{name}/releases/latest" |
|
||||||
) as response: |
|
||||||
text = response.read() |
|
||||||
data = json.loads(text) |
|
||||||
return parse(data["tag_name"]) |
|
||||||
except: |
|
||||||
return None |
|
Loading…
Reference in new issue