def output(self, _filename): """ _filename is not used Args: _filename(string) """ all_tables = [] all_txt = "" for contract in self.fortress.contracts_derived: txt = "\nContract %s" % contract.name table = MyPrettyTable(["Function", "require or assert"]) for function in contract.functions: require = function.all_slithir_operations() require = [ ir for ir in require if isinstance(ir, SolidityCall) and ir.function in require_or_assert ] require = [ir.node for ir in require] table.add_row([ function.name, self._convert([str(m.expression) for m in set(require)]), ]) txt += "\n" + str(table) self.info(txt) all_tables.append((contract.name, table)) all_txt += txt res = self.generate_output(all_txt) for name, table in all_tables: res.add_pretty_table(table, name) return res
def output(self, _filename): """ _filename is not used Args: _filename(string) """ txt = "" all_tables = [] for contract in self.fortress.contracts_derived: txt += "\n{}:\n".format(contract.name) table = MyPrettyTable(["Name", "Type", "Slot", "Offset"]) for variable in contract.state_variables_ordered: if not variable.is_constant: slot, offset = self.fortress.storage_layout_of( contract, variable) table.add_row([ variable.canonical_name, str(variable.type), slot, offset ]) all_tables.append((contract.name, table)) txt += str(table) + "\n" self.info(txt) res = self.generate_output(txt) for name, table in all_tables: res.add_pretty_table(table, name) return res
def output(self, _filename): """ _filename is not used Args: _filename(string) """ all_txt = "" all_tables = [] for contract in self.fortress.contracts_derived: txt = "\nContract %s" % contract.name table = MyPrettyTable(["Function", "Modifiers"]) for function in contract.functions: modifiers = function.modifiers for call in function.all_internal_calls(): if isinstance(call, Function): modifiers += call.modifiers for (_, call) in function.all_library_calls(): if isinstance(call, Function): modifiers += call.modifiers table.add_row( [function.name, [m.name for m in set(modifiers)]]) txt += "\n" + str(table) self.info(txt) res = self.generate_output(all_txt) for name, table in all_tables: res.add_pretty_table(table, name) return res
def output_detectors(detector_classes): detectors_list = [] for detector in detector_classes: argument = detector.ARGUMENT help_info = detector.HELP impact = detector.IMPACT require_proxy = detector.REQUIRE_PROXY require_v2 = detector.REQUIRE_CONTRACT_V2 detectors_list.append((argument, help_info, impact, require_proxy, require_v2)) table = MyPrettyTable(["Num", "Check", "What it Detects", "Impact", "Proxy", "Contract V2"]) # Sort by impact, confidence, and name detectors_list = sorted(detectors_list, key=lambda element: (element[2], element[0])) idx = 1 for (argument, help_info, impact, proxy, v2) in detectors_list: table.add_row( [ idx, argument, help_info, classification_txt[impact], "X" if proxy else "", "X" if v2 else "", ] ) idx = idx + 1 print(table)
def _all_properties(): table = MyPrettyTable(["Num", "Description", "Scenario"]) idx = 0 for scenario, value in ERC20_PROPERTIES.items(): for prop in value.properties: table.add_row([idx, prop.description, scenario]) idx = idx + 1 return table
def output_printers(printer_classes): printers_list = [] for printer in printer_classes: argument = printer.ARGUMENT help_info = printer.HELP printers_list.append((argument, help_info)) table = MyPrettyTable(["Num", "Printer", "What it Does"]) # Sort by impact, confidence, and name printers_list = sorted(printers_list, key=lambda element: (element[0])) idx = 1 for (argument, help_info) in printers_list: table.add_row([idx, argument, help_info]) idx = idx + 1 print(table)
def add_pretty_table( self, content: MyPrettyTable, name: str, additional_fields: Optional[Dict] = None, ): if additional_fields is None: additional_fields = {} type_specific_fields = {"content": content.to_json(), "name": name} element = _create_base_element("pretty_table", type_specific_fields, additional_fields) self._data["elements"].append(element)
def output_mutators(mutators_classes): mutators_list = [] for detector in mutators_classes: argument = detector.NAME help_info = detector.HELP fault_class = detector.FAULTCLASS.name fault_nature = detector.FAULTNATURE.name mutators_list.append((argument, help_info, fault_class, fault_nature)) table = MyPrettyTable( ["Num", "Name", "What it Does", "Fault Class", "Fault Nature"]) # Sort by class, nature, name mutators_list = sorted(mutators_list, key=lambda element: (element[2], element[3], element[0])) idx = 1 for (argument, help_info, fault_class, fault_nature) in mutators_list: table.add_row([idx, argument, help_info, fault_class, fault_nature]) idx = idx + 1 print(table)
def output(self, _filename): """ _filename is not used Args: _filename(string) """ all_tables = [] all_txt = "" txt = "" for c in self.contracts: if c.is_top_level: continue txt += "\nContract %s\n" % c.name table = MyPrettyTable(["Variable", "Dependencies"]) for v in c.state_variables: table.add_row([v.name, _get(v, c)]) txt += str(table) txt += "\n" for f in c.functions_and_modifiers_declared: txt += "\nFunction %s\n" % f.full_name table = MyPrettyTable(["Variable", "Dependencies"]) for v in f.variables: table.add_row([v.name, _get(v, f)]) for v in c.state_variables: table.add_row([v.canonical_name, _get(v, f)]) txt += str(table) self.info(txt) all_txt += txt all_tables.append((c.name, table)) res = self.generate_output(all_txt) for name, table in all_tables: res.add_pretty_table(table, name) return res
def output(self, _filename): """ _filename is not used Args: _filename(string) """ txt = "" all_tables = [] for contract in self.fortress.contracts_derived: txt += "\n{}:\n".format(contract.name) table = MyPrettyTable(["Name", "ID"]) for function in contract.functions: if function.visibility in ["public", "external"]: function_id = get_function_id(function.solidity_signature) table.add_row([ function.solidity_signature, f"{function_id:#0{10}x}" ]) for variable in contract.state_variables: if variable.visibility in ["public"]: sig = variable.function_name function_id = get_function_id(sig) table.add_row([sig, f"{function_id:#0{10}x}"]) txt += str(table) + "\n" all_tables.append((contract.name, table)) self.info(txt) res = self.generate_output(txt) for name, table in all_tables: res.add_pretty_table(table, name) return res
def output(self, _filename): """ _filename is not used Args: _filename(string) """ txt = "" all_tables = [] for contract in self.contracts: if contract.is_top_level: continue txt += "\nContract %s\n" % contract.name table = MyPrettyTable([ "Function", "State variables written", "Conditions on msg.sender" ]) for function in contract.functions: state_variables_written = [ v.name for v in function.all_state_variables_written() ] msg_sender_condition = self.get_msg_sender_checks(function) table.add_row([ function.name, str(state_variables_written), str(msg_sender_condition), ]) all_tables.append((contract.name, table)) txt += str(table) + "\n" self.info(txt) res = self.generate_output(txt) for name, table in all_tables: res.add_pretty_table(table, name) return res
def output_detectors(detector_classes): detectors_list = [] for detector in detector_classes: argument = detector.ARGUMENT # dont show the backdoor example if argument == "backdoor": continue help_info = detector.HELP impact = detector.IMPACT confidence = classification_txt[detector.CONFIDENCE] detectors_list.append((argument, help_info, impact, confidence)) table = MyPrettyTable( ["Num", "Check", "What it Detects", "Impact", "Confidence"]) # Sort by impact, confidence, and name detectors_list = sorted(detectors_list, key=lambda element: (element[2], element[3], element[0])) idx = 1 for (argument, help_info, impact, confidence) in detectors_list: table.add_row( [idx, argument, help_info, classification_txt[impact], confidence]) idx = idx + 1 print(table)
def output(self, _filename): # pylint: disable=too-many-locals """ _filename is not used Args: _filename(string) """ all_tables = [] all_txt = "" for c in self.contracts: if c.is_top_level: continue (name, inheritance, var, func_summaries, modif_summaries) = c.get_summary() txt = "\nContract %s" % name txt += "\nContract vars: " + str(var) txt += "\nInheritance:: " + str(inheritance) table = MyPrettyTable([ "Function", "Visibility", "Modifiers", "Read", "Write", "Internal Calls", "External Calls", ]) for ( _c_name, f_name, visi, modifiers, read, write, internal_calls, external_calls, ) in func_summaries: read = self._convert(read) write = self._convert(write) internal_calls = self._convert(internal_calls) external_calls = self._convert(external_calls) table.add_row([ f_name, visi, modifiers, read, write, internal_calls, external_calls, ]) txt += "\n \n" + str(table) table = MyPrettyTable([ "Modifiers", "Visibility", "Read", "Write", "Internal Calls", "External Calls", ]) for ( _c_name, f_name, visi, _, read, write, internal_calls, external_calls, ) in modif_summaries: read = self._convert(read) write = self._convert(write) internal_calls = self._convert(internal_calls) external_calls = self._convert(external_calls) table.add_row([ f_name, visi, read, write, internal_calls, external_calls ]) txt += "\n\n" + str(table) txt += "\n" self.info(txt) all_tables.append((name, table)) all_txt += txt res = self.generate_output(all_txt) for name, table in all_tables: res.add_pretty_table(table, name) return res
def output(self, _filename): # pylint: disable=too-many-locals,too-many-statements """ _filename is not used Args: _filename(string) """ txt = "\n" txt += self._compilation_type() results = { "contracts": { "elements": [] }, "number_lines": 0, "number_lines_in_dependencies": 0, "number_lines_assembly": 0, "standard_libraries": [], "ercs": [], "number_findings": dict(), "detectors": [], } lines_number = self._lines_number() if lines_number: total_lines, total_dep_lines, total_tests_lines = lines_number txt += f"Number of lines: {total_lines} (+ {total_dep_lines} in dependencies, + {total_tests_lines} in tests)\n" results["number_lines"] = total_lines results["number_lines__dependencies"] = total_dep_lines total_asm_lines = self._get_number_of_assembly_lines() txt += f"Number of assembly lines: {total_asm_lines}\n" results["number_lines_assembly"] = total_asm_lines ( number_contracts, number_contracts_deps, number_contracts_tests, ) = self._number_contracts() txt += f"Number of contracts: {number_contracts} (+ {number_contracts_deps} in dependencies, + {number_contracts_tests} tests) \n\n" ( txt_detectors, detectors_results, optimization, info, low, medium, high, ) = self.get_detectors_result() txt += txt_detectors results["number_findings"] = { "optimization_issues": optimization, "informational_issues": info, "low_issues": low, "medium_issues": medium, "high_issues": high, } results["detectors"] = detectors_results libs = self._standard_libraries() if libs: txt += f'\nUse: {", ".join(libs)}\n' results["standard_libraries"] = [str(l) for l in libs] ercs = self._ercs() if ercs: txt += f'ERCs: {", ".join(ercs)}\n' results["ercs"] = [str(e) for e in ercs] table = MyPrettyTable([ "Name", "# functions", "ERCS", "ERC20 info", "Complex code", "Features" ]) for contract in self.fortress.contracts_derived: if contract.is_from_dependency() or contract.is_test: continue is_complex = self.is_complex_code(contract) number_functions = self._number_functions(contract) ercs = ",".join(contract.ercs()) is_erc20 = contract.is_erc20() erc20_info = "" if is_erc20: erc20_info += self.get_summary_erc20(contract) features = "\n".join([ name for name, to_print in self._get_features(contract).items() if to_print ]) table.add_row([ contract.name, number_functions, ercs, erc20_info, is_complex, features, ]) self.info(txt + "\n" + str(table)) results_contract = output.Output("") for contract in self.fortress.contracts_derived: if contract.is_test or contract.is_from_dependency(): continue contract_d = { "contract_name": contract.name, "is_complex_code": self._is_complex_code(contract), "is_erc20": contract.is_erc20(), "number_functions": self._number_functions(contract), "features": [ name for name, to_print in self._get_features(contract).items() if to_print ], } if contract_d["is_erc20"]: pause, mint_limited, race_condition_mitigated = self._get_summary_erc20( contract) contract_d["erc20_pause"] = pause if mint_limited is not None: contract_d["erc20_can_mint"] = True contract_d["erc20_mint_limited"] = mint_limited else: contract_d["erc20_can_mint"] = False contract_d[ "erc20_race_condition_mitigated"] = race_condition_mitigated results_contract.add_contract(contract, additional_fields=contract_d) results["contracts"]["elements"] = results_contract.elements json = self.generate_output(txt, additional_fields=results) return json