mirror of https://github.com/crytic/slither
commit
95b09cc708
@ -0,0 +1,105 @@ |
|||||||
|
""" |
||||||
|
Module printing summary of the contract |
||||||
|
""" |
||||||
|
import logging |
||||||
|
|
||||||
|
from slither.printers.abstract_printer import AbstractPrinter |
||||||
|
from slither.utils.code_complexity import compute_cyclomatic_complexity |
||||||
|
from slither.utils.colors import green, red, yellow |
||||||
|
|
||||||
|
|
||||||
|
class PrinterHumanSummary(AbstractPrinter): |
||||||
|
ARGUMENT = 'human-summary' |
||||||
|
HELP = 'Print a human readable summary of the contracts' |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def get_summary_erc20(contract): |
||||||
|
txt = '' |
||||||
|
functions_name = [f.name for f in contract.functions] |
||||||
|
state_variables = [v.name for v in contract.state_variables] |
||||||
|
|
||||||
|
if 'pause' in functions_name: |
||||||
|
txt += "\t\t Can be paused? : {}\n".format(yellow('Yes')) |
||||||
|
else: |
||||||
|
txt += "\t\t Can be paused? : {}\n".format(green('No')) |
||||||
|
|
||||||
|
if 'mint' in functions_name: |
||||||
|
if not 'mintingFinished' in state_variables: |
||||||
|
txt += "\t\t Minting restriction? : {}\n".format(red('None')) |
||||||
|
else: |
||||||
|
txt += "\t\t Minting restriction? : {}\n".format(yellow('Yes')) |
||||||
|
else: |
||||||
|
txt += "\t\t Minting restriction? : {}\n".format(green('No Minting')) |
||||||
|
|
||||||
|
if 'increaseApproval' in functions_name or 'safeIncreaseAllowance' in functions_name: |
||||||
|
txt += "\t\t ERC20 race condition mitigation: {}\n".format(green('Yes')) |
||||||
|
else: |
||||||
|
txt += "\t\t ERC20 race condition mitigation: {}\n".format(red('No')) |
||||||
|
|
||||||
|
return txt |
||||||
|
|
||||||
|
def get_detectors_result(self): |
||||||
|
|
||||||
|
# disable detectors logger |
||||||
|
logger = logging.getLogger('Detectors') |
||||||
|
logger.setLevel(logging.ERROR) |
||||||
|
|
||||||
|
checks_informational = self.slither.detectors_informational |
||||||
|
checks_low = self.slither.detectors_low |
||||||
|
checks_medium = self.slither.detectors_medium |
||||||
|
checks_high = self.slither.detectors_high |
||||||
|
|
||||||
|
issues_informational = [c.detect() for c in checks_informational] |
||||||
|
issues_informational = [item for sublist in issues_informational for item in sublist] |
||||||
|
issues_low = [c.detect() for c in checks_low] |
||||||
|
issues_low = [c for c in issues_low if c] |
||||||
|
issues_medium = (c.detect() for c in checks_medium) |
||||||
|
issues_medium = [c for c in issues_medium if c] |
||||||
|
issues_high = [c.detect() for c in checks_high] |
||||||
|
issues_high = [c for c in issues_high if c] |
||||||
|
|
||||||
|
txt = "Number of informational issues: {}\n".format(green(len(issues_informational))) |
||||||
|
txt += "Number of low issues: {}\n".format(green(len(issues_low))) |
||||||
|
txt += "Number of medium issues: {}\n".format(yellow(len(issues_medium))) |
||||||
|
txt += "Number of high issues: {}\n".format(red(len(issues_high))) |
||||||
|
|
||||||
|
return txt |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def is_complex_code(contract): |
||||||
|
""" |
||||||
|
Check if the code is complex |
||||||
|
Heuristic, the code is complex if: |
||||||
|
- One function has a cyclomatic complexity > 7 |
||||||
|
Args: |
||||||
|
contract |
||||||
|
""" |
||||||
|
is_complex = False |
||||||
|
|
||||||
|
for f in contract.functions: |
||||||
|
if compute_cyclomatic_complexity(f) > 7: |
||||||
|
is_complex = True |
||||||
|
|
||||||
|
result = red('Yes') if is_complex else green('No') |
||||||
|
|
||||||
|
return "\tComplex code? {}\n".format(result) |
||||||
|
|
||||||
|
def output(self, _filename): |
||||||
|
""" |
||||||
|
_filename is not used |
||||||
|
Args: |
||||||
|
_filename(string) |
||||||
|
""" |
||||||
|
|
||||||
|
txt = "Analyze of {}\n".format(self.slither.filename) |
||||||
|
txt += self.get_detectors_result() |
||||||
|
for contract in self.slither.contracts_derived: |
||||||
|
txt += "\nContract {}\n".format(contract.name) |
||||||
|
txt += self.is_complex_code(contract) |
||||||
|
is_erc20 = contract.is_erc20() |
||||||
|
txt += '\tNumber of functions:{}'.format(len(contract.functions)) |
||||||
|
txt += "\tIs ERC20 token: {}\n".format(contract.is_erc20()) |
||||||
|
if is_erc20: |
||||||
|
txt += self.get_summary_erc20(contract) |
||||||
|
|
||||||
|
self.info(txt) |
Loading…
Reference in new issue