コード例 #1
0
    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
コード例 #2
0
    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
コード例 #3
0
    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
コード例 #4
0
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)
コード例 #5
0
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
コード例 #6
0
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)
コード例 #7
0
    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)
コード例 #8
0
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)
コード例 #9
0
    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
コード例 #10
0
    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
コード例 #11
0
    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
コード例 #12
0
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)
コード例 #13
0
    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
コード例 #14
0
    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