Echidna printer: add have_external_calls, and call_a_parameter info

pull/437/head
Josselin 5 years ago
parent aba525f402
commit faed844f2e
  1. 55
      slither/printers/guidance/echidna.py

@ -5,6 +5,7 @@ import json
from collections import defaultdict
from typing import Dict, List, Set, Tuple, Union, NamedTuple
from slither.analyses.data_dependency.data_dependency import is_dependent
from slither.core.cfg.node import Node
from slither.core.declarations import Function
from slither.core.declarations.solidity_variables import SolidityVariableComposed, SolidityFunction, SolidityVariable
@ -202,7 +203,7 @@ def _extract_function_relations(slither: Slither) -> Dict[str, Dict[str, Dict[st
for function in contract.functions_entry_points}
for function in contract.functions_entry_points:
ret[contract.name][_get_name(function)] = {"impacts": [],
"is_impacted_by": []}
"is_impacted_by": []}
for candidate, varsWritten in written.items():
if any((r in varsWritten for r in function.all_state_variables_read())):
ret[contract.name][_get_name(function)]["is_impacted_by"].append(candidate)
@ -212,6 +213,50 @@ def _extract_function_relations(slither: Slither) -> Dict[str, Dict[str, Dict[st
return ret
def _have_external_calls(slither: Slither) -> Dict[str, List[str]]:
"""
Detect the functions with external calls
:param slither:
:return:
"""
ret: Dict[str, List[str]] = defaultdict(list)
for contract in slither.contracts:
for function in contract.functions_entry_points:
if function.all_high_level_calls() or function.all_low_level_calls():
ret[contract.name].append(_get_name(function))
return ret
def _call_a_parameter(slither: Slither) -> Dict[str, List[Dict]]:
"""
Detect the functions with external calls
:param slither:
:return:
"""
# contract -> [ (function, idx, interface_called) ]
ret: Dict[str, List[Dict]] = defaultdict(list)
for contract in slither.contracts:
for function in contract.functions_entry_points:
for ir in function.all_slithir_operations():
if isinstance(ir, HighLevelCall):
for idx, parameter in enumerate(function.parameters):
if is_dependent(ir.destination, parameter, function):
ret[contract.name].append({
"function": _get_name(function),
"parameter_idx": idx,
"signature": _get_name(ir.function)
})
if isinstance(ir, LowLevelCall):
for idx, parameter in enumerate(function.parameters):
if is_dependent(ir.destination, parameter, function):
ret[contract.name].append({
"function": _get_name(function),
"parameter_idx": idx,
"signature": None
})
return ret
class Echidna(AbstractPrinter):
ARGUMENT = 'echidna'
HELP = 'Export Echidna guiding information'
@ -245,6 +290,10 @@ class Echidna(AbstractPrinter):
constructors = {contract.name: contract.constructor.full_name
for contract in self.slither.contracts if contract.constructor}
external_calls = _have_external_calls(self.slither)
call_parameters = _call_a_parameter(self.slither)
d = {'payable': payable,
'timestamp': timestamp,
'block_number': block_number,
@ -255,7 +304,9 @@ class Echidna(AbstractPrinter):
'constants_used': cst_used,
'constants_used_in_binary': cst_used_in_binary,
'functions_relations': functions_relations,
'constructors': constructors}
'constructors': constructors,
'have_external_calls': external_calls,
'call_a_parameter': call_parameters}
self.info(json.dumps(d, indent=4))

Loading…
Cancel
Save