From e364ba208ead091bfb0fab3e0a0d684b14d8f5b6 Mon Sep 17 00:00:00 2001 From: Josselin Date: Mon, 4 Nov 2019 13:24:21 +0100 Subject: [PATCH 1/2] API break: generate_json_result takes a list as input, instead of a str The list can contains str, or any elements that can be converted to a str with source mapping Ex: Variable, Contract, Event, Function, .. generate_json_result will automatically add the elements to the json. As a result, detectors only need to add the elements to the info list, and do not need to add the element to the json. AbstractDetectors has a STANDARD_JSON parameter, if set to False, generate_json_result will not add the elements to the json --- slither/__main__.py | 5 + slither/core/declarations/pragma_directive.py | 4 + slither/core/slither_core.py | 6 + slither/core/source_mapping/source_mapping.py | 20 +- slither/core/variables/local_variable.py | 2 +- slither/detectors/abstract_detector.py | 7 +- .../detectors/attributes/const_functions.py | 16 +- .../detectors/attributes/constant_pragma.py | 10 +- .../detectors/attributes/incorrect_solc.py | 4 +- slither/detectors/attributes/locked_ether.py | 14 +- .../erc/incorrect_erc20_interface.py | 9 +- .../erc/incorrect_erc721_interface.py | 7 +- .../erc/unindexed_event_parameters.py | 5 +- slither/detectors/examples/backdoor.py | 6 +- slither/detectors/functions/arbitrary_send.py | 11 +- .../detectors/functions/external_function.py | 13 +- slither/detectors/functions/suicidal.py | 6 +- .../naming_convention/naming_convention.py | 34 +- .../detectors/operations/block_timestamp.py | 12 +- .../detectors/operations/low_level_calls.py | 9 +- .../operations/unused_return_values.py | 10 +- .../detectors/operations/void_constructor.py | 8 +- .../detectors/reentrancy/reentrancy_benign.py | 19 +- .../detectors/reentrancy/reentrancy_eth.py | 18 +- .../reentrancy_read_before_write.py | 13 +- slither/detectors/shadowing/abstract.py | 8 +- .../detectors/shadowing/builtin_symbols.py | 29 +- slither/detectors/shadowing/local.py | 34 +- slither/detectors/shadowing/state.py | 8 +- slither/detectors/source/rtlo.py | 1 + slither/detectors/statements/assembly.py | 7 +- slither/detectors/statements/calls_in_loop.py | 5 +- .../statements/controlled_delegatecall.py | 9 +- .../detectors/statements/deprecated_calls.py | 12 +- .../statements/incorrect_strict_equality.py | 7 +- .../detectors/statements/too_many_digits.py | 7 +- slither/detectors/statements/tx_origin.py | 7 +- .../possible_const_state_variables.py | 5 +- .../uninitialized_local_variables.py | 10 +- .../uninitialized_state_variables.py | 13 +- .../uninitialized_storage_variables.py | 8 +- .../variables/unused_state_variables.py | 7 +- slither/slither.py | 2 + slither/utils/json_utils.py | 75 +- .../arbitrary_send-0.5.1.arbitrary-send.json | 22 +- .../arbitrary_send-0.5.1.arbitrary-send.txt | 4 +- .../arbitrary_send.arbitrary-send.json | 22 +- .../arbitrary_send.arbitrary-send.txt | 4 +- tests/expected_json/backdoor.backdoor.json | 11 +- tests/expected_json/backdoor.backdoor.txt | 6 +- tests/expected_json/backdoor.suicidal.json | 11 +- tests/expected_json/backdoor.suicidal.txt | 4 +- ...onst_state_variables.constable-states.json | 66 +- ...const_state_variables.constable-states.txt | 16 +- .../constant-0.5.1.constant-function.json | 11 +- .../constant-0.5.1.constant-function.txt | 4 +- .../constant.constant-function.json | 33 +- .../constant.constant-function.txt | 8 +- ..._delegatecall.controlled-delegatecall.json | 178 +++-- ...d_delegatecall.controlled-delegatecall.txt | 8 +- ...deprecated_calls.deprecated-standards.json | 88 +- .../deprecated_calls.deprecated-standards.txt | 20 +- .../erc20_indexed.erc20-indexed.json | 44 +- .../erc20_indexed.erc20-indexed.txt | 12 +- .../external_function.external-function.json | 55 +- ...incorrect_equality.incorrect-equality.json | 756 +++++++++--------- .../incorrect_equality.incorrect-equality.txt | 28 +- ...rrect_erc20_interface.erc20-interface.json | 216 ++++- ...orrect_erc20_interface.erc20-interface.txt | 16 +- ...ect_erc721_interface.erc721-interface.json | 390 +++++++-- ...rect_erc721_interface.erc721-interface.txt | 24 +- ...line_assembly_contract-0.5.1.assembly.json | 11 +- ...nline_assembly_contract-0.5.1.assembly.txt | 8 +- .../inline_assembly_contract.assembly.json | 11 +- .../inline_assembly_contract.assembly.txt | 8 +- ...nline_assembly_library-0.5.1.assembly.json | 22 +- ...inline_assembly_library-0.5.1.assembly.txt | 12 +- .../inline_assembly_library.assembly.json | 22 +- .../inline_assembly_library.assembly.txt | 12 +- .../locked_ether-0.5.1.locked-ether.json | 11 +- .../locked_ether-0.5.1.locked-ether.txt | 8 +- .../locked_ether.locked-ether.json | 11 +- .../locked_ether.locked-ether.txt | 8 +- .../low_level_calls.low-level-calls.json | 11 +- .../low_level_calls.low-level-calls.txt | 6 +- .../multiple_calls_in_loop.calls-loop.json | 68 +- .../multiple_calls_in_loop.calls-loop.txt | 8 +- .../naming_convention.naming-convention.json | 132 +-- .../naming_convention.naming-convention.txt | 28 +- .../old_solc.sol.json.solc-version.json | 11 +- .../old_solc.sol.json.solc-version.txt | 6 +- tests/expected_json/pragma.0.4.24.pragma.json | 11 +- tests/expected_json/pragma.0.4.24.pragma.txt | 8 +- .../reentrancy-0.5.1.reentrancy-eth.json | 22 +- .../reentrancy-0.5.1.reentrancy-eth.txt | 8 +- .../reentrancy.reentrancy-eth.json | 22 +- .../reentrancy.reentrancy-eth.txt | 8 +- .../right_to_left_override.rtlo.json | 11 +- .../right_to_left_override.rtlo.txt | 4 +- ...shadowing_abstract.shadowing-abstract.json | 11 +- .../shadowing_abstract.shadowing-abstract.txt | 4 +- ...ing_builtin_symbols.shadowing-builtin.json | 143 ++-- ...wing_builtin_symbols.shadowing-builtin.txt | 30 +- ...dowing_local_variable.shadowing-local.json | 55 +- ...adowing_local_variable.shadowing-local.txt | 28 +- ...dowing_state_variable.shadowing-state.json | 11 +- ...adowing_state_variable.shadowing-state.txt | 4 +- .../solc_version_incorrect.solc-version.json | 22 +- .../solc_version_incorrect.solc-version.txt | 8 +- ...on_incorrect_05.ast.json.solc-version.json | 22 +- ...ion_incorrect_05.ast.json.solc-version.txt | 8 +- tests/expected_json/timestamp.timestamp.json | 33 +- tests/expected_json/timestamp.timestamp.txt | 4 +- .../too_many_digits.too-many-digits.json | 463 ++++++++++- .../too_many_digits.too-many-digits.txt | 22 +- .../tx_origin-0.5.1.tx-origin.json | 152 +++- .../tx_origin-0.5.1.tx-origin.txt | 8 +- tests/expected_json/tx_origin.tx-origin.json | 152 +++- tests/expected_json/tx_origin.tx-origin.txt | 8 +- ...ked_lowlevel-0.5.1.unchecked-lowlevel.json | 113 +-- ...cked_lowlevel-0.5.1.unchecked-lowlevel.txt | 6 +- ...unchecked_lowlevel.unchecked-lowlevel.json | 111 +-- .../unchecked_lowlevel.unchecked-lowlevel.txt | 6 +- .../unchecked_send-0.5.1.unchecked-send.json | 127 +-- .../unchecked_send-0.5.1.unchecked-send.txt | 6 +- ...initialized-0.5.1.uninitialized-state.json | 44 +- ...ninitialized-0.5.1.uninitialized-state.txt | 12 +- .../uninitialized.uninitialized-state.json | 44 +- .../uninitialized.uninitialized-state.txt | 12 +- ...ed_local_variable.uninitialized-local.json | 62 +- ...zed_local_variable.uninitialized-local.txt | 6 +- ...storage_pointer.uninitialized-storage.json | 68 +- ..._storage_pointer.uninitialized-storage.txt | 6 +- .../unused_return.unused-return.json | 168 ++-- .../unused_return.unused-return.txt | 8 +- .../unused_state.unused-state.json | 44 +- .../unused_state.unused-state.txt | 12 +- tests/expected_json/void-cst.void-cst.json | 11 +- tests/expected_json/void-cst.void-cst.txt | 6 +- 139 files changed, 3160 insertions(+), 1987 deletions(-) diff --git a/slither/__main__.py b/slither/__main__.py index 5f9a68158..699134c58 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -331,6 +331,11 @@ def parse_args(detector_classes, printer_classes): action='store', default=defaults_flag_in_config['json-types']) + group_misc.add_argument('--markdown-root', + help='URL for markdown generation', + action='store', + default="") + group_misc.add_argument('--disable-color', help='Disable output colorization', action='store_true', diff --git a/slither/core/declarations/pragma_directive.py b/slither/core/declarations/pragma_directive.py index 1747b9229..1b1cd4756 100644 --- a/slither/core/declarations/pragma_directive.py +++ b/slither/core/declarations/pragma_directive.py @@ -17,5 +17,9 @@ class Pragma(SourceMapping): def version(self): return ''.join(self.directive[1:]) + @property + def name(self): + return self.version + def __str__(self): return 'pragma '+''.join(self.directive) diff --git a/slither/core/slither_core.py b/slither/core/slither_core.py index 6442b2443..ec4572b4d 100644 --- a/slither/core/slither_core.py +++ b/slither/core/slither_core.py @@ -37,6 +37,8 @@ class Slither(Context): self._generate_patches = False + self._markdown_root = "" + ################################################################################### ################################################################################### # region Source code @@ -68,6 +70,10 @@ class Slither(Context): with open(path, encoding='utf8', newline='') as f: self.source_code[path] = f.read() + @property + def markdown_root(self): + return self._markdown_root + # endregion ################################################################################### ################################################################################### diff --git a/slither/core/source_mapping/source_mapping.py b/slither/core/source_mapping/source_mapping.py index 564b2f0e1..839d74a8f 100644 --- a/slither/core/source_mapping/source_mapping.py +++ b/slither/core/source_mapping/source_mapping.py @@ -132,16 +132,22 @@ class SourceMapping(Context): else: self._source_mapping = self._convert_source_mapping(offset, slither) - - @property - def source_mapping_str(self): - + def _get_lines_str(self, line_descr=""): lines = self.source_mapping.get('lines', None) if not lines: lines = '' elif len(lines) == 1: - lines = '#{}'.format(lines[0]) + lines = '#{}{}'.format(line_descr, lines[0]) else: - lines = '#{}-{}'.format(lines[0], lines[-1]) - return '{}{}'.format(self.source_mapping['filename_short'], lines) + lines = '#{}{}-{}{}'.format(line_descr, lines[0], line_descr, lines[-1]) + return lines + + def source_mapping_to_markdown(self, markdown_root): + lines = self._get_lines_str(line_descr="L") + return f'{markdown_root}{self.source_mapping["filename_relative"]}{lines}' + + @property + def source_mapping_str(self): + lines = self._get_lines_str() + return f'{self.source_mapping["filename_short"]}{lines}' diff --git a/slither/core/variables/local_variable.py b/slither/core/variables/local_variable.py index 39e237271..8b353d530 100644 --- a/slither/core/variables/local_variable.py +++ b/slither/core/variables/local_variable.py @@ -52,6 +52,6 @@ class LocalVariable(ChildFunction, Variable): @property def canonical_name(self): - return self.name + return '{}.{}'.format(self.function.canonical_name, self.name) diff --git a/slither/detectors/abstract_detector.py b/slither/detectors/abstract_detector.py index fb9aca05d..06a6ae8fa 100644 --- a/slither/detectors/abstract_detector.py +++ b/slither/detectors/abstract_detector.py @@ -49,6 +49,8 @@ class AbstractDetector(metaclass=abc.ABCMeta): WIKI_EXPLOIT_SCENARIO = '' WIKI_RECOMMENDATION = '' + STANDARD_JSON = True + def __init__(self, slither, logger): self.slither = slither self.contracts = slither.contracts @@ -169,7 +171,10 @@ class AbstractDetector(metaclass=abc.ABCMeta): return classification_colors[self.IMPACT] def generate_json_result(self, info, additional_fields=None): - d = json_utils.generate_json_result(info, additional_fields) + d = json_utils.generate_json_result(info, + additional_fields, + standard_format=self.STANDARD_JSON, + markdown_root=self.slither.markdown_root) d['check'] = self.ARGUMENT d['impact'] = classification_txt[self.IMPACT] diff --git a/slither/detectors/attributes/const_functions.py b/slither/detectors/attributes/const_functions.py index 7d5d492f4..99247b91b 100644 --- a/slither/detectors/attributes/const_functions.py +++ b/slither/detectors/attributes/const_functions.py @@ -57,23 +57,23 @@ All the calls to `get` revert, breaking Bob's smart contract execution.''' if f.view or f.pure: if f.contains_assembly: attr = 'view' if f.view else 'pure' - info = '{} ({}) is declared {} but contains assembly code\n' - info = info.format(f.canonical_name, f.source_mapping_str, attr) + + info = [f, f' is declared {attr} but contains assembly code\n'] json = self.generate_json_result(info, {'contains_assembly': True}) - self.add_function_to_json(f, json) + results.append(json) variables_written = f.all_state_variables_written() if variables_written: attr = 'view' if f.view else 'pure' - info = '{} ({}) is declared {} but changes state variables:\n' - info = info.format(f.canonical_name, f.source_mapping_str, attr) + + info = [f, f' is declared {attr} but changes state variables:\n'] + for variable_written in variables_written: - info += '\t- {}\n'.format(variable_written.canonical_name) + info += ['\t- ', variable_written, '\n'] json = self.generate_json_result(info, {'contains_assembly': False}) - self.add_function_to_json(f, json) - self.add_variables_to_json(variables_written, json) + results.append(json) return results diff --git a/slither/detectors/attributes/constant_pragma.py b/slither/detectors/attributes/constant_pragma.py index 0c2e54bca..d931d6a3d 100644 --- a/slither/detectors/attributes/constant_pragma.py +++ b/slither/detectors/attributes/constant_pragma.py @@ -30,16 +30,14 @@ class ConstantPragma(AbstractDetector): versions = sorted(list(set(versions))) if len(versions) > 1: - info = "Different versions of Solidity is used in {}:\n".format(self.filename) - info += "\t- Version used: {}\n".format([str(v) for v in versions]) + info = [f"Different versions of Solidity is used in {self.filename}:\n"] + info += [f"\t- Version used: {[str(v) for v in versions]}\n"] + for p in pragma: - info += "\t- {} declares {}\n".format(p.source_mapping_str, str(p)) + info += ["\t- ", p, "\n"] json = self.generate_json_result(info) - # Add each pragma to our elements - for p in pragma: - self.add_pragma_to_json(p, json) results.append(json) return results diff --git a/slither/detectors/attributes/incorrect_solc.py b/slither/detectors/attributes/incorrect_solc.py index 17dcd5204..95b967750 100644 --- a/slither/detectors/attributes/incorrect_solc.py +++ b/slither/detectors/attributes/incorrect_solc.py @@ -100,10 +100,10 @@ Use Solidity 0.4.25 or 0.5.3. Consider using the latest version of Solidity for # If we found any disallowed pragmas, we output our findings. if disallowed_pragmas: for (reason, p) in disallowed_pragmas: - info = f"Pragma version \"{p.version}\" {reason} ({p.source_mapping_str})\n" + info = ["Pragma version", p, f" {reason}\n"] json = self.generate_json_result(info) - self.add_pragma_to_json(p, json) + results.append(json) return results diff --git a/slither/detectors/attributes/locked_ether.py b/slither/detectors/attributes/locked_ether.py index 2a4e1d1c3..3de56c00c 100644 --- a/slither/detectors/attributes/locked_ether.py +++ b/slither/detectors/attributes/locked_ether.py @@ -74,18 +74,14 @@ Every ether sent to `Locked` will be lost.''' funcs_payable = [function for function in contract.functions if function.payable] if funcs_payable: if self.do_no_send_ether(contract): - txt = "Contract locking ether found in {}:\n".format(self.filename) - txt += "\tContract {} has payable functions:\n".format(contract.name) + info = [f"Contract locking ether found in {self.filename}:\n"] + info += ["\tContract ", contract, " has payable functions:\n"] for function in funcs_payable: - txt += "\t - {} ({})\n".format(function.name, function.source_mapping_str) - txt += "\tBut does not have a function to withdraw the ether\n" - info = txt.format(self.filename, - contract.name, - [f.name for f in funcs_payable]) + info += [f"\t - ", function, "\n"] + info += "\tBut does not have a function to withdraw the ether\n" json = self.generate_json_result(info) - self.add_contract_to_json(contract, json) - self.add_functions_to_json(funcs_payable, json) + results.append(json) return results diff --git a/slither/detectors/erc/incorrect_erc20_interface.py b/slither/detectors/erc/incorrect_erc20_interface.py index c2c0a4112..a9aa4ad77 100644 --- a/slither/detectors/erc/incorrect_erc20_interface.py +++ b/slither/detectors/erc/incorrect_erc20_interface.py @@ -87,12 +87,9 @@ contract Token{ functions = IncorrectERC20InterfaceDetection.detect_incorrect_erc20_interface(c) if functions: for function in functions: - info = "{} ({}) has incorrect ERC20 function interface: {} ({})\n".format(c.name, - c.source_mapping_str, - function.full_name, - function.source_mapping_str) - json = self.generate_json_result(info) - self.add_function_to_json(function, json) + info = [c, " has incorrect ERC20 function interface:", function, "\n"] + json = self.generate_json_result(info) + results.append(json) return results diff --git a/slither/detectors/erc/incorrect_erc721_interface.py b/slither/detectors/erc/incorrect_erc721_interface.py index bff88413c..bce1695b1 100644 --- a/slither/detectors/erc/incorrect_erc721_interface.py +++ b/slither/detectors/erc/incorrect_erc721_interface.py @@ -86,12 +86,9 @@ contract Token{ functions = IncorrectERC721InterfaceDetection.detect_incorrect_erc721_interface(c) if functions: for function in functions: - info = "{} ({}) has incorrect ERC721 function interface: {} ({})\n".format(c.name, - c.source_mapping_str, - function.full_name, - function.source_mapping_str) + info = [c, " has incorrect ERC721 function interface:", function, "\n"] json = self.generate_json_result(info) - self.add_function_to_json(function, json) + results.append(json) return results diff --git a/slither/detectors/erc/unindexed_event_parameters.py b/slither/detectors/erc/unindexed_event_parameters.py index 55ab15e25..1e382da59 100644 --- a/slither/detectors/erc/unindexed_event_parameters.py +++ b/slither/detectors/erc/unindexed_event_parameters.py @@ -32,6 +32,8 @@ In this case, Transfer and Approval events should have the 'indexed' keyword on WIKI_RECOMMENDATION = 'Add the `indexed` keyword to event parameters which should include it, according to the ERC20 specification.' + STANDARD_JSON = False + @staticmethod def detect_erc20_unindexed_event_params(contract): """ @@ -71,10 +73,11 @@ In this case, Transfer and Approval events should have the 'indexed' keyword on # Add each problematic event definition to our result list for (event, parameter) in unindexed_params: - info = "ERC20 event {}.{} ({}) does not index parameter '{}'\n".format(c.name, event.name, event.source_mapping_str, parameter.name) + info = ["ERC20 event ", event, f"does not index parameter {parameter}\n"] # Add the events to the JSON (note: we do not add the params/vars as they have no source mapping). json = self.generate_json_result(info) + self.add_event_to_json(event, json, { "parameter_name": parameter.name }) diff --git a/slither/detectors/examples/backdoor.py b/slither/detectors/examples/backdoor.py index bbc60a8b3..d9f00979e 100644 --- a/slither/detectors/examples/backdoor.py +++ b/slither/detectors/examples/backdoor.py @@ -26,11 +26,11 @@ class Backdoor(AbstractDetector): for f in contract.functions: if 'backdoor' in f.name: # Info to be printed - info = 'Backdoor function found in {}.{} ({})\n' - info = info.format(contract.name, f.name, f.source_mapping_str) + info = ['Backdoor function found in ', f, '\n'] + # Add the result in result json = self.generate_json_result(info) - self.add_function_to_json(f, json) + results.append(json) return results diff --git a/slither/detectors/functions/arbitrary_send.py b/slither/detectors/functions/arbitrary_send.py index d28cd1258..4a14873a9 100644 --- a/slither/detectors/functions/arbitrary_send.py +++ b/slither/detectors/functions/arbitrary_send.py @@ -109,16 +109,13 @@ Bob calls `setDestination` and `withdraw`. As a result he withdraws the contract arbitrary_send = self.detect_arbitrary_send(c) for (func, nodes) in arbitrary_send: - info = "{} ({}) sends eth to arbitrary user\n" - info = info.format(func.canonical_name, - func.source_mapping_str) - info += '\tDangerous calls:\n' + info = [func, " sends eth to arbitrary user\n"] + info += ['\tDangerous calls:\n'] for node in nodes: - info += '\t- {} ({})\n'.format(node.expression, node.source_mapping_str) + info += ['\t- ', node, '\n'] json = self.generate_json_result(info) - self.add_function_to_json(func, json) - self.add_nodes_to_json(nodes, json) + results.append(json) return results diff --git a/slither/detectors/functions/external_function.py b/slither/detectors/functions/external_function.py index 233f24f48..7b48be5ba 100644 --- a/slither/detectors/functions/external_function.py +++ b/slither/detectors/functions/external_function.py @@ -182,16 +182,13 @@ class ExternalFunction(AbstractDetector): function_definition = all_function_definitions[0] all_function_definitions = all_function_definitions[1:] - txt = f"{function_definition.full_name} should be declared external:\n" - txt += f"\t- {function_definition.canonical_name} ({function_definition.source_mapping_str})\n" + info = [f"{function_definition.full_name} should be declared external:\n"] + info += [f"\t- ", function_definition, "\n"] for other_function_definition in all_function_definitions: - txt += f"\t- {other_function_definition.canonical_name}" - txt += f" ({other_function_definition.source_mapping_str})\n" + info += [f"\t- ", other_function_definition, "\n"] + + json = self.generate_json_result(info) - json = self.generate_json_result(txt) - self.add_function_to_json(function_definition, json) - for other_function_definition in all_function_definitions: - self.add_function_to_json(other_function_definition, json) results.append(json) return results diff --git a/slither/detectors/functions/suicidal.py b/slither/detectors/functions/suicidal.py index 5f5d0f73b..2dc28cf13 100644 --- a/slither/detectors/functions/suicidal.py +++ b/slither/detectors/functions/suicidal.py @@ -73,12 +73,10 @@ Bob calls `kill` and destructs the contract.''' functions = self.detect_suicidal(c) for func in functions: - txt = "{} ({}) allows anyone to destruct the contract\n" - info = txt.format(func.canonical_name, - func.source_mapping_str) + info = [func, " allows anyone to destruct the contract\n"] json = self.generate_json_result(info) - self.add_function_to_json(func, json) + results.append(json) return results diff --git a/slither/detectors/naming_convention/naming_convention.py b/slither/detectors/naming_convention/naming_convention.py index a6499ca99..93825e419 100644 --- a/slither/detectors/naming_convention/naming_convention.py +++ b/slither/detectors/naming_convention/naming_convention.py @@ -30,6 +30,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 WIKI_RECOMMENDATION = 'Follow the Solidity [naming convention](https://solidity.readthedocs.io/en/v0.4.25/style-guide.html#naming-conventions).' + STANDARD_JSON = False @staticmethod def is_cap_words(name): @@ -59,8 +60,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 for contract in self.contracts: if not self.is_cap_words(contract.name): - info = "Contract '{}' ({}) is not in CapWords\n".format(contract.name, - contract.source_mapping_str) + info = ["Contract ", contract, " is not in CapWords\n"] json = self.generate_json_result(info) self.add_contract_to_json(contract, json, { @@ -71,8 +71,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 for struct in contract.structures_declared: if not self.is_cap_words(struct.name): - info = "Struct '{}' ({}) is not in CapWords\n" - info = info.format(struct.canonical_name, struct.source_mapping_str) + info = ["Struct ", struct, " is not in CapWords\n"] json = self.generate_json_result(info) self.add_struct_to_json(struct, json, { @@ -83,8 +82,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 for event in contract.events_declared: if not self.is_cap_words(event.name): - info = "Event '{}' ({}) is not in CapWords\n" - info = info.format(event.canonical_name, event.source_mapping_str) + info = ["Event ", event, " is not in CapWords\n"] json = self.generate_json_result(info) self.add_event_to_json(event, json, { @@ -101,8 +99,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 continue if func.name.startswith("echidna_") or func.name.startswith("crytic_"): continue - info = "Function '{}' ({}) is not in mixedCase\n" - info = info.format(func.canonical_name, func.source_mapping_str) + info = ["Function ", func, " is not in mixedCase\n"] json = self.generate_json_result(info) self.add_function_to_json(func, json, { @@ -120,10 +117,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 else: correct_naming = self.is_mixed_case_with_underscore(argument.name) if not correct_naming: - info = "Parameter '{}' of {} ({}) is not in mixedCase\n" - info = info.format(argument.name, - argument.canonical_name, - argument.source_mapping_str) + info = ["Parameter ", argument, " is not in mixedCase\n"] json = self.generate_json_result(info) self.add_variable_to_json(argument, json, { @@ -135,8 +129,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 for var in contract.state_variables_declared: if self.should_avoid_name(var.name): if not self.is_upper_case_with_underscores(var.name): - info = "Variable '{}' ({}) used l, O, I, which should not be used\n" - info = info.format(var.canonical_name, var.source_mapping_str) + info = ["Variable ", var," used l, O, I, which should not be used\n"] json = self.generate_json_result(info) self.add_variable_to_json(var, json, { @@ -151,8 +144,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 continue if not self.is_upper_case_with_underscores(var.name): - info = "Constant '{}' ({}) is not in UPPER_CASE_WITH_UNDERSCORES\n" - info = info.format(var.canonical_name, var.source_mapping_str) + info = ["Constant ", var," is not in UPPER_CASE_WITH_UNDERSCORES\n"] json = self.generate_json_result(info) self.add_variable_to_json(var, json, { @@ -167,8 +159,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 else: correct_naming = self.is_mixed_case(var.name) if not correct_naming: - info = "Variable '{}' ({}) is not in mixedCase\n" - info = info.format(var.canonical_name, var.source_mapping_str) + info = ["Variable ", var, " is not in mixedCase\n"] json = self.generate_json_result(info) self.add_variable_to_json(var, json, { @@ -179,8 +170,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 for enum in contract.enums_declared: if not self.is_cap_words(enum.name): - info = "Enum '{}' ({}) is not in CapWords\n" - info = info.format(enum.canonical_name, enum.source_mapping_str) + info = ["Enum ", enum, " is not in CapWords\n"] json = self.generate_json_result(info) self.add_enum_to_json(enum, json, { @@ -191,9 +181,7 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 for modifier in contract.modifiers_declared: if not self.is_mixed_case(modifier.name): - info = "Modifier '{}' ({}) is not in mixedCase\n" - info = info.format(modifier.canonical_name, - modifier.source_mapping_str) + info = ["Modifier ", modifier, " is not in mixedCase\n"] json = self.generate_json_result(info) self.add_function_to_json(modifier, json, { diff --git a/slither/detectors/operations/block_timestamp.py b/slither/detectors/operations/block_timestamp.py index 81c115341..23ad8e178 100644 --- a/slither/detectors/operations/block_timestamp.py +++ b/slither/detectors/operations/block_timestamp.py @@ -69,16 +69,14 @@ class Timestamp(AbstractDetector): dangerous_timestamp = self.detect_dangerous_timestamp(c) for (func, nodes) in dangerous_timestamp: - info = "{} ({}) uses timestamp for comparisons\n" - info = info.format(func.canonical_name, - func.source_mapping_str) - info += '\tDangerous comparisons:\n' + info = [func, " uses timestamp for comparisons\n"] + + info += ['\tDangerous comparisons:\n'] for node in nodes: - info += '\t- {} ({})\n'.format(node.expression, node.source_mapping_str) + info += ['\t- ', node, '\n'] json = self.generate_json_result(info) - self.add_function_to_json(func, json) - self.add_nodes_to_json(nodes, json) + results.append(json) return results diff --git a/slither/detectors/operations/low_level_calls.py b/slither/detectors/operations/low_level_calls.py index 4e36448a4..c22ff8139 100644 --- a/slither/detectors/operations/low_level_calls.py +++ b/slither/detectors/operations/low_level_calls.py @@ -48,14 +48,13 @@ class LowLevelCalls(AbstractDetector): for c in self.contracts: values = self.detect_low_level_calls(c) for func, nodes in values: - info = "Low level call in {} ({}):\n" - info = info.format(func.canonical_name, func.source_mapping_str) + info = ["Low level call in ", func,":\n"] + for node in nodes: - info += "\t-{} {}\n".format(str(node.expression), node.source_mapping_str) + info += ['\t- ', node, '\n'] json = self.generate_json_result(info) - self.add_function_to_json(func, json) - self.add_nodes_to_json(nodes, json) + results.append(json) return results diff --git a/slither/detectors/operations/unused_return_values.py b/slither/detectors/operations/unused_return_values.py index 77a0e5b86..a8233a6d8 100644 --- a/slither/detectors/operations/unused_return_values.py +++ b/slither/detectors/operations/unused_return_values.py @@ -74,16 +74,10 @@ contract MyConc{ if unused_return: for node in unused_return: - info = "{} ({}) ignores return value by {} \"{}\" ({})\n" - info = info.format(f.canonical_name, - f.source_mapping_str, - self._txt_description, - node.expression, - node.source_mapping_str) + info = [f, f" ignores return value by ", node, "\n"] json = self.generate_json_result(info) - self.add_node_to_json(node, json) - self.add_function_to_json(f, json) + results.append(json) return results diff --git a/slither/detectors/operations/void_constructor.py b/slither/detectors/operations/void_constructor.py index 6be913ffa..181a5ae50 100644 --- a/slither/detectors/operations/void_constructor.py +++ b/slither/detectors/operations/void_constructor.py @@ -36,12 +36,10 @@ By reading B's constructor definition, the reader might assume that `A()` initia for constructor_call in cst.explicit_base_constructor_calls_statements: for node in constructor_call.nodes: if any(isinstance(ir, Nop) for ir in node.irs): - info = "Void constructor called in {} ({}):\n" - info = info.format(cst.canonical_name, cst.source_mapping_str) - info += "\t-{} {}\n".format(str(node.expression), node.source_mapping_str) + info = ["Void constructor called in ", cst, ":\n"] + info += ["\t- ", node, "\n"] json = self.generate_json_result(info) - self.add_function_to_json(cst, json) - self.add_nodes_to_json([node], json) + results.append(json) return results diff --git a/slither/detectors/reentrancy/reentrancy_benign.py b/slither/detectors/reentrancy/reentrancy_benign.py index 2d16d757f..79dfec78f 100644 --- a/slither/detectors/reentrancy/reentrancy_benign.py +++ b/slither/detectors/reentrancy/reentrancy_benign.py @@ -36,6 +36,8 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr WIKI_RECOMMENDATION = 'Apply the [check-effects-interactions pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy).' + STANDARD_JSON = False + def find_reentrancies(self): result = {} for contract in self.contracts: @@ -78,18 +80,19 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr for (func, calls, send_eth), varsWritten in result_sorted: calls = sorted(list(set(calls)), key=lambda x: x.node_id) send_eth = sorted(list(set(send_eth)), key=lambda x: x.node_id) - info = 'Reentrancy in {} ({}):\n' - info = info.format(func.canonical_name, func.source_mapping_str) - info += '\tExternal calls:\n' + info = ['Reentrancy in ', func, ':\n'] + + info += ['\tExternal calls:\n'] for call_info in calls: - info += '\t- {} ({})\n'.format(call_info.expression, call_info.source_mapping_str) + info += ['\t- ' , call_info, '\n'] if calls != send_eth and send_eth: - info += '\tExternal calls sending eth:\n' + info += ['\tExternal calls sending eth:\n'] for call_info in send_eth: - info += '\t- {} ({})\n'.format(call_info.expression, call_info.source_mapping_str) - info += '\tState variables written after the call(s):\n' + info += ['\t- ', call_info, '\n'] + info += ['\tState variables written after the call(s):\n'] for (v, node) in sorted(varsWritten, key=lambda x: (x[0].name, x[1].node_id)): - info += '\t- {} ({})\n'.format(v, node.source_mapping_str) + info += ['\t- ', v, ' in ', node, '\n'] + # Create our JSON result json = self.generate_json_result(info) diff --git a/slither/detectors/reentrancy/reentrancy_eth.py b/slither/detectors/reentrancy/reentrancy_eth.py index 4439887aa..b0d501ec1 100644 --- a/slither/detectors/reentrancy/reentrancy_eth.py +++ b/slither/detectors/reentrancy/reentrancy_eth.py @@ -37,6 +37,7 @@ Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw m WIKI_RECOMMENDATION = 'Apply the [check-effects-interactions pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy).' + STANDARD_JSON = False def find_reentrancies(self): result = {} @@ -81,18 +82,17 @@ Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw m calls = sorted(list(set(calls)), key=lambda x: x.node_id) send_eth = sorted(list(set(send_eth)), key=lambda x: x.node_id) - info = 'Reentrancy in {} ({}):\n' - info = info.format(func.canonical_name, func.source_mapping_str) - info += '\tExternal calls:\n' + info = ['Reentrancy in ', func, ':\n'] + info += ['\tExternal calls:\n'] for call_info in calls: - info += '\t- {} ({})\n'.format(call_info.expression, call_info.source_mapping_str) - if calls != send_eth: - info += '\tExternal calls sending eth:\n' + info += ['\t- ' , call_info, '\n'] + if calls != send_eth and send_eth: + info += ['\tExternal calls sending eth:\n'] for call_info in send_eth: - info += '\t- {} ({})\n'.format(call_info.expression, call_info.source_mapping_str) - info += '\tState variables written after the call(s):\n' + info += ['\t- ', call_info, '\n'] + info += ['\tState variables written after the call(s):\n'] for (v, node) in sorted(varsWritten, key=lambda x: (x[0].name, x[1].node_id)): - info += '\t- {} ({})\n'.format(v, node.source_mapping_str) + info += ['\t- ', v, ' in ', node, '\n'] # Create our JSON result json = self.generate_json_result(info) diff --git a/slither/detectors/reentrancy/reentrancy_read_before_write.py b/slither/detectors/reentrancy/reentrancy_read_before_write.py index 0432459cc..6389847fc 100644 --- a/slither/detectors/reentrancy/reentrancy_read_before_write.py +++ b/slither/detectors/reentrancy/reentrancy_read_before_write.py @@ -36,6 +36,8 @@ Do not report reentrancies that involve ethers (see `reentrancy-eth`)''' ''' WIKI_RECOMMENDATION = 'Apply the [check-effects-interactions pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy).' + STANDARD_JSON = False + def find_reentrancies(self): result = {} for contract in self.contracts: @@ -75,14 +77,15 @@ Do not report reentrancies that involve ethers (see `reentrancy-eth`)''' result_sorted = sorted(list(reentrancies.items()), key=lambda x:x[0][0].name) for (func, calls), varsWritten in result_sorted: calls = sorted(list(set(calls)), key=lambda x: x.node_id) - info = 'Reentrancy in {} ({}):\n' - info = info.format(func.canonical_name, func.source_mapping_str) - info += '\tExternal calls:\n' + + info = ['Reentrancy in ', func, ':\n'] + + info += ['\tExternal calls:\n'] for call_info in calls: - info += '\t- {} ({})\n'.format(call_info.expression, call_info.source_mapping_str) + info += ['\t- ', call_info, '\n'] info += '\tState variables written after the call(s):\n' for (v, node) in sorted(varsWritten, key=lambda x: (x[0].name, x[1].node_id)): - info += '\t- {} ({})\n'.format(v, node.source_mapping_str) + info += ['\t- ', v, ' in ', node, '\n'] # Create our JSON result json = self.generate_json_result(info) diff --git a/slither/detectors/shadowing/abstract.py b/slither/detectors/shadowing/abstract.py index 15bb7e2c1..f2e7c7119 100644 --- a/slither/detectors/shadowing/abstract.py +++ b/slither/detectors/shadowing/abstract.py @@ -65,14 +65,12 @@ contract DerivedContract is BaseContract{ for all_variables in shadowing: shadow = all_variables[0] variables = all_variables[1:] - info = '{} ({}) shadows:\n'.format(shadow.canonical_name, - shadow.source_mapping_str) + info = [shadow, ' shadows:\n'] for var in variables: - info += "\t- {} ({})\n".format(var.canonical_name, - var.source_mapping_str) + info += ["\t- ", var, "\n"] json = self.generate_json_result(info) - self.add_variables_to_json(all_variables, json) + results.append(json) return results diff --git a/slither/detectors/shadowing/builtin_symbols.py b/slither/detectors/shadowing/builtin_symbols.py index 2cd4cff09..c0bf4e8b0 100644 --- a/slither/detectors/shadowing/builtin_symbols.py +++ b/slither/detectors/shadowing/builtin_symbols.py @@ -77,7 +77,7 @@ contract Bug { results = [] for local in function_or_modifier.variables: if self.is_builtin_symbol(local.name): - results.append((self.SHADOWING_LOCAL_VARIABLE, local, function_or_modifier)) + results.append((self.SHADOWING_LOCAL_VARIABLE, local)) return results def detect_builtin_shadowing_definitions(self, contract): @@ -92,18 +92,18 @@ contract Bug { # Loop through all functions, modifiers, variables (state and local) to detect any built-in symbol keywords. for function in contract.functions_declared: if self.is_builtin_symbol(function.name): - result.append((self.SHADOWING_FUNCTION, function, None)) + result.append((self.SHADOWING_FUNCTION, function)) result += self.detect_builtin_shadowing_locals(function) for modifier in contract.modifiers_declared: if self.is_builtin_symbol(modifier.name): - result.append((self.SHADOWING_MODIFIER, modifier, None)) + result.append((self.SHADOWING_MODIFIER, modifier)) result += self.detect_builtin_shadowing_locals(modifier) for variable in contract.state_variables_declared: if self.is_builtin_symbol(variable.name): - result.append((self.SHADOWING_STATE_VARIABLE, variable, None)) + result.append((self.SHADOWING_STATE_VARIABLE, variable)) for event in contract.events_declared: if self.is_builtin_symbol(event.name): - result.append((self.SHADOWING_EVENT, event, None)) + result.append((self.SHADOWING_EVENT, event)) return result @@ -124,27 +124,10 @@ contract Bug { # Obtain components shadow_type = shadow[0] shadow_object = shadow[1] - local_variable_parent = shadow[2] - # Build the path for our info string - local_variable_path = contract.name + "." - if local_variable_parent is not None: - local_variable_path += local_variable_parent.name + "." - local_variable_path += shadow_object.name + info = [shadow_object, f' ({shadow_type}) shadows built-in symbol"\n'] - info = '{} ({} @ {}) shadows built-in symbol \"{}"\n'.format(local_variable_path, - shadow_type, - shadow_object.source_mapping_str, - shadow_object.name) - - # Generate relevant JSON data for this shadowing definition. json = self.generate_json_result(info) - if shadow_type in [self.SHADOWING_FUNCTION, self.SHADOWING_MODIFIER]: - self.add_function_to_json(shadow_object, json) - elif shadow_type == self.SHADOWING_EVENT: - self.add_event_to_json(shadow_object, json) - elif shadow_type in [self.SHADOWING_STATE_VARIABLE, self.SHADOWING_LOCAL_VARIABLE]: - self.add_variable_to_json(shadow_object, json) results.append(json) return results diff --git a/slither/detectors/shadowing/local.py b/slither/detectors/shadowing/local.py index 66f769882..0da45cf99 100644 --- a/slither/detectors/shadowing/local.py +++ b/slither/detectors/shadowing/local.py @@ -68,23 +68,23 @@ contract Bug { # Check functions for scope_function in scope_contract.functions_declared: if variable.name == scope_function.name: - overshadowed.append((self.OVERSHADOWED_FUNCTION, scope_contract.name, scope_function)) + overshadowed.append((self.OVERSHADOWED_FUNCTION, scope_function)) # Check modifiers for scope_modifier in scope_contract.modifiers_declared: if variable.name == scope_modifier.name: - overshadowed.append((self.OVERSHADOWED_MODIFIER, scope_contract.name, scope_modifier)) + overshadowed.append((self.OVERSHADOWED_MODIFIER, scope_modifier)) # Check events for scope_event in scope_contract.events_declared: if variable.name == scope_event.name: - overshadowed.append((self.OVERSHADOWED_EVENT, scope_contract.name, scope_event)) + overshadowed.append((self.OVERSHADOWED_EVENT, scope_event)) # Check state variables for scope_state_variable in scope_contract.state_variables_declared: if variable.name == scope_state_variable.name: - overshadowed.append((self.OVERSHADOWED_STATE_VARIABLE, scope_contract.name, scope_state_variable)) + overshadowed.append((self.OVERSHADOWED_STATE_VARIABLE, scope_state_variable)) # If we have found any overshadowed objects, we'll want to add it to our result list. if overshadowed: - result.append((contract.name, function.name, variable, overshadowed)) + result.append((variable, overshadowed)) return result @@ -102,29 +102,15 @@ contract Bug { shadows = self.detect_shadowing_definitions(contract) if shadows: for shadow in shadows: - local_parent_name = shadow[1] - local_variable = shadow[2] - overshadowed = shadow[3] - info = '{}.{}.{} (local variable @ {}) shadows:\n'.format(contract.name, - local_parent_name, - local_variable.name, - local_variable.source_mapping_str) + local_variable = shadow[0] + overshadowed = shadow[1] + info = [local_variable, ' shadows:\n'] for overshadowed_entry in overshadowed: - info += "\t- {}.{} ({} @ {})\n".format(overshadowed_entry[1], - overshadowed_entry[2], - overshadowed_entry[0], - overshadowed_entry[2].source_mapping_str) + info += ["\t- ", overshadowed_entry[1], f" ({overshadowed_entry[0]})\n"] # Generate relevant JSON data for this shadowing definition. json = self.generate_json_result(info) - self.add_variable_to_json(local_variable, json) - for overshadowed_entry in overshadowed: - if overshadowed_entry[0] in [self.OVERSHADOWED_FUNCTION, self.OVERSHADOWED_MODIFIER]: - self.add_function_to_json(overshadowed_entry[2], json) - elif overshadowed_entry[0] == self.OVERSHADOWED_EVENT: - self.add_event_to_json(overshadowed_entry[2], json) - elif overshadowed_entry[0] == self.OVERSHADOWED_STATE_VARIABLE: - self.add_variable_to_json(overshadowed_entry[2], json) + results.append(json) return results diff --git a/slither/detectors/shadowing/state.py b/slither/detectors/shadowing/state.py index 41da711f3..b5df61151 100644 --- a/slither/detectors/shadowing/state.py +++ b/slither/detectors/shadowing/state.py @@ -76,14 +76,12 @@ contract DerivedContract is BaseContract{ for all_variables in shadowing: shadow = all_variables[0] variables = all_variables[1:] - info = '{} ({}) shadows:\n'.format(shadow.canonical_name, - shadow.source_mapping_str) + info = [shadow, ' shadows:\n'] for var in variables: - info += "\t- {} ({})\n".format(var.canonical_name, - var.source_mapping_str) + info += ["\t- ", var, "\n"] json = self.generate_json_result(info) - self.add_variables_to_json(all_variables, json) + results.append(json) diff --git a/slither/detectors/source/rtlo.py b/slither/detectors/source/rtlo.py index 7c4b78305..135b5aa6a 100644 --- a/slither/detectors/source/rtlo.py +++ b/slither/detectors/source/rtlo.py @@ -46,6 +46,7 @@ contract Token WIKI_RECOMMENDATION = 'Special control characters must not be allowed.' RTLO_CHARACTER_ENCODED = "\u202e".encode('utf-8') + STANDARD_JSON = False def _detect(self): results = [] diff --git a/slither/detectors/statements/assembly.py b/slither/detectors/statements/assembly.py index 936794366..af65f2331 100644 --- a/slither/detectors/statements/assembly.py +++ b/slither/detectors/statements/assembly.py @@ -51,15 +51,12 @@ class Assembly(AbstractDetector): for c in self.contracts: values = self.detect_assembly(c) for func, nodes in values: - info = "{} uses assembly ({})\n" - info = info.format(func.canonical_name, func.source_mapping_str) + info = [func, " uses assembly\n"] for node in nodes: - info += "\t- {}\n".format(node.source_mapping_str) + info += ["\t- ", node, "\n"] json = self.generate_json_result(info) - self.add_function_to_json(func, json) - self.add_nodes_to_json(nodes, json) results.append(json) return results diff --git a/slither/detectors/statements/calls_in_loop.py b/slither/detectors/statements/calls_in_loop.py index 092003c8f..b2dfd5c11 100644 --- a/slither/detectors/statements/calls_in_loop.py +++ b/slither/detectors/statements/calls_in_loop.py @@ -87,11 +87,8 @@ If one of the destinations has a fallback function which reverts, `bad` will alw for node in values: func = node.function - info = "{} has external calls inside a loop: \"{}\" ({})\n" - info = info.format(func.canonical_name, node.expression, node.source_mapping_str) - + info = [func, " has external calls inside a loop: ", node, "\n"] json = self.generate_json_result(info) - self.add_node_to_json(node, json) results.append(json) return results diff --git a/slither/detectors/statements/controlled_delegatecall.py b/slither/detectors/statements/controlled_delegatecall.py index 455be0594..0dcff87bc 100644 --- a/slither/detectors/statements/controlled_delegatecall.py +++ b/slither/detectors/statements/controlled_delegatecall.py @@ -47,14 +47,11 @@ Bob calls `delegate` and delegates the execution to its malicious contract. As a continue nodes = self.controlled_delegatecall(f) if nodes: - func_info = '{}.{} ({}) uses delegatecall to a input-controlled function id\n' - func_info = func_info.format(contract.name, f.name, f.source_mapping_str) - for node in nodes: - node_info = func_info + '\t- {} ({})\n'.format(node.expression, node.source_mapping_str) + func_info = [f, ' uses delegatecall to a input-controlled function id\n'] + for node in nodes: + node_info = func_info + ['\t- ', node,'\n'] json = self.generate_json_result(node_info) - self.add_node_to_json(node, json) - self.add_function_to_json(f, json) results.append(json) return results diff --git a/slither/detectors/statements/deprecated_calls.py b/slither/detectors/statements/deprecated_calls.py index c18843125..de8b8e860 100644 --- a/slither/detectors/statements/deprecated_calls.py +++ b/slither/detectors/statements/deprecated_calls.py @@ -152,20 +152,12 @@ contract ContractWithDeprecatedReferences { for deprecated_reference in deprecated_references: source_object = deprecated_reference[0] deprecated_entries = deprecated_reference[1] - info = 'Deprecated standard detected @ {}:\n'.format(source_object.source_mapping_str) + info = ['Deprecated standard detected ', source_object, ':\n'] for (dep_id, original_desc, recommended_disc) in deprecated_entries: - info += "\t- Usage of \"{}\" should be replaced with \"{}\"\n".format(original_desc, - recommended_disc) + info += [f"\t- Usage of \"{original_desc}\" should be replaced with \"{recommended_disc}\"\n"] - - # Generate relevant JSON data for this deprecated standard. json = self.generate_json_result(info) - if isinstance(source_object, StateVariableSolc) or isinstance(source_object, StateVariable): - self.add_variable_to_json(source_object, json) - else: - self.add_nodes_to_json([source_object], json) - results.append(json) return results diff --git a/slither/detectors/statements/incorrect_strict_equality.py b/slither/detectors/statements/incorrect_strict_equality.py index 0ef6a5dea..01faf4d62 100644 --- a/slither/detectors/statements/incorrect_strict_equality.py +++ b/slither/detectors/statements/incorrect_strict_equality.py @@ -111,19 +111,16 @@ contract Crowdsale{ ret = sorted(list(ret.items()), key=lambda x:x[0].name) for f, nodes in ret: - func_info = "{} ({}) uses a dangerous strict equality:\n".format(f.canonical_name, - f.source_mapping_str) + func_info = [f, " uses a dangerous strict equality:\n"] # sort the nodes to get deterministic results nodes.sort(key=lambda x: x.node_id) # Output each node with the function info header as a separate result. for node in nodes: - node_info = func_info + f"\t- {str(node.expression)}\n" + node_info = func_info + [f"\t- ", node, "\n"] json = self.generate_json_result(node_info) - self.add_node_to_json(node, json) - self.add_function_to_json(f, json) results.append(json) return results diff --git a/slither/detectors/statements/too_many_digits.py b/slither/detectors/statements/too_many_digits.py index df9e21921..0e6591546 100644 --- a/slither/detectors/statements/too_many_digits.py +++ b/slither/detectors/statements/too_many_digits.py @@ -64,15 +64,12 @@ Use: # iterate over all the nodes ret = self._detect_too_many_digits(f) if ret: - func_info = '{}.{} ({}) uses literals with too many digits:'.format(f.contract.name, - f.name, - f.source_mapping_str) + func_info = [f, ' uses literals with too many digits:'] for node in ret: - node_info = func_info + '\n\t- {}\n'.format(node.expression) + node_info = func_info + ['\n\t- ', node,'\n'] # Add the result in result json = self.generate_json_result(node_info) - self.add_node_to_json(node, json) results.append(json) return results diff --git a/slither/detectors/statements/tx_origin.py b/slither/detectors/statements/tx_origin.py index 3b4e662a7..8f2b9968b 100644 --- a/slither/detectors/statements/tx_origin.py +++ b/slither/detectors/statements/tx_origin.py @@ -68,12 +68,9 @@ Bob is the owner of `TxOrigin`. Bob calls Eve's contract. Eve's contract calls ` for func, nodes in values: for node in nodes: - info = "{} uses tx.origin for authorization: \"{}\" ({})\n".format(func.canonical_name, - node.expression, - node.source_mapping_str) - + info = [func, " uses tx.origin for authorization: ", node, "\n"] json = self.generate_json_result(info) - self.add_node_to_json(node, json) + results.append(json) return results diff --git a/slither/detectors/variables/possible_const_state_variables.py b/slither/detectors/variables/possible_const_state_variables.py index e6c676c16..eaed2dac8 100644 --- a/slither/detectors/variables/possible_const_state_variables.py +++ b/slither/detectors/variables/possible_const_state_variables.py @@ -88,11 +88,8 @@ class ConstCandidateStateVars(AbstractDetector): # Create a result for each finding for v in constable_variables: - info = "{} should be constant ({})\n".format(v.canonical_name, - v.source_mapping_str) + info = [v, " should be constant\n"] json = self.generate_json_result(info) - self.add_variable_to_json(v, json) - results.append(json) return results diff --git a/slither/detectors/variables/uninitialized_local_variables.py b/slither/detectors/variables/uninitialized_local_variables.py index c767e7b2c..cc0ff0968 100644 --- a/slither/detectors/variables/uninitialized_local_variables.py +++ b/slither/detectors/variables/uninitialized_local_variables.py @@ -97,17 +97,9 @@ Bob calls `transfer`. As a result, the ethers are sent to the address 0x0 and ar self._detect_uninitialized(function, function.entry_point, []) all_results = list(set(self.results)) for(function, uninitialized_local_variable) in all_results: - var_name = uninitialized_local_variable.name - - info = "{} in {} ({}) is a local variable never initialiazed\n" - info = info.format(var_name, - function.canonical_name, - uninitialized_local_variable.source_mapping_str) - + info = [uninitialized_local_variable, " is a local variable never initialiazed\n"] json = self.generate_json_result(info) - self.add_variable_to_json(uninitialized_local_variable, json) - self.add_function_to_json(function, json) results.append(json) return results diff --git a/slither/detectors/variables/uninitialized_state_variables.py b/slither/detectors/variables/uninitialized_state_variables.py index 86a9e09d3..8eaa784e6 100644 --- a/slither/detectors/variables/uninitialized_state_variables.py +++ b/slither/detectors/variables/uninitialized_state_variables.py @@ -87,18 +87,13 @@ Initialize all the variables. If a variable is meant to be initialized to zero, for c in self.slither.contracts_derived: ret = self.detect_uninitialized(c) for variable, functions in ret: - info = "{} ({}) is never initialized. It is used in:\n" - info = info.format(variable.canonical_name, - variable.source_mapping_str) - for f in functions: - info += "\t- {} ({})\n".format(f.name, f.source_mapping_str) - source = [variable.source_mapping] - source += [f.source_mapping for f in functions] + info = [variable, " is never initialized. It is used in:\n"] + + for f in functions: + info += ["\t- ", f, "\n"] json = self.generate_json_result(info) - self.add_variable_to_json(variable, json) - self.add_functions_to_json(functions, json) results.append(json) return results diff --git a/slither/detectors/variables/uninitialized_storage_variables.py b/slither/detectors/variables/uninitialized_storage_variables.py index 78f7b8343..f77f95d2a 100644 --- a/slither/detectors/variables/uninitialized_storage_variables.py +++ b/slither/detectors/variables/uninitialized_storage_variables.py @@ -101,14 +101,8 @@ Bob calls `func`. As a result, `owner` is override to 0. self._detect_uninitialized(function, function.entry_point, []) for(function, uninitialized_storage_variable) in self.results: - var_name = uninitialized_storage_variable.name - - info = "{} in {} ({}) is a storage variable never initialiazed\n" - info = info.format(var_name, function.canonical_name, uninitialized_storage_variable.source_mapping_str) - + info = [uninitialized_storage_variable, " is a storage variable never initialiazed\n"] json = self.generate_json_result(info) - self.add_variable_to_json(uninitialized_storage_variable, json) - self.add_function_to_json(function, json) results.append(json) return results diff --git a/slither/detectors/variables/unused_state_variables.py b/slither/detectors/variables/unused_state_variables.py index 35fa66999..def3d2804 100644 --- a/slither/detectors/variables/unused_state_variables.py +++ b/slither/detectors/variables/unused_state_variables.py @@ -60,13 +60,8 @@ class UnusedStateVars(AbstractDetector): unusedVars = self.detect_unused(c) if unusedVars: for var in unusedVars: - info = "{} ({}) is never used in {}\n".format(var.canonical_name, - var.source_mapping_str, - c.name) - + info = [var, " is never used in ", c, "\n"] json = self.generate_json_result(info) - self.add_variable_to_json(var, json) - self.add_contract_to_json(c, json) results.append(json) return results diff --git a/slither/slither.py b/slither/slither.py index af07cfd93..1dbf9e7ce 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -68,6 +68,8 @@ class Slither(SlitherSolc): if kwargs.get('generate_patches', False): self.generate_patches = True + self._markdown_root = kwargs.get('markdown_root', "") + self._detectors = [] self._printers = [] diff --git a/slither/utils/json_utils.py b/slither/utils/json_utils.py index 8aecc8230..3ae2b8862 100644 --- a/slither/utils/json_utils.py +++ b/slither/utils/json_utils.py @@ -3,7 +3,11 @@ import json import logging from collections import OrderedDict +from slither.core.cfg.node import Node +from slither.core.declarations import Contract, Function, Enum, Event, Structure, Pragma from slither.core.source_mapping.source_mapping import SourceMapping +from slither.core.variables.variable import Variable +from slither.exceptions import SlitherError from slither.utils.colors import yellow logger = logging.getLogger("Slither") @@ -54,12 +58,79 @@ def output_json(filename, error, results): ################################################################################### ################################################################################### -def generate_json_result(info, additional_fields=None): +def _convert_to_description(d): + if isinstance(d, str): + return d + + if not isinstance(d, SourceMapping): + raise SlitherError(f'{d} does not inherit from SourceMapping, conversion impossible') + + if isinstance(d, Node): + if d.expression: + return f'{d.expression} ({d.source_mapping_str})' + else: + return f'{str(d)} ({d.source_mapping_str})' + + if hasattr(d, 'canonical_name'): + return f'{d.canonical_name} ({d.source_mapping_str})' + + if hasattr(d, 'name'): + return f'{d.name} ({d.source_mapping_str})' + + raise SlitherError(f'{type(d)} cannot be converted (no name, or canonical_name') + +def _convert_to_markdown(d, markdown_root): + if isinstance(d, str): + return d + + if not isinstance(d, SourceMapping): + raise SlitherError(f'{d} does not inherit from SourceMapping, conversion impossible') + + if isinstance(d, Node): + if d.expression: + return f'[{d.expression}]({d.source_mapping_to_markdown(markdown_root)})' + else: + return f'[{str(d)}]({d.source_mapping_to_markdown(markdown_root)})' + + if hasattr(d, 'canonical_name'): + return f'[{d.canonical_name}]({d.source_mapping_to_markdown(markdown_root)})' + + if hasattr(d, 'name'): + return f'[{d.name}]({d.source_mapping_to_markdown(markdown_root)})' + + raise SlitherError(f'{type(d)} cannot be converted (no name, or canonical_name') + +def generate_json_result(info, additional_fields=None, markdown_root='', standard_format=False): if additional_fields is None: additional_fields = {} d = OrderedDict() d['elements'] = [] - d['description'] = info + d['description'] = ''.join(_convert_to_description(d) for d in info) + d['markdown'] = ''.join(_convert_to_markdown(d, markdown_root) for d in info) + + if standard_format: + to_add = [i for i in info if not isinstance(i, str)] + + for add in to_add: + if isinstance(add, Variable): + add_variable_to_json(add, d) + elif isinstance(add, Contract): + add_contract_to_json(add, d) + elif isinstance(add, Function): + add_function_to_json(add, d) + elif isinstance(add, Enum): + add_enum_to_json(add, d) + elif isinstance(add, Event): + add_event_to_json(add, d) + elif isinstance(add, Structure): + add_struct_to_json(add, d) + elif isinstance(add, Pragma): + add_pragma_to_json(add, d) + elif isinstance(add, Node): + add_node_to_json(add, d) + else: + raise SlitherError(f'Impossible to add {type(add)} to the json') + if additional_fields: d['additional_fields'] = additional_fields diff --git a/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.json b/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.json index 6e544d0c4..09c8fb7b9 100644 --- a/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.json +++ b/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "arbitrary-send", - "impact": "High", - "confidence": "Medium", - "description": "Test.direct() (tests/arbitrary_send-0.5.1.sol#11-13) sends eth to arbitrary user\n\tDangerous calls:\n\t- msg.sender.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#12)\n", "elements": [ { "type": "function", @@ -191,13 +187,14 @@ } } } - ] - }, - { + ], + "description": "Test.direct() (tests/arbitrary_send-0.5.1.sol#11-13) sends eth to arbitrary user\n\tDangerous calls:\n\t- msg.sender.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#12)\n", + "markdown": "[Test.direct()](tests/arbitrary_send-0.5.1.sol#L11-L13) sends eth to arbitrary user\n\tDangerous calls:\n\t- [msg.sender.send(address(this).balance)](tests/arbitrary_send-0.5.1.sol#L12)\n", "check": "arbitrary-send", "impact": "High", - "confidence": "Medium", - "description": "Test.indirect() (tests/arbitrary_send-0.5.1.sol#19-21) sends eth to arbitrary user\n\tDangerous calls:\n\t- destination.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#20)\n", + "confidence": "Medium" + }, + { "elements": [ { "type": "function", @@ -381,7 +378,12 @@ } } } - ] + ], + "description": "Test.indirect() (tests/arbitrary_send-0.5.1.sol#19-21) sends eth to arbitrary user\n\tDangerous calls:\n\t- destination.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#20)\n", + "markdown": "[Test.indirect()](tests/arbitrary_send-0.5.1.sol#L19-L21) sends eth to arbitrary user\n\tDangerous calls:\n\t- [destination.send(address(this).balance)](tests/arbitrary_send-0.5.1.sol#L20)\n", + "check": "arbitrary-send", + "impact": "High", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.txt b/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.txt index cc2b1953f..f439b3e58 100644 --- a/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.txt +++ b/tests/expected_json/arbitrary_send-0.5.1.arbitrary-send.txt @@ -1,4 +1,4 @@ -INFO:Detectors: + Test.direct() (tests/arbitrary_send-0.5.1.sol#11-13) sends eth to arbitrary user Dangerous calls: - msg.sender.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#12) @@ -6,4 +6,4 @@ Test.indirect() (tests/arbitrary_send-0.5.1.sol#19-21) sends eth to arbitrary us Dangerous calls: - destination.send(address(this).balance) (tests/arbitrary_send-0.5.1.sol#20) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations -INFO:Slither:tests/arbitrary_send-0.5.1.sol analyzed (1 contracts), 2 result(s) found +tests/arbitrary_send-0.5.1.sol analyzed (1 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/arbitrary_send.arbitrary-send.json b/tests/expected_json/arbitrary_send.arbitrary-send.json index 993747b20..1d6122843 100644 --- a/tests/expected_json/arbitrary_send.arbitrary-send.json +++ b/tests/expected_json/arbitrary_send.arbitrary-send.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "arbitrary-send", - "impact": "High", - "confidence": "Medium", - "description": "Test.direct() (tests/arbitrary_send.sol#11-13) sends eth to arbitrary user\n\tDangerous calls:\n\t- msg.sender.send(address(this).balance) (tests/arbitrary_send.sol#12)\n", "elements": [ { "type": "function", @@ -191,13 +187,14 @@ } } } - ] - }, - { + ], + "description": "Test.direct() (tests/arbitrary_send.sol#11-13) sends eth to arbitrary user\n\tDangerous calls:\n\t- msg.sender.send(address(this).balance) (tests/arbitrary_send.sol#12)\n", + "markdown": "[Test.direct()](tests/arbitrary_send.sol#L11-L13) sends eth to arbitrary user\n\tDangerous calls:\n\t- [msg.sender.send(address(this).balance)](tests/arbitrary_send.sol#L12)\n", "check": "arbitrary-send", "impact": "High", - "confidence": "Medium", - "description": "Test.indirect() (tests/arbitrary_send.sol#19-21) sends eth to arbitrary user\n\tDangerous calls:\n\t- destination.send(address(this).balance) (tests/arbitrary_send.sol#20)\n", + "confidence": "Medium" + }, + { "elements": [ { "type": "function", @@ -381,7 +378,12 @@ } } } - ] + ], + "description": "Test.indirect() (tests/arbitrary_send.sol#19-21) sends eth to arbitrary user\n\tDangerous calls:\n\t- destination.send(address(this).balance) (tests/arbitrary_send.sol#20)\n", + "markdown": "[Test.indirect()](tests/arbitrary_send.sol#L19-L21) sends eth to arbitrary user\n\tDangerous calls:\n\t- [destination.send(address(this).balance)](tests/arbitrary_send.sol#L20)\n", + "check": "arbitrary-send", + "impact": "High", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/arbitrary_send.arbitrary-send.txt b/tests/expected_json/arbitrary_send.arbitrary-send.txt index ee8440aa4..4b8a2e920 100644 --- a/tests/expected_json/arbitrary_send.arbitrary-send.txt +++ b/tests/expected_json/arbitrary_send.arbitrary-send.txt @@ -1,4 +1,4 @@ -INFO:Detectors: + Test.direct() (tests/arbitrary_send.sol#11-13) sends eth to arbitrary user Dangerous calls: - msg.sender.send(address(this).balance) (tests/arbitrary_send.sol#12) @@ -6,4 +6,4 @@ Test.indirect() (tests/arbitrary_send.sol#19-21) sends eth to arbitrary user Dangerous calls: - destination.send(address(this).balance) (tests/arbitrary_send.sol#20) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations -INFO:Slither:tests/arbitrary_send.sol analyzed (1 contracts), 2 result(s) found +tests/arbitrary_send.sol analyzed (1 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/backdoor.backdoor.json b/tests/expected_json/backdoor.backdoor.json index 243fabcc7..beae48a85 100644 --- a/tests/expected_json/backdoor.backdoor.json +++ b/tests/expected_json/backdoor.backdoor.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "backdoor", - "impact": "High", - "confidence": "High", - "description": "Backdoor function found in C.i_am_a_backdoor (tests/backdoor.sol#4-6)\n", "elements": [ { "type": "function", @@ -56,7 +52,12 @@ "signature": "i_am_a_backdoor()" } } - ] + ], + "description": "Backdoor function found in C.i_am_a_backdoor() (tests/backdoor.sol#4-6)\n", + "markdown": "Backdoor function found in [C.i_am_a_backdoor()](tests/backdoor.sol#L4-L6)\n", + "check": "backdoor", + "impact": "High", + "confidence": "High" } ] } diff --git a/tests/expected_json/backdoor.backdoor.txt b/tests/expected_json/backdoor.backdoor.txt index 76d21139d..68d34c305 100644 --- a/tests/expected_json/backdoor.backdoor.txt +++ b/tests/expected_json/backdoor.backdoor.txt @@ -1,5 +1,5 @@ -INFO:Detectors: -Backdoor function found in C.i_am_a_backdoor (tests/backdoor.sol#4-6) + +Backdoor function found in C.i_am_a_backdoor() (tests/backdoor.sol#4-6) Reference: https://github.com/trailofbits/slither/wiki/Adding-a-new-detector +tests/backdoor.sol analyzed (1 contracts with 1 detectors), 1 result(s) found INFO:Slither:/home/travis/build/crytic/slither/scripts/../tests/expected_json/backdoor.backdoor.json exists already, the overwrite is prevented -INFO:Slither:tests/backdoor.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/backdoor.suicidal.json b/tests/expected_json/backdoor.suicidal.json index 73ff578a5..ae632e1dc 100644 --- a/tests/expected_json/backdoor.suicidal.json +++ b/tests/expected_json/backdoor.suicidal.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "suicidal", - "impact": "High", - "confidence": "High", - "description": "C.i_am_a_backdoor() (tests/backdoor.sol#4-6) allows anyone to destruct the contract\n", "elements": [ { "type": "function", @@ -56,7 +52,12 @@ "signature": "i_am_a_backdoor()" } } - ] + ], + "description": "C.i_am_a_backdoor() (tests/backdoor.sol#4-6) allows anyone to destruct the contract\n", + "markdown": "[C.i_am_a_backdoor()](tests/backdoor.sol#L4-L6) allows anyone to destruct the contract\n", + "check": "suicidal", + "impact": "High", + "confidence": "High" } ] } diff --git a/tests/expected_json/backdoor.suicidal.txt b/tests/expected_json/backdoor.suicidal.txt index eefe0e4bf..80a385db6 100644 --- a/tests/expected_json/backdoor.suicidal.txt +++ b/tests/expected_json/backdoor.suicidal.txt @@ -1,5 +1,5 @@ -INFO:Detectors: + C.i_am_a_backdoor() (tests/backdoor.sol#4-6) allows anyone to destruct the contract Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#suicidal +tests/backdoor.sol analyzed (1 contracts with 1 detectors), 1 result(s) found INFO:Slither:/home/travis/build/crytic/slither/scripts/../tests/expected_json/backdoor.suicidal.json exists already, the overwrite is prevented -INFO:Slither:tests/backdoor.sol analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/const_state_variables.constable-states.json b/tests/expected_json/const_state_variables.constable-states.json index 60aeaa59b..5864c1e07 100644 --- a/tests/expected_json/const_state_variables.constable-states.json +++ b/tests/expected_json/const_state_variables.constable-states.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "constable-states", - "impact": "Optimization", - "confidence": "High", - "description": "A.myFriendsAddress should be constant (tests/const_state_variables.sol#7)\n", "elements": [ { "type": "variable", @@ -64,13 +60,14 @@ } } } - ] - }, - { + ], + "description": "A.myFriendsAddress (tests/const_state_variables.sol#7) should be constant\n", + "markdown": "[A.myFriendsAddress](tests/const_state_variables.sol#L7) should be constant\n", "check": "constable-states", "impact": "Optimization", - "confidence": "High", - "description": "A.test should be constant (tests/const_state_variables.sol#10)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -127,13 +124,14 @@ } } } - ] - }, - { + ], + "description": "A.test (tests/const_state_variables.sol#10) should be constant\n", + "markdown": "[A.test](tests/const_state_variables.sol#L10) should be constant\n", "check": "constable-states", "impact": "Optimization", - "confidence": "High", - "description": "A.text2 should be constant (tests/const_state_variables.sol#14)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -190,13 +188,14 @@ } } } - ] - }, - { + ], + "description": "A.text2 (tests/const_state_variables.sol#14) should be constant\n", + "markdown": "[A.text2](tests/const_state_variables.sol#L14) should be constant\n", "check": "constable-states", "impact": "Optimization", - "confidence": "High", - "description": "B.mySistersAddress should be constant (tests/const_state_variables.sol#26)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -249,13 +248,14 @@ } } } - ] - }, - { + ], + "description": "B.mySistersAddress (tests/const_state_variables.sol#26) should be constant\n", + "markdown": "[B.mySistersAddress](tests/const_state_variables.sol#L26) should be constant\n", "check": "constable-states", "impact": "Optimization", - "confidence": "High", - "description": "MyConc.should_be_constant should be constant (tests/const_state_variables.sol#42)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -308,13 +308,14 @@ } } } - ] - }, - { + ], + "description": "MyConc.should_be_constant (tests/const_state_variables.sol#42) should be constant\n", + "markdown": "[MyConc.should_be_constant](tests/const_state_variables.sol#L42) should be constant\n", "check": "constable-states", "impact": "Optimization", - "confidence": "High", - "description": "MyConc.should_be_constant_2 should be constant (tests/const_state_variables.sol#43)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -367,7 +368,12 @@ } } } - ] + ], + "description": "MyConc.should_be_constant_2 (tests/const_state_variables.sol#43) should be constant\n", + "markdown": "[MyConc.should_be_constant_2](tests/const_state_variables.sol#L43) should be constant\n", + "check": "constable-states", + "impact": "Optimization", + "confidence": "High" } ] } diff --git a/tests/expected_json/const_state_variables.constable-states.txt b/tests/expected_json/const_state_variables.constable-states.txt index d7b05ff8e..27670357d 100644 --- a/tests/expected_json/const_state_variables.constable-states.txt +++ b/tests/expected_json/const_state_variables.constable-states.txt @@ -1,9 +1,9 @@ -INFO:Detectors: -A.myFriendsAddress should be constant (tests/const_state_variables.sol#7) -A.test should be constant (tests/const_state_variables.sol#10) -A.text2 should be constant (tests/const_state_variables.sol#14) -B.mySistersAddress should be constant (tests/const_state_variables.sol#26) -MyConc.should_be_constant should be constant (tests/const_state_variables.sol#42) -MyConc.should_be_constant_2 should be constant (tests/const_state_variables.sol#43) + +A.myFriendsAddress (tests/const_state_variables.sol#7) should be constant +A.test (tests/const_state_variables.sol#10) should be constant +A.text2 (tests/const_state_variables.sol#14) should be constant +B.mySistersAddress (tests/const_state_variables.sol#26) should be constant +MyConc.should_be_constant (tests/const_state_variables.sol#42) should be constant +MyConc.should_be_constant_2 (tests/const_state_variables.sol#43) should be constant Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant -INFO:Slither:tests/const_state_variables.sol analyzed (3 contracts), 6 result(s) found +tests/const_state_variables.sol analyzed (3 contracts with 1 detectors), 6 result(s) found diff --git a/tests/expected_json/constant-0.5.1.constant-function.json b/tests/expected_json/constant-0.5.1.constant-function.json index 92880bd23..158cd404d 100644 --- a/tests/expected_json/constant-0.5.1.constant-function.json +++ b/tests/expected_json/constant-0.5.1.constant-function.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "constant-function", - "impact": "Medium", - "confidence": "Medium", - "description": "Constant.test_assembly_bug() (tests/constant-0.5.1.sol#15-17) is declared view but contains assembly code\n", "elements": [ { "type": "function", @@ -68,9 +64,14 @@ } } ], + "description": "Constant.test_assembly_bug() (tests/constant-0.5.1.sol#15-17) is declared view but contains assembly code\n", + "markdown": "[Constant.test_assembly_bug()](tests/constant-0.5.1.sol#L15-L17) is declared view but contains assembly code\n", "additional_fields": { "contains_assembly": true - } + }, + "check": "constant-function", + "impact": "Medium", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/constant-0.5.1.constant-function.txt b/tests/expected_json/constant-0.5.1.constant-function.txt index 2f308dd12..1fa22f64d 100644 --- a/tests/expected_json/constant-0.5.1.constant-function.txt +++ b/tests/expected_json/constant-0.5.1.constant-function.txt @@ -1,4 +1,4 @@ -INFO:Detectors: + Constant.test_assembly_bug() (tests/constant-0.5.1.sol#15-17) is declared view but contains assembly code Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state -INFO:Slither:tests/constant-0.5.1.sol analyzed (1 contracts), 1 result(s) found +tests/constant-0.5.1.sol analyzed (1 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/constant.constant-function.json b/tests/expected_json/constant.constant-function.json index cf6f53771..a15771900 100644 --- a/tests/expected_json/constant.constant-function.json +++ b/tests/expected_json/constant.constant-function.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "constant-function", - "impact": "Medium", - "confidence": "Medium", - "description": "Constant.test_view_bug() (tests/constant.sol#5-7) is declared view but changes state variables:\n\t- Constant.a\n", "elements": [ { "type": "function", @@ -137,15 +133,16 @@ } } ], + "description": "Constant.test_view_bug() (tests/constant.sol#5-7) is declared view but changes state variables:\n\t- Constant.a (tests/constant.sol#3)\n", + "markdown": "[Constant.test_view_bug()](tests/constant.sol#L5-L7) is declared view but changes state variables:\n\t- [Constant.a](tests/constant.sol#L3)\n", "additional_fields": { "contains_assembly": false - } - }, - { + }, "check": "constant-function", "impact": "Medium", - "confidence": "Medium", - "description": "Constant.test_constant_bug() (tests/constant.sol#9-11) is declared view but changes state variables:\n\t- Constant.a\n", + "confidence": "Medium" + }, + { "elements": [ { "type": "function", @@ -275,15 +272,16 @@ } } ], + "description": "Constant.test_constant_bug() (tests/constant.sol#9-11) is declared view but changes state variables:\n\t- Constant.a (tests/constant.sol#3)\n", + "markdown": "[Constant.test_constant_bug()](tests/constant.sol#L9-L11) is declared view but changes state variables:\n\t- [Constant.a](tests/constant.sol#L3)\n", "additional_fields": { "contains_assembly": false - } - }, - { + }, "check": "constant-function", "impact": "Medium", - "confidence": "Medium", - "description": "Constant.test_assembly_bug() (tests/constant.sol#22-24) is declared view but contains assembly code\n", + "confidence": "Medium" + }, + { "elements": [ { "type": "function", @@ -351,9 +349,14 @@ } } ], + "description": "Constant.test_assembly_bug() (tests/constant.sol#22-24) is declared view but contains assembly code\n", + "markdown": "[Constant.test_assembly_bug()](tests/constant.sol#L22-L24) is declared view but contains assembly code\n", "additional_fields": { "contains_assembly": true - } + }, + "check": "constant-function", + "impact": "Medium", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/constant.constant-function.txt b/tests/expected_json/constant.constant-function.txt index 00eed4577..f2b695232 100644 --- a/tests/expected_json/constant.constant-function.txt +++ b/tests/expected_json/constant.constant-function.txt @@ -1,8 +1,8 @@ -INFO:Detectors: + Constant.test_view_bug() (tests/constant.sol#5-7) is declared view but changes state variables: - - Constant.a + - Constant.a (tests/constant.sol#3) Constant.test_constant_bug() (tests/constant.sol#9-11) is declared view but changes state variables: - - Constant.a + - Constant.a (tests/constant.sol#3) Constant.test_assembly_bug() (tests/constant.sol#22-24) is declared view but contains assembly code Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state -INFO:Slither:tests/constant.sol analyzed (1 contracts), 3 result(s) found +tests/constant.sol analyzed (1 contracts with 1 detectors), 3 result(s) found diff --git a/tests/expected_json/controlled_delegatecall.controlled-delegatecall.json b/tests/expected_json/controlled_delegatecall.controlled-delegatecall.json index 8ee63d9cc..1f2c9bf9c 100644 --- a/tests/expected_json/controlled_delegatecall.controlled-delegatecall.json +++ b/tests/expected_json/controlled_delegatecall.controlled-delegatecall.json @@ -4,11 +4,73 @@ "results": { "detectors": [ { - "check": "controlled-delegatecall", - "impact": "High", - "confidence": "Medium", - "description": "C.bad_delegate_call (tests/controlled_delegatecall.sol#8-11) uses delegatecall to a input-controlled function id\n\t- addr_bad.delegatecall(data) (tests/controlled_delegatecall.sol#10)\n", "elements": [ + { + "type": "function", + "name": "bad_delegate_call", + "source_mapping": { + "start": 101, + "length": 134, + "filename_used": "/home/travis/build/crytic/slither/tests/controlled_delegatecall.sol", + "filename_relative": "tests/controlled_delegatecall.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/controlled_delegatecall.sol", + "filename_short": "tests/controlled_delegatecall.sol", + "is_dependency": false, + "lines": [ + 8, + 9, + 10, + 11 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 585, + "filename_used": "/home/travis/build/crytic/slither/tests/controlled_delegatecall.sol", + "filename_relative": "tests/controlled_delegatecall.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/controlled_delegatecall.sol", + "filename_short": "tests/controlled_delegatecall.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "bad_delegate_call(bytes)" + } + }, { "type": "node", "name": "addr_bad.delegatecall(data)", @@ -94,23 +156,31 @@ } } } - }, + } + ], + "description": "C.bad_delegate_call(bytes) (tests/controlled_delegatecall.sol#8-11) uses delegatecall to a input-controlled function id\n\t- addr_bad.delegatecall(data) (tests/controlled_delegatecall.sol#10)\n", + "markdown": "[C.bad_delegate_call(bytes)](tests/controlled_delegatecall.sol#L8-L11) uses delegatecall to a input-controlled function id\n\t- [addr_bad.delegatecall(data)](tests/controlled_delegatecall.sol#L10)\n", + "check": "controlled-delegatecall", + "impact": "High", + "confidence": "Medium" + }, + { + "elements": [ { "type": "function", - "name": "bad_delegate_call", + "name": "bad_delegate_call2", "source_mapping": { - "start": 101, - "length": 134, + "start": 337, + "length": 118, "filename_used": "/home/travis/build/crytic/slither/tests/controlled_delegatecall.sol", "filename_relative": "tests/controlled_delegatecall.sol", "filename_absolute": "/home/travis/build/crytic/slither/tests/controlled_delegatecall.sol", "filename_short": "tests/controlled_delegatecall.sol", "is_dependency": false, "lines": [ - 8, - 9, - 10, - 11 + 18, + 19, + 20 ], "starting_column": 5, "ending_column": 6 @@ -158,17 +228,9 @@ "ending_column": 2 } }, - "signature": "bad_delegate_call(bytes)" + "signature": "bad_delegate_call2(bytes)" } - } - ] - }, - { - "check": "controlled-delegatecall", - "impact": "High", - "confidence": "Medium", - "description": "C.bad_delegate_call2 (tests/controlled_delegatecall.sol#18-20) uses delegatecall to a input-controlled function id\n\t- addr_bad.delegatecall(abi.encode(func_id,data)) (tests/controlled_delegatecall.sol#19)\n", - "elements": [ + }, { "type": "node", "name": "addr_bad.delegatecall(abi.encode(func_id,data))", @@ -253,73 +315,13 @@ } } } - }, - { - "type": "function", - "name": "bad_delegate_call2", - "source_mapping": { - "start": 337, - "length": 118, - "filename_used": "/home/travis/build/crytic/slither/tests/controlled_delegatecall.sol", - "filename_relative": "tests/controlled_delegatecall.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/controlled_delegatecall.sol", - "filename_short": "tests/controlled_delegatecall.sol", - "is_dependency": false, - "lines": [ - 18, - 19, - 20 - ], - "starting_column": 5, - "ending_column": 6 - }, - "type_specific_fields": { - "parent": { - "type": "contract", - "name": "C", - "source_mapping": { - "start": 0, - "length": 585, - "filename_used": "/home/travis/build/crytic/slither/tests/controlled_delegatecall.sol", - "filename_relative": "tests/controlled_delegatecall.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/controlled_delegatecall.sol", - "filename_short": "tests/controlled_delegatecall.sol", - "is_dependency": false, - "lines": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25 - ], - "starting_column": 1, - "ending_column": 2 - } - }, - "signature": "bad_delegate_call2(bytes)" - } } - ] + ], + "description": "C.bad_delegate_call2(bytes) (tests/controlled_delegatecall.sol#18-20) uses delegatecall to a input-controlled function id\n\t- addr_bad.delegatecall(abi.encode(func_id,data)) (tests/controlled_delegatecall.sol#19)\n", + "markdown": "[C.bad_delegate_call2(bytes)](tests/controlled_delegatecall.sol#L18-L20) uses delegatecall to a input-controlled function id\n\t- [addr_bad.delegatecall(abi.encode(func_id,data))](tests/controlled_delegatecall.sol#L19)\n", + "check": "controlled-delegatecall", + "impact": "High", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/controlled_delegatecall.controlled-delegatecall.txt b/tests/expected_json/controlled_delegatecall.controlled-delegatecall.txt index c97185377..ade36ba5b 100644 --- a/tests/expected_json/controlled_delegatecall.controlled-delegatecall.txt +++ b/tests/expected_json/controlled_delegatecall.controlled-delegatecall.txt @@ -1,7 +1,7 @@ -INFO:Detectors: -C.bad_delegate_call (tests/controlled_delegatecall.sol#8-11) uses delegatecall to a input-controlled function id + +C.bad_delegate_call(bytes) (tests/controlled_delegatecall.sol#8-11) uses delegatecall to a input-controlled function id - addr_bad.delegatecall(data) (tests/controlled_delegatecall.sol#10) -C.bad_delegate_call2 (tests/controlled_delegatecall.sol#18-20) uses delegatecall to a input-controlled function id +C.bad_delegate_call2(bytes) (tests/controlled_delegatecall.sol#18-20) uses delegatecall to a input-controlled function id - addr_bad.delegatecall(abi.encode(func_id,data)) (tests/controlled_delegatecall.sol#19) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall -INFO:Slither:tests/controlled_delegatecall.sol analyzed (1 contracts), 2 result(s) found +tests/controlled_delegatecall.sol analyzed (1 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/deprecated_calls.deprecated-standards.json b/tests/expected_json/deprecated_calls.deprecated-standards.json index 9680b948d..c318914ac 100644 --- a/tests/expected_json/deprecated_calls.deprecated-standards.json +++ b/tests/expected_json/deprecated_calls.deprecated-standards.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "deprecated-standards", - "impact": "Informational", - "confidence": "High", - "description": "Deprecated standard detected @ tests/deprecated_calls.sol#2:\n\t- Usage of \"block.blockhash()\" should be replaced with \"blockhash()\"\n", "elements": [ { "type": "variable", @@ -73,13 +69,14 @@ } } } - ] - }, - { + ], + "description": "Deprecated standard detected ContractWithDeprecatedReferences.globalBlockHash (tests/deprecated_calls.sol#2):\n\t- Usage of \"block.blockhash()\" should be replaced with \"blockhash()\"\n", + "markdown": "Deprecated standard detected [ContractWithDeprecatedReferences.globalBlockHash](tests/deprecated_calls.sol#L2):\n\t- Usage of \"block.blockhash()\" should be replaced with \"blockhash()\"\n", "check": "deprecated-standards", "impact": "Informational", - "confidence": "High", - "description": "Deprecated standard detected @ tests/deprecated_calls.sol#7:\n\t- Usage of \"msg.gas\" should be replaced with \"gasleft()\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "node", @@ -172,13 +169,14 @@ } } } - ] - }, - { + ], + "description": "Deprecated standard detected msg.gas == msg.value (tests/deprecated_calls.sol#7):\n\t- Usage of \"msg.gas\" should be replaced with \"gasleft()\"\n", + "markdown": "Deprecated standard detected [msg.gas == msg.value](tests/deprecated_calls.sol#L7):\n\t- Usage of \"msg.gas\" should be replaced with \"gasleft()\"\n", "check": "deprecated-standards", "impact": "Informational", - "confidence": "High", - "description": "Deprecated standard detected @ tests/deprecated_calls.sol#9:\n\t- Usage of \"throw\" should be replaced with \"revert()\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "node", @@ -271,13 +269,14 @@ } } } - ] - }, - { + ], + "description": "Deprecated standard detected THROW None (tests/deprecated_calls.sol#9):\n\t- Usage of \"throw\" should be replaced with \"revert()\"\n", + "markdown": "Deprecated standard detected [THROW None](tests/deprecated_calls.sol#L9):\n\t- Usage of \"throw\" should be replaced with \"revert()\"\n", "check": "deprecated-standards", "impact": "Informational", - "confidence": "High", - "description": "Deprecated standard detected @ tests/deprecated_calls.sol#16:\n\t- Usage of \"sha3()\" should be replaced with \"keccak256()\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "node", @@ -376,13 +375,14 @@ } } } - ] - }, - { + ], + "description": "Deprecated standard detected sha3Result = sha3()(test deprecated sha3 usage) (tests/deprecated_calls.sol#16):\n\t- Usage of \"sha3()\" should be replaced with \"keccak256()\"\n", + "markdown": "Deprecated standard detected [sha3Result = sha3()(test deprecated sha3 usage)](tests/deprecated_calls.sol#L16):\n\t- Usage of \"sha3()\" should be replaced with \"keccak256()\"\n", "check": "deprecated-standards", "impact": "Informational", - "confidence": "High", - "description": "Deprecated standard detected @ tests/deprecated_calls.sol#19:\n\t- Usage of \"block.blockhash()\" should be replaced with \"blockhash()\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "node", @@ -481,13 +481,14 @@ } } } - ] - }, - { + ], + "description": "Deprecated standard detected blockHashResult = block.blockhash(0) (tests/deprecated_calls.sol#19):\n\t- Usage of \"block.blockhash()\" should be replaced with \"blockhash()\"\n", + "markdown": "Deprecated standard detected [blockHashResult = block.blockhash(0)](tests/deprecated_calls.sol#L19):\n\t- Usage of \"block.blockhash()\" should be replaced with \"blockhash()\"\n", "check": "deprecated-standards", "impact": "Informational", - "confidence": "High", - "description": "Deprecated standard detected @ tests/deprecated_calls.sol#22:\n\t- Usage of \"callcode\" should be replaced with \"delegatecall\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "node", @@ -586,13 +587,14 @@ } } } - ] - }, - { + ], + "description": "Deprecated standard detected address(this).callcode() (tests/deprecated_calls.sol#22):\n\t- Usage of \"callcode\" should be replaced with \"delegatecall\"\n", + "markdown": "Deprecated standard detected [address(this).callcode()](tests/deprecated_calls.sol#L22):\n\t- Usage of \"callcode\" should be replaced with \"delegatecall\"\n", "check": "deprecated-standards", "impact": "Informational", - "confidence": "High", - "description": "Deprecated standard detected @ tests/deprecated_calls.sol#25:\n\t- Usage of \"suicide()\" should be replaced with \"selfdestruct()\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "node", @@ -691,13 +693,14 @@ } } } - ] - }, - { + ], + "description": "Deprecated standard detected suicide(address)(address(0)) (tests/deprecated_calls.sol#25):\n\t- Usage of \"suicide()\" should be replaced with \"selfdestruct()\"\n", + "markdown": "Deprecated standard detected [suicide(address)(address(0))](tests/deprecated_calls.sol#L25):\n\t- Usage of \"suicide()\" should be replaced with \"selfdestruct()\"\n", "check": "deprecated-standards", "impact": "Informational", - "confidence": "High", - "description": "Deprecated standard detected @ tests/deprecated_calls.sol#2:\n\t- Usage of \"block.blockhash()\" should be replaced with \"blockhash()\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "node", @@ -810,7 +813,12 @@ } } } - ] + ], + "description": "Deprecated standard detected globalBlockHash = block.blockhash(0) (tests/deprecated_calls.sol#2):\n\t- Usage of \"block.blockhash()\" should be replaced with \"blockhash()\"\n", + "markdown": "Deprecated standard detected [globalBlockHash = block.blockhash(0)](tests/deprecated_calls.sol#L2):\n\t- Usage of \"block.blockhash()\" should be replaced with \"blockhash()\"\n", + "check": "deprecated-standards", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/deprecated_calls.deprecated-standards.txt b/tests/expected_json/deprecated_calls.deprecated-standards.txt index 63d07a08d..a8180ef3b 100644 --- a/tests/expected_json/deprecated_calls.deprecated-standards.txt +++ b/tests/expected_json/deprecated_calls.deprecated-standards.txt @@ -1,19 +1,19 @@ -INFO:Detectors: -Deprecated standard detected @ tests/deprecated_calls.sol#2: + +Deprecated standard detected ContractWithDeprecatedReferences.globalBlockHash (tests/deprecated_calls.sol#2): - Usage of "block.blockhash()" should be replaced with "blockhash()" -Deprecated standard detected @ tests/deprecated_calls.sol#7: +Deprecated standard detected msg.gas == msg.value (tests/deprecated_calls.sol#7): - Usage of "msg.gas" should be replaced with "gasleft()" -Deprecated standard detected @ tests/deprecated_calls.sol#9: +Deprecated standard detected THROW None (tests/deprecated_calls.sol#9): - Usage of "throw" should be replaced with "revert()" -Deprecated standard detected @ tests/deprecated_calls.sol#16: +Deprecated standard detected sha3Result = sha3()(test deprecated sha3 usage) (tests/deprecated_calls.sol#16): - Usage of "sha3()" should be replaced with "keccak256()" -Deprecated standard detected @ tests/deprecated_calls.sol#19: +Deprecated standard detected blockHashResult = block.blockhash(0) (tests/deprecated_calls.sol#19): - Usage of "block.blockhash()" should be replaced with "blockhash()" -Deprecated standard detected @ tests/deprecated_calls.sol#22: +Deprecated standard detected address(this).callcode() (tests/deprecated_calls.sol#22): - Usage of "callcode" should be replaced with "delegatecall" -Deprecated standard detected @ tests/deprecated_calls.sol#25: +Deprecated standard detected suicide(address)(address(0)) (tests/deprecated_calls.sol#25): - Usage of "suicide()" should be replaced with "selfdestruct()" -Deprecated standard detected @ tests/deprecated_calls.sol#2: +Deprecated standard detected globalBlockHash = block.blockhash(0) (tests/deprecated_calls.sol#2): - Usage of "block.blockhash()" should be replaced with "blockhash()" Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards -INFO:Slither:tests/deprecated_calls.sol analyzed (1 contracts), 8 result(s) found +tests/deprecated_calls.sol analyzed (1 contracts with 1 detectors), 8 result(s) found diff --git a/tests/expected_json/erc20_indexed.erc20-indexed.json b/tests/expected_json/erc20_indexed.erc20-indexed.json index b6d7aafcb..3aeaf30a9 100644 --- a/tests/expected_json/erc20_indexed.erc20-indexed.json +++ b/tests/expected_json/erc20_indexed.erc20-indexed.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "erc20-indexed", - "impact": "Informational", - "confidence": "High", - "description": "ERC20 event IERC20Bad.Transfer (tests/erc20_indexed.sol#19) does not index parameter 'from'\n", "elements": [ { "type": "event", @@ -60,13 +56,14 @@ "parameter_name": "from" } } - ] - }, - { + ], + "description": "ERC20 event IERC20BadTransfer(address,address,uint256) (tests/erc20_indexed.sol#19)does not index parameter from\n", + "markdown": "ERC20 event [IERC20BadTransfer(address,address,uint256)](tests/erc20_indexed.sol#L19)does not index parameter from\n", "check": "erc20-indexed", "impact": "Informational", - "confidence": "High", - "description": "ERC20 event IERC20Bad.Transfer (tests/erc20_indexed.sol#19) does not index parameter 'to'\n", + "confidence": "High" + }, + { "elements": [ { "type": "event", @@ -119,13 +116,14 @@ "parameter_name": "to" } } - ] - }, - { + ], + "description": "ERC20 event IERC20BadTransfer(address,address,uint256) (tests/erc20_indexed.sol#19)does not index parameter to\n", + "markdown": "ERC20 event [IERC20BadTransfer(address,address,uint256)](tests/erc20_indexed.sol#L19)does not index parameter to\n", "check": "erc20-indexed", "impact": "Informational", - "confidence": "High", - "description": "ERC20 event IERC20Bad.Approval (tests/erc20_indexed.sol#20) does not index parameter 'owner'\n", + "confidence": "High" + }, + { "elements": [ { "type": "event", @@ -178,13 +176,14 @@ "parameter_name": "owner" } } - ] - }, - { + ], + "description": "ERC20 event IERC20BadApproval(address,address,uint256) (tests/erc20_indexed.sol#20)does not index parameter owner\n", + "markdown": "ERC20 event [IERC20BadApproval(address,address,uint256)](tests/erc20_indexed.sol#L20)does not index parameter owner\n", "check": "erc20-indexed", "impact": "Informational", - "confidence": "High", - "description": "ERC20 event IERC20Bad.Approval (tests/erc20_indexed.sol#20) does not index parameter 'spender'\n", + "confidence": "High" + }, + { "elements": [ { "type": "event", @@ -237,7 +236,12 @@ "parameter_name": "spender" } } - ] + ], + "description": "ERC20 event IERC20BadApproval(address,address,uint256) (tests/erc20_indexed.sol#20)does not index parameter spender\n", + "markdown": "ERC20 event [IERC20BadApproval(address,address,uint256)](tests/erc20_indexed.sol#L20)does not index parameter spender\n", + "check": "erc20-indexed", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/erc20_indexed.erc20-indexed.txt b/tests/expected_json/erc20_indexed.erc20-indexed.txt index db0314cbd..4f7728022 100644 --- a/tests/expected_json/erc20_indexed.erc20-indexed.txt +++ b/tests/expected_json/erc20_indexed.erc20-indexed.txt @@ -1,7 +1,7 @@ -INFO:Detectors: -ERC20 event IERC20Bad.Transfer (tests/erc20_indexed.sol#19) does not index parameter 'from' -ERC20 event IERC20Bad.Transfer (tests/erc20_indexed.sol#19) does not index parameter 'to' -ERC20 event IERC20Bad.Approval (tests/erc20_indexed.sol#20) does not index parameter 'owner' -ERC20 event IERC20Bad.Approval (tests/erc20_indexed.sol#20) does not index parameter 'spender' + +ERC20 event IERC20BadTransfer(address,address,uint256) (tests/erc20_indexed.sol#19)does not index parameter from +ERC20 event IERC20BadTransfer(address,address,uint256) (tests/erc20_indexed.sol#19)does not index parameter to +ERC20 event IERC20BadApproval(address,address,uint256) (tests/erc20_indexed.sol#20)does not index parameter owner +ERC20 event IERC20BadApproval(address,address,uint256) (tests/erc20_indexed.sol#20)does not index parameter spender Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters -INFO:Slither:tests/erc20_indexed.sol analyzed (3 contracts), 4 result(s) found +tests/erc20_indexed.sol analyzed (3 contracts with 1 detectors), 4 result(s) found diff --git a/tests/expected_json/external_function.external-function.json b/tests/expected_json/external_function.external-function.json index 026c45140..2e1fa666c 100644 --- a/tests/expected_json/external_function.external-function.json +++ b/tests/expected_json/external_function.external-function.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "external-function", - "impact": "Optimization", - "confidence": "High", - "description": "funcNotCalled3() should be declared external:\n\t- ContractWithFunctionNotCalled.funcNotCalled3() (tests/external_function.sol#13-15)\n", "elements": [ { "type": "function", @@ -68,13 +64,14 @@ "signature": "funcNotCalled3()" } } - ] - }, - { + ], + "description": "funcNotCalled3() should be declared external:\n\t- ContractWithFunctionNotCalled.funcNotCalled3() (tests/external_function.sol#13-15)\n", + "markdown": "funcNotCalled3() should be declared external:\n\t- [ContractWithFunctionNotCalled.funcNotCalled3()](tests/external_function.sol#L13-L15)\n", "check": "external-function", "impact": "Optimization", - "confidence": "High", - "description": "funcNotCalled2() should be declared external:\n\t- ContractWithFunctionNotCalled.funcNotCalled2() (tests/external_function.sol#17-19)\n", + "confidence": "High" + }, + { "elements": [ { "type": "function", @@ -135,13 +132,14 @@ "signature": "funcNotCalled2()" } } - ] - }, - { + ], + "description": "funcNotCalled2() should be declared external:\n\t- ContractWithFunctionNotCalled.funcNotCalled2() (tests/external_function.sol#17-19)\n", + "markdown": "funcNotCalled2() should be declared external:\n\t- [ContractWithFunctionNotCalled.funcNotCalled2()](tests/external_function.sol#L17-L19)\n", "check": "external-function", "impact": "Optimization", - "confidence": "High", - "description": "funcNotCalled() should be declared external:\n\t- ContractWithFunctionNotCalled.funcNotCalled() (tests/external_function.sol#21-23)\n", + "confidence": "High" + }, + { "elements": [ { "type": "function", @@ -202,13 +200,14 @@ "signature": "funcNotCalled()" } } - ] - }, - { + ], + "description": "funcNotCalled() should be declared external:\n\t- ContractWithFunctionNotCalled.funcNotCalled() (tests/external_function.sol#21-23)\n", + "markdown": "funcNotCalled() should be declared external:\n\t- [ContractWithFunctionNotCalled.funcNotCalled()](tests/external_function.sol#L21-L23)\n", "check": "external-function", "impact": "Optimization", - "confidence": "High", - "description": "funcNotCalled() should be declared external:\n\t- ContractWithFunctionNotCalled2.funcNotCalled() (tests/external_function.sol#32-39)\n", + "confidence": "High" + }, + { "elements": [ { "type": "function", @@ -265,13 +264,14 @@ "signature": "funcNotCalled()" } } - ] - }, - { + ], + "description": "funcNotCalled() should be declared external:\n\t- ContractWithFunctionNotCalled2.funcNotCalled() (tests/external_function.sol#32-39)\n", + "markdown": "funcNotCalled() should be declared external:\n\t- [ContractWithFunctionNotCalled2.funcNotCalled()](tests/external_function.sol#L32-L39)\n", "check": "external-function", "impact": "Optimization", - "confidence": "High", - "description": "parameter_read_ok_for_external(uint256) should be declared external:\n\t- FunctionParameterWrite.parameter_read_ok_for_external(uint256) (tests/external_function.sol#74-76)\n", + "confidence": "High" + }, + { "elements": [ { "type": "function", @@ -324,7 +324,12 @@ "signature": "parameter_read_ok_for_external(uint256)" } } - ] + ], + "description": "parameter_read_ok_for_external(uint256) should be declared external:\n\t- FunctionParameterWrite.parameter_read_ok_for_external(uint256) (tests/external_function.sol#74-76)\n", + "markdown": "parameter_read_ok_for_external(uint256) should be declared external:\n\t- [FunctionParameterWrite.parameter_read_ok_for_external(uint256)](tests/external_function.sol#L74-L76)\n", + "check": "external-function", + "impact": "Optimization", + "confidence": "High" } ] } diff --git a/tests/expected_json/incorrect_equality.incorrect-equality.json b/tests/expected_json/incorrect_equality.incorrect-equality.json index 3802e83b6..bf26037cf 100644 --- a/tests/expected_json/incorrect_equality.incorrect-equality.json +++ b/tests/expected_json/incorrect_equality.incorrect-equality.json @@ -4,11 +4,66 @@ "results": { "detectors": [ { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "ERC20TestBalance.bad0(ERC20Function) (tests/incorrect_equality.sol#21-23) uses a dangerous strict equality:\n\t- require(bool)(erc.balanceOf(address(this)) == 10)\n", "elements": [ + { + "type": "function", + "name": "bad0", + "source_mapping": { + "start": 404, + "length": 101, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", + "filename_relative": "tests/incorrect_equality.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", + "filename_short": "tests/incorrect_equality.sol", + "is_dependency": false, + "lines": [ + 21, + 22, + 23 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20TestBalance", + "source_mapping": { + "start": 165, + "length": 445, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", + "filename_relative": "tests/incorrect_equality.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", + "filename_short": "tests/incorrect_equality.sol", + "is_dependency": false, + "lines": [ + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "bad0(ERC20Function)" + } + }, { "type": "node", "name": "require(bool)(erc.balanceOf(address(this)) == 10)", @@ -87,22 +142,31 @@ } } } - }, + } + ], + "description": "ERC20TestBalance.bad0(ERC20Function) (tests/incorrect_equality.sol#21-23) uses a dangerous strict equality:\n\t- require(bool)(erc.balanceOf(address(this)) == 10) (tests/incorrect_equality.sol#22)\n", + "markdown": "[ERC20TestBalance.bad0(ERC20Function)](tests/incorrect_equality.sol#L21-L23) uses a dangerous strict equality:\n\t- [require(bool)(erc.balanceOf(address(this)) == 10)](tests/incorrect_equality.sol#L22)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" + }, + { + "elements": [ { "type": "function", - "name": "bad0", + "name": "bad1", "source_mapping": { - "start": 404, - "length": 101, + "start": 511, + "length": 97, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 21, - 22, - 23 + 25, + 26, + 27 ], "starting_column": 5, "ending_column": 6 @@ -144,17 +208,9 @@ "ending_column": 2 } }, - "signature": "bad0(ERC20Function)" + "signature": "bad1(ERC20Variable)" } - } - ] - }, - { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "ERC20TestBalance.bad1(ERC20Variable) (tests/incorrect_equality.sol#25-27) uses a dangerous strict equality:\n\t- require(bool)(erc.balanceOf(msg.sender) == 10)\n", - "elements": [ + }, { "type": "node", "name": "require(bool)(erc.balanceOf(msg.sender) == 10)", @@ -233,22 +289,32 @@ } } } - }, + } + ], + "description": "ERC20TestBalance.bad1(ERC20Variable) (tests/incorrect_equality.sol#25-27) uses a dangerous strict equality:\n\t- require(bool)(erc.balanceOf(msg.sender) == 10) (tests/incorrect_equality.sol#26)\n", + "markdown": "[ERC20TestBalance.bad1(ERC20Variable)](tests/incorrect_equality.sol#L25-L27) uses a dangerous strict equality:\n\t- [require(bool)(erc.balanceOf(msg.sender) == 10)](tests/incorrect_equality.sol#L26)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" + }, + { + "elements": [ { "type": "function", - "name": "bad1", + "name": "bad0", "source_mapping": { - "start": 511, - "length": 97, + "start": 648, + "length": 133, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 25, - 26, - 27 + 32, + 33, + 34, + 35 ], "starting_column": 5, "ending_column": 6 @@ -256,51 +322,92 @@ "type_specific_fields": { "parent": { "type": "contract", - "name": "ERC20TestBalance", + "name": "TestContractBalance", "source_mapping": { - "start": 165, - "length": 445, + "start": 612, + "length": 1754, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28 + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97 ], "starting_column": 1, "ending_column": 2 } }, - "signature": "bad1(ERC20Variable)" + "signature": "bad0()" } - } - ] - }, - { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "TestContractBalance.bad0() (tests/incorrect_equality.sol#32-35) uses a dangerous strict equality:\n\t- require(bool)(address(address(this)).balance == 10000000000000000000)\n", - "elements": [ + }, { "type": "node", "name": "require(bool)(address(address(this)).balance == 10000000000000000000)", @@ -429,12 +536,21 @@ } } } - }, + } + ], + "description": "TestContractBalance.bad0() (tests/incorrect_equality.sol#32-35) uses a dangerous strict equality:\n\t- require(bool)(address(address(this)).balance == 10000000000000000000) (tests/incorrect_equality.sol#33)\n", + "markdown": "[TestContractBalance.bad0()](tests/incorrect_equality.sol#L32-L35) uses a dangerous strict equality:\n\t- [require(bool)(address(address(this)).balance == 10000000000000000000)](tests/incorrect_equality.sol#L33)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" + }, + { + "elements": [ { "type": "function", - "name": "bad0", + "name": "bad1", "source_mapping": { - "start": 648, + "start": 787, "length": 133, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", @@ -442,10 +558,10 @@ "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 32, - 33, - 34, - 35 + 37, + 38, + 39, + 40 ], "starting_column": 5, "ending_column": 6 @@ -536,17 +652,9 @@ "ending_column": 2 } }, - "signature": "bad0()" + "signature": "bad1()" } - } - ] - }, - { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "TestContractBalance.bad1() (tests/incorrect_equality.sol#37-40) uses a dangerous strict equality:\n\t- require(bool)(10000000000000000000 == address(address(this)).balance)\n", - "elements": [ + }, { "type": "node", "name": "require(bool)(10000000000000000000 == address(address(this)).balance)", @@ -675,23 +783,32 @@ } } } - }, + } + ], + "description": "TestContractBalance.bad1() (tests/incorrect_equality.sol#37-40) uses a dangerous strict equality:\n\t- require(bool)(10000000000000000000 == address(address(this)).balance) (tests/incorrect_equality.sol#38)\n", + "markdown": "[TestContractBalance.bad1()](tests/incorrect_equality.sol#L37-L40) uses a dangerous strict equality:\n\t- [require(bool)(10000000000000000000 == address(address(this)).balance)](tests/incorrect_equality.sol#L38)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" + }, + { + "elements": [ { "type": "function", - "name": "bad1", + "name": "bad2", "source_mapping": { - "start": 787, - "length": 133, + "start": 926, + "length": 124, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 37, - 38, - 39, - 40 + 42, + 43, + 44, + 45 ], "starting_column": 5, "ending_column": 6 @@ -782,17 +899,9 @@ "ending_column": 2 } }, - "signature": "bad1()" + "signature": "bad2()" } - } - ] - }, - { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "TestContractBalance.bad2() (tests/incorrect_equality.sol#42-45) uses a dangerous strict equality:\n\t- require(bool)(address(this).balance == 10000000000000000000)\n", - "elements": [ + }, { "type": "node", "name": "require(bool)(address(this).balance == 10000000000000000000)", @@ -921,12 +1030,21 @@ } } } - }, + } + ], + "description": "TestContractBalance.bad2() (tests/incorrect_equality.sol#42-45) uses a dangerous strict equality:\n\t- require(bool)(address(this).balance == 10000000000000000000) (tests/incorrect_equality.sol#43)\n", + "markdown": "[TestContractBalance.bad2()](tests/incorrect_equality.sol#L42-L45) uses a dangerous strict equality:\n\t- [require(bool)(address(this).balance == 10000000000000000000)](tests/incorrect_equality.sol#L43)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" + }, + { + "elements": [ { "type": "function", - "name": "bad2", + "name": "bad3", "source_mapping": { - "start": 926, + "start": 1056, "length": 124, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", @@ -934,10 +1052,10 @@ "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 42, - 43, - 44, - 45 + 47, + 48, + 49, + 50 ], "starting_column": 5, "ending_column": 6 @@ -1028,17 +1146,9 @@ "ending_column": 2 } }, - "signature": "bad2()" + "signature": "bad3()" } - } - ] - }, - { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "TestContractBalance.bad3() (tests/incorrect_equality.sol#47-50) uses a dangerous strict equality:\n\t- require(bool)(10000000000000000000 == address(this).balance)\n", - "elements": [ + }, { "type": "node", "name": "require(bool)(10000000000000000000 == address(this).balance)", @@ -1167,23 +1277,34 @@ } } } - }, + } + ], + "description": "TestContractBalance.bad3() (tests/incorrect_equality.sol#47-50) uses a dangerous strict equality:\n\t- require(bool)(10000000000000000000 == address(this).balance) (tests/incorrect_equality.sol#48)\n", + "markdown": "[TestContractBalance.bad3()](tests/incorrect_equality.sol#L47-L50) uses a dangerous strict equality:\n\t- [require(bool)(10000000000000000000 == address(this).balance)](tests/incorrect_equality.sol#L48)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" + }, + { + "elements": [ { "type": "function", - "name": "bad3", + "name": "bad4", "source_mapping": { - "start": 1056, - "length": 124, + "start": 1186, + "length": 170, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 47, - 48, - 49, - 50 + 52, + 53, + 54, + 55, + 56, + 57 ], "starting_column": 5, "ending_column": 6 @@ -1274,17 +1395,9 @@ "ending_column": 2 } }, - "signature": "bad3()" + "signature": "bad4()" } - } - ] - }, - { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "TestContractBalance.bad4() (tests/incorrect_equality.sol#52-57) uses a dangerous strict equality:\n\t- balance == 10000000000000000000\n", - "elements": [ + }, { "type": "node", "name": "balance == 10000000000000000000", @@ -1415,12 +1528,21 @@ } } } - }, + } + ], + "description": "TestContractBalance.bad4() (tests/incorrect_equality.sol#52-57) uses a dangerous strict equality:\n\t- balance == 10000000000000000000 (tests/incorrect_equality.sol#54)\n", + "markdown": "[TestContractBalance.bad4()](tests/incorrect_equality.sol#L52-L57) uses a dangerous strict equality:\n\t- [balance == 10000000000000000000](tests/incorrect_equality.sol#L54)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" + }, + { + "elements": [ { "type": "function", - "name": "bad4", + "name": "bad5", "source_mapping": { - "start": 1186, + "start": 1362, "length": 170, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", @@ -1428,12 +1550,12 @@ "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 52, - 53, - 54, - 55, - 56, - 57 + 59, + 60, + 61, + 62, + 63, + 64 ], "starting_column": 5, "ending_column": 6 @@ -1524,17 +1646,9 @@ "ending_column": 2 } }, - "signature": "bad4()" + "signature": "bad5()" } - } - ] - }, - { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "TestContractBalance.bad5() (tests/incorrect_equality.sol#59-64) uses a dangerous strict equality:\n\t- 10000000000000000000 == balance\n", - "elements": [ + }, { "type": "node", "name": "10000000000000000000 == balance", @@ -1665,25 +1779,34 @@ } } } - }, + } + ], + "description": "TestContractBalance.bad5() (tests/incorrect_equality.sol#59-64) uses a dangerous strict equality:\n\t- 10000000000000000000 == balance (tests/incorrect_equality.sol#61)\n", + "markdown": "[TestContractBalance.bad5()](tests/incorrect_equality.sol#L59-L64) uses a dangerous strict equality:\n\t- [10000000000000000000 == balance](tests/incorrect_equality.sol#L61)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" + }, + { + "elements": [ { "type": "function", - "name": "bad5", + "name": "bad6", "source_mapping": { - "start": 1362, - "length": 170, + "start": 1538, + "length": 179, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 59, - 60, - 61, - 62, - 63, - 64 + 66, + 67, + 68, + 69, + 70, + 71 ], "starting_column": 5, "ending_column": 6 @@ -1774,17 +1897,9 @@ "ending_column": 2 } }, - "signature": "bad5()" + "signature": "bad6()" } - } - ] - }, - { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "TestContractBalance.bad6() (tests/incorrect_equality.sol#66-71) uses a dangerous strict equality:\n\t- balance == 10000000000000000000\n", - "elements": [ + }, { "type": "node", "name": "balance == 10000000000000000000", @@ -1915,25 +2030,31 @@ } } } - }, + } + ], + "description": "TestContractBalance.bad6() (tests/incorrect_equality.sol#66-71) uses a dangerous strict equality:\n\t- balance == 10000000000000000000 (tests/incorrect_equality.sol#68)\n", + "markdown": "[TestContractBalance.bad6()](tests/incorrect_equality.sol#L66-L71) uses a dangerous strict equality:\n\t- [balance == 10000000000000000000](tests/incorrect_equality.sol#L68)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" + }, + { + "elements": [ { "type": "function", - "name": "bad6", + "name": "bad0", "source_mapping": { - "start": 1538, - "length": 179, + "start": 2935, + "length": 59, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 66, - 67, - 68, - 69, - 70, - 71 + 123, + 124, + 125 ], "starting_column": 5, "ending_column": 6 @@ -1941,100 +2062,61 @@ "type_specific_fields": { "parent": { "type": "contract", - "name": "TestContractBalance", + "name": "TestSolidityKeyword", "source_mapping": { - "start": 612, - "length": 1754, + "start": 2368, + "length": 774, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - 62, - 63, - 64, - 65, - 66, - 67, - 68, - 69, - 70, - 71, - 72, - 73, - 74, - 75, - 76, - 77, - 78, - 79, - 80, - 81, - 82, - 83, - 84, - 85, - 86, - 87, - 88, - 89, - 90, - 91, - 92, - 93, - 94, - 95, - 96, - 97 + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135 ], "starting_column": 1, "ending_column": 2 } }, - "signature": "bad6()" + "signature": "bad0()" } - } - ] - }, - { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "TestSolidityKeyword.bad0() (tests/incorrect_equality.sol#123-125) uses a dangerous strict equality:\n\t- require(bool)(now == 0)\n", - "elements": [ + }, { "type": "node", "name": "require(bool)(now == 0)", @@ -2131,22 +2213,31 @@ } } } - }, + } + ], + "description": "TestSolidityKeyword.bad0() (tests/incorrect_equality.sol#123-125) uses a dangerous strict equality:\n\t- require(bool)(now == 0) (tests/incorrect_equality.sol#124)\n", + "markdown": "[TestSolidityKeyword.bad0()](tests/incorrect_equality.sol#L123-L125) uses a dangerous strict equality:\n\t- [require(bool)(now == 0)](tests/incorrect_equality.sol#L124)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" + }, + { + "elements": [ { "type": "function", - "name": "bad0", + "name": "bad1", "source_mapping": { - "start": 2935, - "length": 59, + "start": 3000, + "length": 66, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 123, - 124, - 125 + 127, + 128, + 129 ], "starting_column": 5, "ending_column": 6 @@ -2206,17 +2297,9 @@ "ending_column": 2 } }, - "signature": "bad0()" + "signature": "bad1()" } - } - ] - }, - { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "TestSolidityKeyword.bad1() (tests/incorrect_equality.sol#127-129) uses a dangerous strict equality:\n\t- require(bool)(block.number == 0)\n", - "elements": [ + }, { "type": "node", "name": "require(bool)(block.number == 0)", @@ -2313,22 +2396,31 @@ } } } - }, + } + ], + "description": "TestSolidityKeyword.bad1() (tests/incorrect_equality.sol#127-129) uses a dangerous strict equality:\n\t- require(bool)(block.number == 0) (tests/incorrect_equality.sol#128)\n", + "markdown": "[TestSolidityKeyword.bad1()](tests/incorrect_equality.sol#L127-L129) uses a dangerous strict equality:\n\t- [require(bool)(block.number == 0)](tests/incorrect_equality.sol#L128)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" + }, + { + "elements": [ { "type": "function", - "name": "bad1", + "name": "bad2", "source_mapping": { - "start": 3000, - "length": 66, + "start": 3072, + "length": 67, "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_relative": "tests/incorrect_equality.sol", "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", "filename_short": "tests/incorrect_equality.sol", "is_dependency": false, "lines": [ - 127, - 128, - 129 + 131, + 132, + 133 ], "starting_column": 5, "ending_column": 6 @@ -2388,17 +2480,9 @@ "ending_column": 2 } }, - "signature": "bad1()" + "signature": "bad2()" } - } - ] - }, - { - "check": "incorrect-equality", - "impact": "Medium", - "confidence": "High", - "description": "TestSolidityKeyword.bad2() (tests/incorrect_equality.sol#131-133) uses a dangerous strict equality:\n\t- require(bool)(block.number == 0)\n", - "elements": [ + }, { "type": "node", "name": "require(bool)(block.number == 0)", @@ -2495,85 +2579,13 @@ } } } - }, - { - "type": "function", - "name": "bad2", - "source_mapping": { - "start": 3072, - "length": 67, - "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", - "filename_relative": "tests/incorrect_equality.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", - "filename_short": "tests/incorrect_equality.sol", - "is_dependency": false, - "lines": [ - 131, - 132, - 133 - ], - "starting_column": 5, - "ending_column": 6 - }, - "type_specific_fields": { - "parent": { - "type": "contract", - "name": "TestSolidityKeyword", - "source_mapping": { - "start": 2368, - "length": 774, - "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", - "filename_relative": "tests/incorrect_equality.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_equality.sol", - "filename_short": "tests/incorrect_equality.sol", - "is_dependency": false, - "lines": [ - 99, - 100, - 101, - 102, - 103, - 104, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112, - 113, - 114, - 115, - 116, - 117, - 118, - 119, - 120, - 121, - 122, - 123, - 124, - 125, - 126, - 127, - 128, - 129, - 130, - 131, - 132, - 133, - 134, - 135 - ], - "starting_column": 1, - "ending_column": 2 - } - }, - "signature": "bad2()" - } } - ] + ], + "description": "TestSolidityKeyword.bad2() (tests/incorrect_equality.sol#131-133) uses a dangerous strict equality:\n\t- require(bool)(block.number == 0) (tests/incorrect_equality.sol#132)\n", + "markdown": "[TestSolidityKeyword.bad2()](tests/incorrect_equality.sol#L131-L133) uses a dangerous strict equality:\n\t- [require(bool)(block.number == 0)](tests/incorrect_equality.sol#L132)\n", + "check": "incorrect-equality", + "impact": "Medium", + "confidence": "High" } ] } diff --git a/tests/expected_json/incorrect_equality.incorrect-equality.txt b/tests/expected_json/incorrect_equality.incorrect-equality.txt index afe5a41c4..fedb9a764 100644 --- a/tests/expected_json/incorrect_equality.incorrect-equality.txt +++ b/tests/expected_json/incorrect_equality.incorrect-equality.txt @@ -1,27 +1,27 @@ -INFO:Detectors: + ERC20TestBalance.bad0(ERC20Function) (tests/incorrect_equality.sol#21-23) uses a dangerous strict equality: - - require(bool)(erc.balanceOf(address(this)) == 10) + - require(bool)(erc.balanceOf(address(this)) == 10) (tests/incorrect_equality.sol#22) ERC20TestBalance.bad1(ERC20Variable) (tests/incorrect_equality.sol#25-27) uses a dangerous strict equality: - - require(bool)(erc.balanceOf(msg.sender) == 10) + - require(bool)(erc.balanceOf(msg.sender) == 10) (tests/incorrect_equality.sol#26) TestContractBalance.bad0() (tests/incorrect_equality.sol#32-35) uses a dangerous strict equality: - - require(bool)(address(address(this)).balance == 10000000000000000000) + - require(bool)(address(address(this)).balance == 10000000000000000000) (tests/incorrect_equality.sol#33) TestContractBalance.bad1() (tests/incorrect_equality.sol#37-40) uses a dangerous strict equality: - - require(bool)(10000000000000000000 == address(address(this)).balance) + - require(bool)(10000000000000000000 == address(address(this)).balance) (tests/incorrect_equality.sol#38) TestContractBalance.bad2() (tests/incorrect_equality.sol#42-45) uses a dangerous strict equality: - - require(bool)(address(this).balance == 10000000000000000000) + - require(bool)(address(this).balance == 10000000000000000000) (tests/incorrect_equality.sol#43) TestContractBalance.bad3() (tests/incorrect_equality.sol#47-50) uses a dangerous strict equality: - - require(bool)(10000000000000000000 == address(this).balance) + - require(bool)(10000000000000000000 == address(this).balance) (tests/incorrect_equality.sol#48) TestContractBalance.bad4() (tests/incorrect_equality.sol#52-57) uses a dangerous strict equality: - - balance == 10000000000000000000 + - balance == 10000000000000000000 (tests/incorrect_equality.sol#54) TestContractBalance.bad5() (tests/incorrect_equality.sol#59-64) uses a dangerous strict equality: - - 10000000000000000000 == balance + - 10000000000000000000 == balance (tests/incorrect_equality.sol#61) TestContractBalance.bad6() (tests/incorrect_equality.sol#66-71) uses a dangerous strict equality: - - balance == 10000000000000000000 + - balance == 10000000000000000000 (tests/incorrect_equality.sol#68) TestSolidityKeyword.bad0() (tests/incorrect_equality.sol#123-125) uses a dangerous strict equality: - - require(bool)(now == 0) + - require(bool)(now == 0) (tests/incorrect_equality.sol#124) TestSolidityKeyword.bad1() (tests/incorrect_equality.sol#127-129) uses a dangerous strict equality: - - require(bool)(block.number == 0) + - require(bool)(block.number == 0) (tests/incorrect_equality.sol#128) TestSolidityKeyword.bad2() (tests/incorrect_equality.sol#131-133) uses a dangerous strict equality: - - require(bool)(block.number == 0) + - require(bool)(block.number == 0) (tests/incorrect_equality.sol#132) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities -INFO:Slither:tests/incorrect_equality.sol analyzed (5 contracts), 12 result(s) found +tests/incorrect_equality.sol analyzed (5 contracts with 1 detectors), 12 result(s) found diff --git a/tests/expected_json/incorrect_erc20_interface.erc20-interface.json b/tests/expected_json/incorrect_erc20_interface.erc20-interface.json index c0b6c6b99..b5a9e0ef8 100644 --- a/tests/expected_json/incorrect_erc20_interface.erc20-interface.json +++ b/tests/expected_json/incorrect_erc20_interface.erc20-interface.json @@ -4,11 +4,32 @@ "results": { "detectors": [ { - "check": "erc20-interface", - "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transfer(address,uint256) (tests/incorrect_erc20_interface.sol#4)\n", "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 26, + "length": 355, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_relative": "tests/incorrect_erc20_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_short": "tests/incorrect_erc20_interface.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "transfer", @@ -55,14 +76,40 @@ "signature": "transfer(address,uint256)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.transfer(address,uint256) (tests/incorrect_erc20_interface.sol#4)\n", + "markdown": "[Token](tests/incorrect_erc20_interface.sol#L3-L10) has incorrect ERC20 function interface:[Token.transfer(address,uint256)](tests/incorrect_erc20_interface.sol#L4)\n", "check": "erc20-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: approve(address,uint256) (tests/incorrect_erc20_interface.sol#5)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 26, + "length": 355, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_relative": "tests/incorrect_erc20_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_short": "tests/incorrect_erc20_interface.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "approve", @@ -109,14 +156,40 @@ "signature": "approve(address,uint256)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.approve(address,uint256) (tests/incorrect_erc20_interface.sol#5)\n", + "markdown": "[Token](tests/incorrect_erc20_interface.sol#L3-L10) has incorrect ERC20 function interface:[Token.approve(address,uint256)](tests/incorrect_erc20_interface.sol#L5)\n", "check": "erc20-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transferFrom(address,address,uint256) (tests/incorrect_erc20_interface.sol#6)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 26, + "length": 355, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_relative": "tests/incorrect_erc20_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_short": "tests/incorrect_erc20_interface.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "transferFrom", @@ -163,14 +236,40 @@ "signature": "transferFrom(address,address,uint256)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.transferFrom(address,address,uint256) (tests/incorrect_erc20_interface.sol#6)\n", + "markdown": "[Token](tests/incorrect_erc20_interface.sol#L3-L10) has incorrect ERC20 function interface:[Token.transferFrom(address,address,uint256)](tests/incorrect_erc20_interface.sol#L6)\n", "check": "erc20-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: totalSupply() (tests/incorrect_erc20_interface.sol#7)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 26, + "length": 355, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_relative": "tests/incorrect_erc20_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_short": "tests/incorrect_erc20_interface.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "totalSupply", @@ -217,14 +316,40 @@ "signature": "totalSupply()" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.totalSupply() (tests/incorrect_erc20_interface.sol#7)\n", + "markdown": "[Token](tests/incorrect_erc20_interface.sol#L3-L10) has incorrect ERC20 function interface:[Token.totalSupply()](tests/incorrect_erc20_interface.sol#L7)\n", "check": "erc20-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: balanceOf(address) (tests/incorrect_erc20_interface.sol#8)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 26, + "length": 355, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_relative": "tests/incorrect_erc20_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_short": "tests/incorrect_erc20_interface.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "balanceOf", @@ -271,14 +396,40 @@ "signature": "balanceOf(address)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.balanceOf(address) (tests/incorrect_erc20_interface.sol#8)\n", + "markdown": "[Token](tests/incorrect_erc20_interface.sol#L3-L10) has incorrect ERC20 function interface:[Token.balanceOf(address)](tests/incorrect_erc20_interface.sol#L8)\n", "check": "erc20-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: allowance(address,address) (tests/incorrect_erc20_interface.sol#9)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 26, + "length": 355, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_relative": "tests/incorrect_erc20_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc20_interface.sol", + "filename_short": "tests/incorrect_erc20_interface.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "allowance", @@ -325,7 +476,12 @@ "signature": "allowance(address,address)" } } - ] + ], + "description": "Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.allowance(address,address) (tests/incorrect_erc20_interface.sol#9)\n", + "markdown": "[Token](tests/incorrect_erc20_interface.sol#L3-L10) has incorrect ERC20 function interface:[Token.allowance(address,address)](tests/incorrect_erc20_interface.sol#L9)\n", + "check": "erc20-interface", + "impact": "Medium", + "confidence": "High" } ] } diff --git a/tests/expected_json/incorrect_erc20_interface.erc20-interface.txt b/tests/expected_json/incorrect_erc20_interface.erc20-interface.txt index 75b71be01..24bcc5276 100644 --- a/tests/expected_json/incorrect_erc20_interface.erc20-interface.txt +++ b/tests/expected_json/incorrect_erc20_interface.erc20-interface.txt @@ -1,9 +1,9 @@ -INFO:Detectors: -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transfer(address,uint256) (tests/incorrect_erc20_interface.sol#4) -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: approve(address,uint256) (tests/incorrect_erc20_interface.sol#5) -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: transferFrom(address,address,uint256) (tests/incorrect_erc20_interface.sol#6) -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: totalSupply() (tests/incorrect_erc20_interface.sol#7) -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: balanceOf(address) (tests/incorrect_erc20_interface.sol#8) -Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface: allowance(address,address) (tests/incorrect_erc20_interface.sol#9) + +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.transfer(address,uint256) (tests/incorrect_erc20_interface.sol#4) +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.approve(address,uint256) (tests/incorrect_erc20_interface.sol#5) +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.transferFrom(address,address,uint256) (tests/incorrect_erc20_interface.sol#6) +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.totalSupply() (tests/incorrect_erc20_interface.sol#7) +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.balanceOf(address) (tests/incorrect_erc20_interface.sol#8) +Token (tests/incorrect_erc20_interface.sol#3-10) has incorrect ERC20 function interface:Token.allowance(address,address) (tests/incorrect_erc20_interface.sol#9) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface -INFO:Slither:tests/incorrect_erc20_interface.sol analyzed (1 contracts), 6 result(s) found +tests/incorrect_erc20_interface.sol analyzed (1 contracts with 1 detectors), 6 result(s) found diff --git a/tests/expected_json/incorrect_erc721_interface.erc721-interface.json b/tests/expected_json/incorrect_erc721_interface.erc721-interface.json index 528be3fc0..1bc67621f 100644 --- a/tests/expected_json/incorrect_erc721_interface.erc721-interface.json +++ b/tests/expected_json/incorrect_erc721_interface.erc721-interface.json @@ -4,11 +4,35 @@ "results": { "detectors": [ { - "check": "erc721-interface", - "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: supportsInterface(bytes4) (tests/incorrect_erc721_interface.sol#4)\n", "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 109, + "length": 739, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_relative": "tests/incorrect_erc721_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_short": "tests/incorrect_erc721_interface.sol", + "is_dependency": false, + "lines": [ + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "supportsInterface", @@ -50,14 +74,43 @@ "signature": "supportsInterface(bytes4)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:IERC165.supportsInterface(bytes4) (tests/incorrect_erc721_interface.sol#4)\n", + "markdown": "[Token](tests/incorrect_erc721_interface.sol#L6-L16) has incorrect ERC721 function interface:[IERC165.supportsInterface(bytes4)](tests/incorrect_erc721_interface.sol#L4)\n", "check": "erc721-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: balanceOf(address) (tests/incorrect_erc721_interface.sol#7)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 109, + "length": 739, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_relative": "tests/incorrect_erc721_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_short": "tests/incorrect_erc721_interface.sol", + "is_dependency": false, + "lines": [ + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "balanceOf", @@ -107,14 +160,43 @@ "signature": "balanceOf(address)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.balanceOf(address) (tests/incorrect_erc721_interface.sol#7)\n", + "markdown": "[Token](tests/incorrect_erc721_interface.sol#L6-L16) has incorrect ERC721 function interface:[Token.balanceOf(address)](tests/incorrect_erc721_interface.sol#L7)\n", "check": "erc721-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: ownerOf(uint256) (tests/incorrect_erc721_interface.sol#8)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 109, + "length": 739, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_relative": "tests/incorrect_erc721_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_short": "tests/incorrect_erc721_interface.sol", + "is_dependency": false, + "lines": [ + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "ownerOf", @@ -164,14 +246,43 @@ "signature": "ownerOf(uint256)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.ownerOf(uint256) (tests/incorrect_erc721_interface.sol#8)\n", + "markdown": "[Token](tests/incorrect_erc721_interface.sol#L6-L16) has incorrect ERC721 function interface:[Token.ownerOf(uint256)](tests/incorrect_erc721_interface.sol#L8)\n", "check": "erc721-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom(address,address,uint256,bytes) (tests/incorrect_erc721_interface.sol#9)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 109, + "length": 739, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_relative": "tests/incorrect_erc721_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_short": "tests/incorrect_erc721_interface.sol", + "is_dependency": false, + "lines": [ + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "safeTransferFrom", @@ -221,14 +332,43 @@ "signature": "safeTransferFrom(address,address,uint256,bytes)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.safeTransferFrom(address,address,uint256,bytes) (tests/incorrect_erc721_interface.sol#9)\n", + "markdown": "[Token](tests/incorrect_erc721_interface.sol#L6-L16) has incorrect ERC721 function interface:[Token.safeTransferFrom(address,address,uint256,bytes)](tests/incorrect_erc721_interface.sol#L9)\n", "check": "erc721-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#10)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 109, + "length": 739, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_relative": "tests/incorrect_erc721_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_short": "tests/incorrect_erc721_interface.sol", + "is_dependency": false, + "lines": [ + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "safeTransferFrom", @@ -278,14 +418,43 @@ "signature": "safeTransferFrom(address,address,uint256)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.safeTransferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#10)\n", + "markdown": "[Token](tests/incorrect_erc721_interface.sol#L6-L16) has incorrect ERC721 function interface:[Token.safeTransferFrom(address,address,uint256)](tests/incorrect_erc721_interface.sol#L10)\n", "check": "erc721-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: transferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#11)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 109, + "length": 739, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_relative": "tests/incorrect_erc721_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_short": "tests/incorrect_erc721_interface.sol", + "is_dependency": false, + "lines": [ + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "transferFrom", @@ -335,14 +504,43 @@ "signature": "transferFrom(address,address,uint256)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.transferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#11)\n", + "markdown": "[Token](tests/incorrect_erc721_interface.sol#L6-L16) has incorrect ERC721 function interface:[Token.transferFrom(address,address,uint256)](tests/incorrect_erc721_interface.sol#L11)\n", "check": "erc721-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: approve(address,uint256) (tests/incorrect_erc721_interface.sol#12)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 109, + "length": 739, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_relative": "tests/incorrect_erc721_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_short": "tests/incorrect_erc721_interface.sol", + "is_dependency": false, + "lines": [ + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "approve", @@ -392,14 +590,43 @@ "signature": "approve(address,uint256)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.approve(address,uint256) (tests/incorrect_erc721_interface.sol#12)\n", + "markdown": "[Token](tests/incorrect_erc721_interface.sol#L6-L16) has incorrect ERC721 function interface:[Token.approve(address,uint256)](tests/incorrect_erc721_interface.sol#L12)\n", "check": "erc721-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: setApprovalForAll(address,bool) (tests/incorrect_erc721_interface.sol#13)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 109, + "length": 739, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_relative": "tests/incorrect_erc721_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_short": "tests/incorrect_erc721_interface.sol", + "is_dependency": false, + "lines": [ + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "setApprovalForAll", @@ -449,14 +676,43 @@ "signature": "setApprovalForAll(address,bool)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.setApprovalForAll(address,bool) (tests/incorrect_erc721_interface.sol#13)\n", + "markdown": "[Token](tests/incorrect_erc721_interface.sol#L6-L16) has incorrect ERC721 function interface:[Token.setApprovalForAll(address,bool)](tests/incorrect_erc721_interface.sol#L13)\n", "check": "erc721-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: getApproved(uint256) (tests/incorrect_erc721_interface.sol#14)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 109, + "length": 739, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_relative": "tests/incorrect_erc721_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_short": "tests/incorrect_erc721_interface.sol", + "is_dependency": false, + "lines": [ + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "getApproved", @@ -506,14 +762,43 @@ "signature": "getApproved(uint256)" } } - ] - }, - { + ], + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.getApproved(uint256) (tests/incorrect_erc721_interface.sol#14)\n", + "markdown": "[Token](tests/incorrect_erc721_interface.sol#L6-L16) has incorrect ERC721 function interface:[Token.getApproved(uint256)](tests/incorrect_erc721_interface.sol#L14)\n", "check": "erc721-interface", "impact": "Medium", - "confidence": "High", - "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: isApprovedForAll(address,address) (tests/incorrect_erc721_interface.sol#15)\n", + "confidence": "High" + }, + { "elements": [ + { + "type": "contract", + "name": "Token", + "source_mapping": { + "start": 109, + "length": 739, + "filename_used": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_relative": "tests/incorrect_erc721_interface.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/incorrect_erc721_interface.sol", + "filename_short": "tests/incorrect_erc721_interface.sol", + "is_dependency": false, + "lines": [ + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16 + ], + "starting_column": 1, + "ending_column": 2 + } + }, { "type": "function", "name": "isApprovedForAll", @@ -563,7 +848,12 @@ "signature": "isApprovedForAll(address,address)" } } - ] + ], + "description": "Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.isApprovedForAll(address,address) (tests/incorrect_erc721_interface.sol#15)\n", + "markdown": "[Token](tests/incorrect_erc721_interface.sol#L6-L16) has incorrect ERC721 function interface:[Token.isApprovedForAll(address,address)](tests/incorrect_erc721_interface.sol#L15)\n", + "check": "erc721-interface", + "impact": "Medium", + "confidence": "High" } ] } diff --git a/tests/expected_json/incorrect_erc721_interface.erc721-interface.txt b/tests/expected_json/incorrect_erc721_interface.erc721-interface.txt index cfd388267..4a82240e2 100644 --- a/tests/expected_json/incorrect_erc721_interface.erc721-interface.txt +++ b/tests/expected_json/incorrect_erc721_interface.erc721-interface.txt @@ -1,13 +1,13 @@ -INFO:Detectors: -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: supportsInterface(bytes4) (tests/incorrect_erc721_interface.sol#4) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: balanceOf(address) (tests/incorrect_erc721_interface.sol#7) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: ownerOf(uint256) (tests/incorrect_erc721_interface.sol#8) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom(address,address,uint256,bytes) (tests/incorrect_erc721_interface.sol#9) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: safeTransferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#10) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: transferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#11) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: approve(address,uint256) (tests/incorrect_erc721_interface.sol#12) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: setApprovalForAll(address,bool) (tests/incorrect_erc721_interface.sol#13) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: getApproved(uint256) (tests/incorrect_erc721_interface.sol#14) -Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface: isApprovedForAll(address,address) (tests/incorrect_erc721_interface.sol#15) + +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:IERC165.supportsInterface(bytes4) (tests/incorrect_erc721_interface.sol#4) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.balanceOf(address) (tests/incorrect_erc721_interface.sol#7) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.ownerOf(uint256) (tests/incorrect_erc721_interface.sol#8) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.safeTransferFrom(address,address,uint256,bytes) (tests/incorrect_erc721_interface.sol#9) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.safeTransferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#10) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.transferFrom(address,address,uint256) (tests/incorrect_erc721_interface.sol#11) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.approve(address,uint256) (tests/incorrect_erc721_interface.sol#12) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.setApprovalForAll(address,bool) (tests/incorrect_erc721_interface.sol#13) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.getApproved(uint256) (tests/incorrect_erc721_interface.sol#14) +Token (tests/incorrect_erc721_interface.sol#6-16) has incorrect ERC721 function interface:Token.isApprovedForAll(address,address) (tests/incorrect_erc721_interface.sol#15) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface -INFO:Slither:tests/incorrect_erc721_interface.sol analyzed (2 contracts), 10 result(s) found +tests/incorrect_erc721_interface.sol analyzed (2 contracts with 1 detectors), 10 result(s) found diff --git a/tests/expected_json/inline_assembly_contract-0.5.1.assembly.json b/tests/expected_json/inline_assembly_contract-0.5.1.assembly.json index 24790e712..8ec3e0312 100644 --- a/tests/expected_json/inline_assembly_contract-0.5.1.assembly.json +++ b/tests/expected_json/inline_assembly_contract-0.5.1.assembly.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "assembly", - "impact": "Informational", - "confidence": "High", - "description": "GetCode.at(address) uses assembly (tests/inline_assembly_contract-0.5.1.sol#6-20)\n\t- tests/inline_assembly_contract-0.5.1.sol#7-20\n", "elements": [ { "type": "function", @@ -180,7 +176,12 @@ } } } - ] + ], + "description": "GetCode.at(address) (tests/inline_assembly_contract-0.5.1.sol#6-20) uses assembly\n\t- INLINE ASM None (tests/inline_assembly_contract-0.5.1.sol#7-20)\n", + "markdown": "[GetCode.at(address)](tests/inline_assembly_contract-0.5.1.sol#L6-L20) uses assembly\n\t- [INLINE ASM None](tests/inline_assembly_contract-0.5.1.sol#L7-L20)\n", + "check": "assembly", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/inline_assembly_contract-0.5.1.assembly.txt b/tests/expected_json/inline_assembly_contract-0.5.1.assembly.txt index f832cfe46..3fe0a4672 100644 --- a/tests/expected_json/inline_assembly_contract-0.5.1.assembly.txt +++ b/tests/expected_json/inline_assembly_contract-0.5.1.assembly.txt @@ -1,5 +1,5 @@ -INFO:Detectors: -GetCode.at(address) uses assembly (tests/inline_assembly_contract-0.5.1.sol#6-20) - - tests/inline_assembly_contract-0.5.1.sol#7-20 + +GetCode.at(address) (tests/inline_assembly_contract-0.5.1.sol#6-20) uses assembly + - INLINE ASM None (tests/inline_assembly_contract-0.5.1.sol#7-20) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage -INFO:Slither:tests/inline_assembly_contract-0.5.1.sol analyzed (1 contracts), 1 result(s) found +tests/inline_assembly_contract-0.5.1.sol analyzed (1 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/inline_assembly_contract.assembly.json b/tests/expected_json/inline_assembly_contract.assembly.json index 75e439a7e..841fb9aa3 100644 --- a/tests/expected_json/inline_assembly_contract.assembly.json +++ b/tests/expected_json/inline_assembly_contract.assembly.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "assembly", - "impact": "Informational", - "confidence": "High", - "description": "GetCode.at(address) uses assembly (tests/inline_assembly_contract.sol#6-20)\n\t- tests/inline_assembly_contract.sol#7-20\n", "elements": [ { "type": "function", @@ -180,7 +176,12 @@ } } } - ] + ], + "description": "GetCode.at(address) (tests/inline_assembly_contract.sol#6-20) uses assembly\n\t- INLINE ASM None (tests/inline_assembly_contract.sol#7-20)\n", + "markdown": "[GetCode.at(address)](tests/inline_assembly_contract.sol#L6-L20) uses assembly\n\t- [INLINE ASM None](tests/inline_assembly_contract.sol#L7-L20)\n", + "check": "assembly", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/inline_assembly_contract.assembly.txt b/tests/expected_json/inline_assembly_contract.assembly.txt index 78c4fa50c..63450506c 100644 --- a/tests/expected_json/inline_assembly_contract.assembly.txt +++ b/tests/expected_json/inline_assembly_contract.assembly.txt @@ -1,5 +1,5 @@ -INFO:Detectors: -GetCode.at(address) uses assembly (tests/inline_assembly_contract.sol#6-20) - - tests/inline_assembly_contract.sol#7-20 + +GetCode.at(address) (tests/inline_assembly_contract.sol#6-20) uses assembly + - INLINE ASM None (tests/inline_assembly_contract.sol#7-20) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage -INFO:Slither:tests/inline_assembly_contract.sol analyzed (1 contracts), 1 result(s) found +tests/inline_assembly_contract.sol analyzed (1 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/inline_assembly_library-0.5.1.assembly.json b/tests/expected_json/inline_assembly_library-0.5.1.assembly.json index bd9b4d97f..f027b15b9 100644 --- a/tests/expected_json/inline_assembly_library-0.5.1.assembly.json +++ b/tests/expected_json/inline_assembly_library-0.5.1.assembly.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "assembly", - "impact": "Informational", - "confidence": "High", - "description": "VectorSum.sumAsm(uint256[]) uses assembly (tests/inline_assembly_library-0.5.1.sol#16-22)\n\t- tests/inline_assembly_library-0.5.1.sol#18-21\n", "elements": [ { "type": "function", @@ -208,13 +204,14 @@ } } } - ] - }, - { + ], + "description": "VectorSum.sumAsm(uint256[]) (tests/inline_assembly_library-0.5.1.sol#16-22) uses assembly\n\t- INLINE ASM None (tests/inline_assembly_library-0.5.1.sol#18-21)\n", + "markdown": "[VectorSum.sumAsm(uint256[])](tests/inline_assembly_library-0.5.1.sol#L16-L22) uses assembly\n\t- [INLINE ASM None](tests/inline_assembly_library-0.5.1.sol#L18-L21)\n", "check": "assembly", "impact": "Informational", - "confidence": "High", - "description": "VectorSum.sumPureAsm(uint256[]) uses assembly (tests/inline_assembly_library-0.5.1.sol#25-47)\n\t- tests/inline_assembly_library-0.5.1.sol#26-47\n", + "confidence": "High" + }, + { "elements": [ { "type": "function", @@ -465,7 +462,12 @@ } } } - ] + ], + "description": "VectorSum.sumPureAsm(uint256[]) (tests/inline_assembly_library-0.5.1.sol#25-47) uses assembly\n\t- INLINE ASM None (tests/inline_assembly_library-0.5.1.sol#26-47)\n", + "markdown": "[VectorSum.sumPureAsm(uint256[])](tests/inline_assembly_library-0.5.1.sol#L25-L47) uses assembly\n\t- [INLINE ASM None](tests/inline_assembly_library-0.5.1.sol#L26-L47)\n", + "check": "assembly", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/inline_assembly_library-0.5.1.assembly.txt b/tests/expected_json/inline_assembly_library-0.5.1.assembly.txt index 5624ad2cf..ce08b243b 100644 --- a/tests/expected_json/inline_assembly_library-0.5.1.assembly.txt +++ b/tests/expected_json/inline_assembly_library-0.5.1.assembly.txt @@ -1,7 +1,7 @@ -INFO:Detectors: -VectorSum.sumAsm(uint256[]) uses assembly (tests/inline_assembly_library-0.5.1.sol#16-22) - - tests/inline_assembly_library-0.5.1.sol#18-21 -VectorSum.sumPureAsm(uint256[]) uses assembly (tests/inline_assembly_library-0.5.1.sol#25-47) - - tests/inline_assembly_library-0.5.1.sol#26-47 + +VectorSum.sumAsm(uint256[]) (tests/inline_assembly_library-0.5.1.sol#16-22) uses assembly + - INLINE ASM None (tests/inline_assembly_library-0.5.1.sol#18-21) +VectorSum.sumPureAsm(uint256[]) (tests/inline_assembly_library-0.5.1.sol#25-47) uses assembly + - INLINE ASM None (tests/inline_assembly_library-0.5.1.sol#26-47) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage -INFO:Slither:tests/inline_assembly_library-0.5.1.sol analyzed (1 contracts), 2 result(s) found +tests/inline_assembly_library-0.5.1.sol analyzed (1 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/inline_assembly_library.assembly.json b/tests/expected_json/inline_assembly_library.assembly.json index 5c1230028..d3e3642b8 100644 --- a/tests/expected_json/inline_assembly_library.assembly.json +++ b/tests/expected_json/inline_assembly_library.assembly.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "assembly", - "impact": "Informational", - "confidence": "High", - "description": "VectorSum.sumAsm(uint256[]) uses assembly (tests/inline_assembly_library.sol#16-22)\n\t- tests/inline_assembly_library.sol#18-21\n", "elements": [ { "type": "function", @@ -208,13 +204,14 @@ } } } - ] - }, - { + ], + "description": "VectorSum.sumAsm(uint256[]) (tests/inline_assembly_library.sol#16-22) uses assembly\n\t- INLINE ASM None (tests/inline_assembly_library.sol#18-21)\n", + "markdown": "[VectorSum.sumAsm(uint256[])](tests/inline_assembly_library.sol#L16-L22) uses assembly\n\t- [INLINE ASM None](tests/inline_assembly_library.sol#L18-L21)\n", "check": "assembly", "impact": "Informational", - "confidence": "High", - "description": "VectorSum.sumPureAsm(uint256[]) uses assembly (tests/inline_assembly_library.sol#25-47)\n\t- tests/inline_assembly_library.sol#26-47\n", + "confidence": "High" + }, + { "elements": [ { "type": "function", @@ -465,7 +462,12 @@ } } } - ] + ], + "description": "VectorSum.sumPureAsm(uint256[]) (tests/inline_assembly_library.sol#25-47) uses assembly\n\t- INLINE ASM None (tests/inline_assembly_library.sol#26-47)\n", + "markdown": "[VectorSum.sumPureAsm(uint256[])](tests/inline_assembly_library.sol#L25-L47) uses assembly\n\t- [INLINE ASM None](tests/inline_assembly_library.sol#L26-L47)\n", + "check": "assembly", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/inline_assembly_library.assembly.txt b/tests/expected_json/inline_assembly_library.assembly.txt index 8bc566c04..2700f394b 100644 --- a/tests/expected_json/inline_assembly_library.assembly.txt +++ b/tests/expected_json/inline_assembly_library.assembly.txt @@ -1,7 +1,7 @@ -INFO:Detectors: -VectorSum.sumAsm(uint256[]) uses assembly (tests/inline_assembly_library.sol#16-22) - - tests/inline_assembly_library.sol#18-21 -VectorSum.sumPureAsm(uint256[]) uses assembly (tests/inline_assembly_library.sol#25-47) - - tests/inline_assembly_library.sol#26-47 + +VectorSum.sumAsm(uint256[]) (tests/inline_assembly_library.sol#16-22) uses assembly + - INLINE ASM None (tests/inline_assembly_library.sol#18-21) +VectorSum.sumPureAsm(uint256[]) (tests/inline_assembly_library.sol#25-47) uses assembly + - INLINE ASM None (tests/inline_assembly_library.sol#26-47) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage -INFO:Slither:tests/inline_assembly_library.sol analyzed (1 contracts), 2 result(s) found +tests/inline_assembly_library.sol analyzed (1 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/locked_ether-0.5.1.locked-ether.json b/tests/expected_json/locked_ether-0.5.1.locked-ether.json index d848114fd..3d7238e5b 100644 --- a/tests/expected_json/locked_ether-0.5.1.locked-ether.json +++ b/tests/expected_json/locked_ether-0.5.1.locked-ether.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "locked-ether", - "impact": "Medium", - "confidence": "High", - "description": "Contract locking ether found in :\n\tContract OnlyLocked has payable functions:\n\t - receive (tests/locked_ether-0.5.1.sol#4-6)\n\tBut does not have a function to withdraw the ether\n", "elements": [ { "type": "contract", @@ -74,7 +70,12 @@ "signature": "receive()" } } - ] + ], + "description": "Contract locking ether found in :\n\tContract OnlyLocked (tests/locked_ether-0.5.1.sol#26) has payable functions:\n\t - Locked.receive() (tests/locked_ether-0.5.1.sol#4-6)\n\tBut does not have a function to withdraw the ether\n", + "markdown": "Contract locking ether found in :\n\tContract [OnlyLocked](tests/locked_ether-0.5.1.sol#L26) has payable functions:\n\t - [Locked.receive()](tests/locked_ether-0.5.1.sol#L4-L6)\n\tBut does not have a function to withdraw the ether\n", + "check": "locked-ether", + "impact": "Medium", + "confidence": "High" } ] } diff --git a/tests/expected_json/locked_ether-0.5.1.locked-ether.txt b/tests/expected_json/locked_ether-0.5.1.locked-ether.txt index 1d0fa6d3b..932326656 100644 --- a/tests/expected_json/locked_ether-0.5.1.locked-ether.txt +++ b/tests/expected_json/locked_ether-0.5.1.locked-ether.txt @@ -1,7 +1,7 @@ -INFO:Detectors: + Contract locking ether found in : - Contract OnlyLocked has payable functions: - - receive (tests/locked_ether-0.5.1.sol#4-6) + Contract OnlyLocked (tests/locked_ether-0.5.1.sol#26) has payable functions: + - Locked.receive() (tests/locked_ether-0.5.1.sol#4-6) But does not have a function to withdraw the ether Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether -INFO:Slither:tests/locked_ether-0.5.1.sol analyzed (4 contracts), 1 result(s) found +tests/locked_ether-0.5.1.sol analyzed (4 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/locked_ether.locked-ether.json b/tests/expected_json/locked_ether.locked-ether.json index 1daa8631b..765e4103e 100644 --- a/tests/expected_json/locked_ether.locked-ether.json +++ b/tests/expected_json/locked_ether.locked-ether.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "locked-ether", - "impact": "Medium", - "confidence": "High", - "description": "Contract locking ether found in :\n\tContract OnlyLocked has payable functions:\n\t - receive (tests/locked_ether.sol#4-6)\n\tBut does not have a function to withdraw the ether\n", "elements": [ { "type": "contract", @@ -74,7 +70,12 @@ "signature": "receive()" } } - ] + ], + "description": "Contract locking ether found in :\n\tContract OnlyLocked (tests/locked_ether.sol#26) has payable functions:\n\t - Locked.receive() (tests/locked_ether.sol#4-6)\n\tBut does not have a function to withdraw the ether\n", + "markdown": "Contract locking ether found in :\n\tContract [OnlyLocked](tests/locked_ether.sol#L26) has payable functions:\n\t - [Locked.receive()](tests/locked_ether.sol#L4-L6)\n\tBut does not have a function to withdraw the ether\n", + "check": "locked-ether", + "impact": "Medium", + "confidence": "High" } ] } diff --git a/tests/expected_json/locked_ether.locked-ether.txt b/tests/expected_json/locked_ether.locked-ether.txt index a27ff383b..304347703 100644 --- a/tests/expected_json/locked_ether.locked-ether.txt +++ b/tests/expected_json/locked_ether.locked-ether.txt @@ -1,7 +1,7 @@ -INFO:Detectors: + Contract locking ether found in : - Contract OnlyLocked has payable functions: - - receive (tests/locked_ether.sol#4-6) + Contract OnlyLocked (tests/locked_ether.sol#26) has payable functions: + - Locked.receive() (tests/locked_ether.sol#4-6) But does not have a function to withdraw the ether Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether -INFO:Slither:tests/locked_ether.sol analyzed (4 contracts), 1 result(s) found +tests/locked_ether.sol analyzed (4 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/low_level_calls.low-level-calls.json b/tests/expected_json/low_level_calls.low-level-calls.json index 71a20c4fe..f3dd0cf61 100644 --- a/tests/expected_json/low_level_calls.low-level-calls.json +++ b/tests/expected_json/low_level_calls.low-level-calls.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "low-level-calls", - "impact": "Informational", - "confidence": "High", - "description": "Low level call in Sender.send(address) (tests/low_level_calls.sol#5-7):\n\t-_receiver.call.value(msg.value).gas(7777)() tests/low_level_calls.sol#6\n", "elements": [ { "type": "function", @@ -119,7 +115,12 @@ } } } - ] + ], + "description": "Low level call in Sender.send(address) (tests/low_level_calls.sol#5-7):\n\t- _receiver.call.value(msg.value).gas(7777)() (tests/low_level_calls.sol#6)\n", + "markdown": "Low level call in [Sender.send(address)](tests/low_level_calls.sol#L5-L7):\n\t- [_receiver.call.value(msg.value).gas(7777)()](tests/low_level_calls.sol#L6)\n", + "check": "low-level-calls", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/low_level_calls.low-level-calls.txt b/tests/expected_json/low_level_calls.low-level-calls.txt index db7034d4a..ab94fa3e0 100644 --- a/tests/expected_json/low_level_calls.low-level-calls.txt +++ b/tests/expected_json/low_level_calls.low-level-calls.txt @@ -1,5 +1,5 @@ -INFO:Detectors: + Low level call in Sender.send(address) (tests/low_level_calls.sol#5-7): - -_receiver.call.value(msg.value).gas(7777)() tests/low_level_calls.sol#6 + - _receiver.call.value(msg.value).gas(7777)() (tests/low_level_calls.sol#6) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls -INFO:Slither:tests/low_level_calls.sol analyzed (2 contracts), 1 result(s) found +tests/low_level_calls.sol analyzed (2 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/multiple_calls_in_loop.calls-loop.json b/tests/expected_json/multiple_calls_in_loop.calls-loop.json index d08dfb95d..f54be581b 100644 --- a/tests/expected_json/multiple_calls_in_loop.calls-loop.json +++ b/tests/expected_json/multiple_calls_in_loop.calls-loop.json @@ -4,11 +4,64 @@ "results": { "detectors": [ { - "check": "calls-loop", - "impact": "Low", - "confidence": "Medium", - "description": "CallInLoop.bad() has external calls inside a loop: \"destinations[i].transfer(i)\" (tests/multiple_calls_in_loop.sol#11)\n", "elements": [ + { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 153, + "length": 135, + "filename_used": "/home/travis/build/crytic/slither/tests/multiple_calls_in_loop.sol", + "filename_relative": "tests/multiple_calls_in_loop.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/multiple_calls_in_loop.sol", + "filename_short": "tests/multiple_calls_in_loop.sol", + "is_dependency": false, + "lines": [ + 9, + 10, + 11, + 12, + 13 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "CallInLoop", + "source_mapping": { + "start": 0, + "length": 291, + "filename_used": "/home/travis/build/crytic/slither/tests/multiple_calls_in_loop.sol", + "filename_relative": "tests/multiple_calls_in_loop.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/multiple_calls_in_loop.sol", + "filename_short": "tests/multiple_calls_in_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "bad()" + } + }, { "type": "node", "name": "destinations[i].transfer(i)", @@ -86,7 +139,12 @@ } } } - ] + ], + "description": "CallInLoop.bad() (tests/multiple_calls_in_loop.sol#9-13) has external calls inside a loop: destinations[i].transfer(i) (tests/multiple_calls_in_loop.sol#11)\n", + "markdown": "[CallInLoop.bad()](tests/multiple_calls_in_loop.sol#L9-L13) has external calls inside a loop: [destinations[i].transfer(i)](tests/multiple_calls_in_loop.sol#L11)\n", + "check": "calls-loop", + "impact": "Low", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/multiple_calls_in_loop.calls-loop.txt b/tests/expected_json/multiple_calls_in_loop.calls-loop.txt index 7803df6de..1114957d7 100644 --- a/tests/expected_json/multiple_calls_in_loop.calls-loop.txt +++ b/tests/expected_json/multiple_calls_in_loop.calls-loop.txt @@ -1,4 +1,4 @@ -INFO:Detectors: -CallInLoop.bad() has external calls inside a loop: "destinations[i].transfer(i)" (tests/multiple_calls_in_loop.sol#11) -Reference: https://github.com/crytic/slither/wiki/Detector-Documentation/_edit#calls-inside-a-loop -INFO:Slither:tests/multiple_calls_in_loop.sol analyzed (1 contracts), 1 result(s) found + +CallInLoop.bad() (tests/multiple_calls_in_loop.sol#9-13) has external calls inside a loop: destinations[i].transfer(i) (tests/multiple_calls_in_loop.sol#11) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop +tests/multiple_calls_in_loop.sol analyzed (1 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/naming_convention.naming-convention.json b/tests/expected_json/naming_convention.naming-convention.json index 794250fcc..b71a64845 100644 --- a/tests/expected_json/naming_convention.naming-convention.json +++ b/tests/expected_json/naming_convention.naming-convention.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "naming-convention", - "impact": "Informational", - "confidence": "High", - "description": "Contract 'naming' (tests/naming_convention.sol#3-48) is not in CapWords\n", "elements": [ { "type": "contract", @@ -76,13 +72,14 @@ "convention": "CapWords" } } - ] - }, - { + ], + "description": "Contract naming (tests/naming_convention.sol#3-48) is not in CapWords\n", + "markdown": "Contract [naming](tests/naming_convention.sol#L3-L48) is not in CapWords\n", "check": "naming-convention", "impact": "Informational", - "confidence": "High", - "description": "Struct 'naming.test' (tests/naming_convention.sol#14-16) is not in CapWords\n", + "confidence": "High" + }, + { "elements": [ { "type": "struct", @@ -173,13 +170,14 @@ "convention": "CapWords" } } - ] - }, - { + ], + "description": "Struct naming.test (tests/naming_convention.sol#14-16) is not in CapWords\n", + "markdown": "Struct [naming.test](tests/naming_convention.sol#L14-L16) is not in CapWords\n", "check": "naming-convention", "impact": "Informational", - "confidence": "High", - "description": "Event 'namingevent_(uint256)' (tests/naming_convention.sol#23) is not in CapWords\n", + "confidence": "High" + }, + { "elements": [ { "type": "event", @@ -269,13 +267,14 @@ "convention": "CapWords" } } - ] - }, - { + ], + "description": "Event namingevent_(uint256) (tests/naming_convention.sol#23) is not in CapWords\n", + "markdown": "Event [namingevent_(uint256)](tests/naming_convention.sol#L23) is not in CapWords\n", "check": "naming-convention", "impact": "Informational", - "confidence": "High", - "description": "Function 'naming.GetOne()' (tests/naming_convention.sol#30-33) is not in mixedCase\n", + "confidence": "High" + }, + { "elements": [ { "type": "function", @@ -368,13 +367,14 @@ "convention": "mixedCase" } } - ] - }, - { + ], + "description": "Function naming.GetOne() (tests/naming_convention.sol#30-33) is not in mixedCase\n", + "markdown": "Function [naming.GetOne()](tests/naming_convention.sol#L30-L33) is not in mixedCase\n", "check": "naming-convention", "impact": "Informational", - "confidence": "High", - "description": "Parameter 'Number2' of Number2 (tests/naming_convention.sol#35) is not in mixedCase\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -487,13 +487,14 @@ "convention": "mixedCase" } } - ] - }, - { + ], + "description": "Parameter naming.setInt(uint256,uint256).Number2 (tests/naming_convention.sol#35) is not in mixedCase\n", + "markdown": "Parameter [naming.setInt(uint256,uint256).Number2](tests/naming_convention.sol#L35) is not in mixedCase\n", "check": "naming-convention", "impact": "Informational", - "confidence": "High", - "description": "Constant 'naming.MY_other_CONSTANT' (tests/naming_convention.sol#9) is not in UPPER_CASE_WITH_UNDERSCORES\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -582,13 +583,14 @@ "convention": "UPPER_CASE_WITH_UNDERSCORES" } } - ] - }, - { + ], + "description": "Constant naming.MY_other_CONSTANT (tests/naming_convention.sol#9) is not in UPPER_CASE_WITH_UNDERSCORES\n", + "markdown": "Constant [naming.MY_other_CONSTANT](tests/naming_convention.sol#L9) is not in UPPER_CASE_WITH_UNDERSCORES\n", "check": "naming-convention", "impact": "Informational", - "confidence": "High", - "description": "Variable 'naming.Var_One' (tests/naming_convention.sol#11) is not in mixedCase\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -677,13 +679,14 @@ "convention": "mixedCase" } } - ] - }, - { + ], + "description": "Variable naming.Var_One (tests/naming_convention.sol#11) is not in mixedCase\n", + "markdown": "Variable [naming.Var_One](tests/naming_convention.sol#L11) is not in mixedCase\n", "check": "naming-convention", "impact": "Informational", - "confidence": "High", - "description": "Enum 'naming.numbers' (tests/naming_convention.sol#6) is not in CapWords\n", + "confidence": "High" + }, + { "elements": [ { "type": "enum", @@ -772,13 +775,14 @@ "convention": "CapWords" } } - ] - }, - { + ], + "description": "Enum naming.numbers (tests/naming_convention.sol#6) is not in CapWords\n", + "markdown": "Enum [naming.numbers](tests/naming_convention.sol#L6) is not in CapWords\n", "check": "naming-convention", "impact": "Informational", - "confidence": "High", - "description": "Modifier 'naming.CantDo()' (tests/naming_convention.sol#41-43) is not in mixedCase\n", + "confidence": "High" + }, + { "elements": [ { "type": "function", @@ -870,13 +874,14 @@ "convention": "mixedCase" } } - ] - }, - { + ], + "description": "Modifier naming.CantDo() (tests/naming_convention.sol#41-43) is not in mixedCase\n", + "markdown": "Modifier [naming.CantDo()](tests/naming_convention.sol#L41-L43) is not in mixedCase\n", "check": "naming-convention", "impact": "Informational", - "confidence": "High", - "description": "Parameter '_used' of _used (tests/naming_convention.sol#59) is not in mixedCase\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -956,13 +961,14 @@ "convention": "mixedCase" } } - ] - }, - { + ], + "description": "Parameter T.test(uint256,uint256)._used (tests/naming_convention.sol#59) is not in mixedCase\n", + "markdown": "Parameter [T.test(uint256,uint256)._used](tests/naming_convention.sol#L59) is not in mixedCase\n", "check": "naming-convention", "impact": "Informational", - "confidence": "High", - "description": "Variable 'T._myPublicVar' (tests/naming_convention.sol#56) is not in mixedCase\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -1020,13 +1026,14 @@ "convention": "mixedCase" } } - ] - }, - { + ], + "description": "Variable T._myPublicVar (tests/naming_convention.sol#56) is not in mixedCase\n", + "markdown": "Variable [T._myPublicVar](tests/naming_convention.sol#L56) is not in mixedCase\n", "check": "naming-convention", "impact": "Informational", - "confidence": "High", - "description": "Variable 'T.l' (tests/naming_convention.sol#67) used l, O, I, which should not be used\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -1084,7 +1091,12 @@ "convention": "l_O_I_should_not_be_used" } } - ] + ], + "description": "Variable T.l (tests/naming_convention.sol#67) used l, O, I, which should not be used\n", + "markdown": "Variable [T.l](tests/naming_convention.sol#L67) used l, O, I, which should not be used\n", + "check": "naming-convention", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/naming_convention.naming-convention.txt b/tests/expected_json/naming_convention.naming-convention.txt index 25be91780..45c53084c 100644 --- a/tests/expected_json/naming_convention.naming-convention.txt +++ b/tests/expected_json/naming_convention.naming-convention.txt @@ -1,15 +1,15 @@ -INFO:Detectors: -Contract 'naming' (tests/naming_convention.sol#3-48) is not in CapWords -Struct 'naming.test' (tests/naming_convention.sol#14-16) is not in CapWords -Event 'namingevent_(uint256)' (tests/naming_convention.sol#23) is not in CapWords -Function 'naming.GetOne()' (tests/naming_convention.sol#30-33) is not in mixedCase -Parameter 'Number2' of Number2 (tests/naming_convention.sol#35) is not in mixedCase -Constant 'naming.MY_other_CONSTANT' (tests/naming_convention.sol#9) is not in UPPER_CASE_WITH_UNDERSCORES -Variable 'naming.Var_One' (tests/naming_convention.sol#11) is not in mixedCase -Enum 'naming.numbers' (tests/naming_convention.sol#6) is not in CapWords -Modifier 'naming.CantDo()' (tests/naming_convention.sol#41-43) is not in mixedCase -Parameter '_used' of _used (tests/naming_convention.sol#59) is not in mixedCase -Variable 'T._myPublicVar' (tests/naming_convention.sol#56) is not in mixedCase -Variable 'T.l' (tests/naming_convention.sol#67) used l, O, I, which should not be used + +Contract naming (tests/naming_convention.sol#3-48) is not in CapWords +Struct naming.test (tests/naming_convention.sol#14-16) is not in CapWords +Event namingevent_(uint256) (tests/naming_convention.sol#23) is not in CapWords +Function naming.GetOne() (tests/naming_convention.sol#30-33) is not in mixedCase +Parameter naming.setInt(uint256,uint256).Number2 (tests/naming_convention.sol#35) is not in mixedCase +Constant naming.MY_other_CONSTANT (tests/naming_convention.sol#9) is not in UPPER_CASE_WITH_UNDERSCORES +Variable naming.Var_One (tests/naming_convention.sol#11) is not in mixedCase +Enum naming.numbers (tests/naming_convention.sol#6) is not in CapWords +Modifier naming.CantDo() (tests/naming_convention.sol#41-43) is not in mixedCase +Parameter T.test(uint256,uint256)._used (tests/naming_convention.sol#59) is not in mixedCase +Variable T._myPublicVar (tests/naming_convention.sol#56) is not in mixedCase +Variable T.l (tests/naming_convention.sol#67) used l, O, I, which should not be used Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions -INFO:Slither:tests/naming_convention.sol analyzed (4 contracts), 12 result(s) found +tests/naming_convention.sol analyzed (4 contracts with 1 detectors), 12 result(s) found diff --git a/tests/expected_json/old_solc.sol.json.solc-version.json b/tests/expected_json/old_solc.sol.json.solc-version.json index e9800bc58..716b2e410 100644 --- a/tests/expected_json/old_solc.sol.json.solc-version.json +++ b/tests/expected_json/old_solc.sol.json.solc-version.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "solc-version", - "impact": "Informational", - "confidence": "High", - "description": "Pragma version \"0.4.21\" allows old versions (None)\n", "elements": [ { "type": "pragma", @@ -32,7 +28,12 @@ ] } } - ] + ], + "description": "Pragma version0.4.21 (None) allows old versions\n", + "markdown": "Pragma version[0.4.21](None) allows old versions\n", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/old_solc.sol.json.solc-version.txt b/tests/expected_json/old_solc.sol.json.solc-version.txt index 119e34692..e8e4c5ad1 100644 --- a/tests/expected_json/old_solc.sol.json.solc-version.txt +++ b/tests/expected_json/old_solc.sol.json.solc-version.txt @@ -1,5 +1,5 @@ -INFO:Detectors: -Pragma version "0.4.21" allows old versions (None) + +Pragma version0.4.21 (None) allows old versions Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity +tests/old_solc.sol.json analyzed (1 contracts with 1 detectors), 1 result(s) found INFO:Slither:/home/travis/build/crytic/slither/scripts/../tests/expected_json/old_solc.sol.json.solc-version.json exists already, the overwrite is prevented -INFO:Slither:tests/old_solc.sol.json analyzed (1 contracts), 1 result(s) found diff --git a/tests/expected_json/pragma.0.4.24.pragma.json b/tests/expected_json/pragma.0.4.24.pragma.json index 42a1a4092..6a8687359 100644 --- a/tests/expected_json/pragma.0.4.24.pragma.json +++ b/tests/expected_json/pragma.0.4.24.pragma.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "pragma", - "impact": "Informational", - "confidence": "High", - "description": "Different versions of Solidity is used in :\n\t- Version used: ['^0.4.23', '^0.4.24']\n\t- tests/pragma.0.4.23.sol#1 declares pragma solidity^0.4.23\n\t- tests/pragma.0.4.24.sol#1 declares pragma solidity^0.4.24\n", "elements": [ { "type": "pragma", @@ -61,7 +57,12 @@ ] } } - ] + ], + "description": "Different versions of Solidity is used in :\n\t- Version used: ['^0.4.23', '^0.4.24']\n\t- ^0.4.23 (tests/pragma.0.4.23.sol#1)\n\t- ^0.4.24 (tests/pragma.0.4.24.sol#1)\n", + "markdown": "Different versions of Solidity is used in :\n\t- Version used: ['^0.4.23', '^0.4.24']\n\t- [^0.4.23](tests/pragma.0.4.23.sol#L1)\n\t- [^0.4.24](tests/pragma.0.4.24.sol#L1)\n", + "check": "pragma", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/pragma.0.4.24.pragma.txt b/tests/expected_json/pragma.0.4.24.pragma.txt index 6961c94cc..8318ed773 100644 --- a/tests/expected_json/pragma.0.4.24.pragma.txt +++ b/tests/expected_json/pragma.0.4.24.pragma.txt @@ -1,7 +1,7 @@ -INFO:Detectors: + Different versions of Solidity is used in : - Version used: ['^0.4.23', '^0.4.24'] - - tests/pragma.0.4.23.sol#1 declares pragma solidity^0.4.23 - - tests/pragma.0.4.24.sol#1 declares pragma solidity^0.4.24 + - ^0.4.23 (tests/pragma.0.4.23.sol#1) + - ^0.4.24 (tests/pragma.0.4.24.sol#1) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used -INFO:Slither:tests/pragma.0.4.24.sol analyzed (1 contracts), 1 result(s) found +tests/pragma.0.4.24.sol analyzed (1 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.json b/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.json index 32cc329fc..7923f8ed2 100644 --- a/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.json +++ b/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "reentrancy-eth", - "impact": "High", - "confidence": "Medium", - "description": "Reentrancy in Reentrancy.withdrawBalance() (tests/reentrancy-0.5.1.sol#14-22):\n\tExternal calls:\n\t- (ret,mem) = msg.sender.call.value(userBalance[msg.sender])() (tests/reentrancy-0.5.1.sol#17)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy-0.5.1.sol#21)\n", "elements": [ { "type": "function", @@ -350,13 +346,14 @@ "variable_name": "userBalance" } } - ] - }, - { + ], + "description": "Reentrancy in Reentrancy.withdrawBalance() (tests/reentrancy-0.5.1.sol#14-22):\n\tExternal calls:\n\t- (ret,mem) = msg.sender.call.value(userBalance[msg.sender])() (tests/reentrancy-0.5.1.sol#17)\n\tState variables written after the call(s):\n\t- Reentrancy.userBalance (tests/reentrancy-0.5.1.sol#4) in userBalance[msg.sender] = 0 (tests/reentrancy-0.5.1.sol#21)\n", + "markdown": "Reentrancy in [Reentrancy.withdrawBalance()](tests/reentrancy-0.5.1.sol#L14-L22):\n\tExternal calls:\n\t- [(ret,mem) = msg.sender.call.value(userBalance[msg.sender])()](tests/reentrancy-0.5.1.sol#L17)\n\tState variables written after the call(s):\n\t- [Reentrancy.userBalance](tests/reentrancy-0.5.1.sol#L4) in [userBalance[msg.sender] = 0](tests/reentrancy-0.5.1.sol#L21)\n", "check": "reentrancy-eth", "impact": "High", - "confidence": "Medium", - "description": "Reentrancy in Reentrancy.withdrawBalance_fixed_3() (tests/reentrancy-0.5.1.sol#44-53):\n\tExternal calls:\n\t- (ret,mem) = msg.sender.call.value(amount)() (tests/reentrancy-0.5.1.sol#49)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy-0.5.1.sol#51)\n", + "confidence": "Medium" + }, + { "elements": [ { "type": "function", @@ -702,7 +699,12 @@ "variable_name": "userBalance" } } - ] + ], + "description": "Reentrancy in Reentrancy.withdrawBalance_fixed_3() (tests/reentrancy-0.5.1.sol#44-53):\n\tExternal calls:\n\t- (ret,mem) = msg.sender.call.value(amount)() (tests/reentrancy-0.5.1.sol#49)\n\tState variables written after the call(s):\n\t- Reentrancy.userBalance (tests/reentrancy-0.5.1.sol#4) in userBalance[msg.sender] = amount (tests/reentrancy-0.5.1.sol#51)\n", + "markdown": "Reentrancy in [Reentrancy.withdrawBalance_fixed_3()](tests/reentrancy-0.5.1.sol#L44-L53):\n\tExternal calls:\n\t- [(ret,mem) = msg.sender.call.value(amount)()](tests/reentrancy-0.5.1.sol#L49)\n\tState variables written after the call(s):\n\t- [Reentrancy.userBalance](tests/reentrancy-0.5.1.sol#L4) in [userBalance[msg.sender] = amount](tests/reentrancy-0.5.1.sol#L51)\n", + "check": "reentrancy-eth", + "impact": "High", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.txt b/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.txt index ebf2a8c52..7f98e13f9 100644 --- a/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.txt +++ b/tests/expected_json/reentrancy-0.5.1.reentrancy-eth.txt @@ -1,13 +1,13 @@ -INFO:Detectors: + Reentrancy in Reentrancy.withdrawBalance() (tests/reentrancy-0.5.1.sol#14-22): External calls: - (ret,mem) = msg.sender.call.value(userBalance[msg.sender])() (tests/reentrancy-0.5.1.sol#17) State variables written after the call(s): - - userBalance (tests/reentrancy-0.5.1.sol#21) + - Reentrancy.userBalance (tests/reentrancy-0.5.1.sol#4) in userBalance[msg.sender] = 0 (tests/reentrancy-0.5.1.sol#21) Reentrancy in Reentrancy.withdrawBalance_fixed_3() (tests/reentrancy-0.5.1.sol#44-53): External calls: - (ret,mem) = msg.sender.call.value(amount)() (tests/reentrancy-0.5.1.sol#49) State variables written after the call(s): - - userBalance (tests/reentrancy-0.5.1.sol#51) + - Reentrancy.userBalance (tests/reentrancy-0.5.1.sol#4) in userBalance[msg.sender] = amount (tests/reentrancy-0.5.1.sol#51) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities -INFO:Slither:tests/reentrancy-0.5.1.sol analyzed (1 contracts), 2 result(s) found +tests/reentrancy-0.5.1.sol analyzed (1 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/reentrancy.reentrancy-eth.json b/tests/expected_json/reentrancy.reentrancy-eth.json index cf7f5ae09..2f403e06e 100644 --- a/tests/expected_json/reentrancy.reentrancy-eth.json +++ b/tests/expected_json/reentrancy.reentrancy-eth.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "reentrancy-eth", - "impact": "High", - "confidence": "Medium", - "description": "Reentrancy in Reentrancy.withdrawBalance() (tests/reentrancy.sol#14-21):\n\tExternal calls:\n\t- ! (msg.sender.call.value(userBalance[msg.sender])()) (tests/reentrancy.sol#17)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy.sol#20)\n", "elements": [ { "type": "function", @@ -401,13 +397,14 @@ "variable_name": "userBalance" } } - ] - }, - { + ], + "description": "Reentrancy in Reentrancy.withdrawBalance() (tests/reentrancy.sol#14-21):\n\tExternal calls:\n\t- ! (msg.sender.call.value(userBalance[msg.sender])()) (tests/reentrancy.sol#17)\n\tState variables written after the call(s):\n\t- Reentrancy.userBalance (tests/reentrancy.sol#4) in userBalance[msg.sender] = 0 (tests/reentrancy.sol#20)\n", + "markdown": "Reentrancy in [Reentrancy.withdrawBalance()](tests/reentrancy.sol#L14-L21):\n\tExternal calls:\n\t- [! (msg.sender.call.value(userBalance[msg.sender])())](tests/reentrancy.sol#L17)\n\tState variables written after the call(s):\n\t- [Reentrancy.userBalance](tests/reentrancy.sol#L4) in [userBalance[msg.sender] = 0](tests/reentrancy.sol#L20)\n", "check": "reentrancy-eth", "impact": "High", - "confidence": "Medium", - "description": "Reentrancy in Reentrancy.withdrawBalance_nested() (tests/reentrancy.sol#64-70):\n\tExternal calls:\n\t- msg.sender.call.value(amount / 2)() (tests/reentrancy.sol#67)\n\tState variables written after the call(s):\n\t- userBalance (tests/reentrancy.sol#68)\n", + "confidence": "Medium" + }, + { "elements": [ { "type": "function", @@ -798,7 +795,12 @@ "variable_name": "userBalance" } } - ] + ], + "description": "Reentrancy in Reentrancy.withdrawBalance_nested() (tests/reentrancy.sol#64-70):\n\tExternal calls:\n\t- msg.sender.call.value(amount / 2)() (tests/reentrancy.sol#67)\n\tState variables written after the call(s):\n\t- Reentrancy.userBalance (tests/reentrancy.sol#4) in userBalance[msg.sender] = 0 (tests/reentrancy.sol#68)\n", + "markdown": "Reentrancy in [Reentrancy.withdrawBalance_nested()](tests/reentrancy.sol#L64-L70):\n\tExternal calls:\n\t- [msg.sender.call.value(amount / 2)()](tests/reentrancy.sol#L67)\n\tState variables written after the call(s):\n\t- [Reentrancy.userBalance](tests/reentrancy.sol#L4) in [userBalance[msg.sender] = 0](tests/reentrancy.sol#L68)\n", + "check": "reentrancy-eth", + "impact": "High", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/reentrancy.reentrancy-eth.txt b/tests/expected_json/reentrancy.reentrancy-eth.txt index e1160ca4c..f5ab77567 100644 --- a/tests/expected_json/reentrancy.reentrancy-eth.txt +++ b/tests/expected_json/reentrancy.reentrancy-eth.txt @@ -1,13 +1,13 @@ -INFO:Detectors: + Reentrancy in Reentrancy.withdrawBalance() (tests/reentrancy.sol#14-21): External calls: - ! (msg.sender.call.value(userBalance[msg.sender])()) (tests/reentrancy.sol#17) State variables written after the call(s): - - userBalance (tests/reentrancy.sol#20) + - Reentrancy.userBalance (tests/reentrancy.sol#4) in userBalance[msg.sender] = 0 (tests/reentrancy.sol#20) Reentrancy in Reentrancy.withdrawBalance_nested() (tests/reentrancy.sol#64-70): External calls: - msg.sender.call.value(amount / 2)() (tests/reentrancy.sol#67) State variables written after the call(s): - - userBalance (tests/reentrancy.sol#68) + - Reentrancy.userBalance (tests/reentrancy.sol#4) in userBalance[msg.sender] = 0 (tests/reentrancy.sol#68) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities -INFO:Slither:tests/reentrancy.sol analyzed (1 contracts), 2 result(s) found +tests/reentrancy.sol analyzed (1 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/right_to_left_override.rtlo.json b/tests/expected_json/right_to_left_override.rtlo.json index c189dbcd7..e7540f466 100644 --- a/tests/expected_json/right_to_left_override.rtlo.json +++ b/tests/expected_json/right_to_left_override.rtlo.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "rtlo", - "impact": "High", - "confidence": "High", - "description": "/home/travis/build/crytic/slither/tests/right_to_left_override.sol contains a unicode right-to-left-override character at byte offset 96:\n\t- b' test1(/*A\\xe2\\x80\\xae/*B*/2 , 1/*\\xe2\\x80\\xad'\n", "elements": [ { "type": "other", @@ -27,7 +23,12 @@ "ending_column": 21 } } - ] + ], + "description": "/home/travis/build/crytic/slither/tests/right_to_left_override.sol contains a unicode right-to-left-override character at byte offset 96:\n\t- b' test1(/*A\\xe2\\x80\\xae/*B*/2 , 1/*\\xe2\\x80\\xad'\n", + "markdown": "/home/travis/build/crytic/slither/tests/right_to_left_override.sol contains a unicode right-to-left-override character at byte offset 96:\n\t- b' test1(/*A\\xe2\\x80\\xae/*B*/2 , 1/*\\xe2\\x80\\xad'\n", + "check": "rtlo", + "impact": "High", + "confidence": "High" } ] } diff --git a/tests/expected_json/right_to_left_override.rtlo.txt b/tests/expected_json/right_to_left_override.rtlo.txt index 9d77008f0..29326d789 100644 --- a/tests/expected_json/right_to_left_override.rtlo.txt +++ b/tests/expected_json/right_to_left_override.rtlo.txt @@ -1,5 +1,5 @@ -INFO:Detectors: + /home/travis/build/crytic/slither/tests/right_to_left_override.sol contains a unicode right-to-left-override character at byte offset 96: - b' test1(/*A\xe2\x80\xae/*B*/2 , 1/*\xe2\x80\xad' Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#right-to-left-override-character -INFO:Slither:tests/right_to_left_override.sol analyzed (1 contracts), 1 result(s) found +tests/right_to_left_override.sol analyzed (1 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/shadowing_abstract.shadowing-abstract.json b/tests/expected_json/shadowing_abstract.shadowing-abstract.json index ec993de29..c83b58049 100644 --- a/tests/expected_json/shadowing_abstract.shadowing-abstract.json +++ b/tests/expected_json/shadowing_abstract.shadowing-abstract.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "shadowing-abstract", - "impact": "Medium", - "confidence": "High", - "description": "DerivedContract.owner (tests/shadowing_abstract.sol#7) shadows:\n\t- BaseContract.owner (tests/shadowing_abstract.sol#2)\n", "elements": [ { "type": "variable", @@ -91,7 +87,12 @@ } } } - ] + ], + "description": "DerivedContract.owner (tests/shadowing_abstract.sol#7) shadows:\n\t- BaseContract.owner (tests/shadowing_abstract.sol#2)\n", + "markdown": "[DerivedContract.owner](tests/shadowing_abstract.sol#L7) shadows:\n\t- [BaseContract.owner](tests/shadowing_abstract.sol#L2)\n", + "check": "shadowing-abstract", + "impact": "Medium", + "confidence": "High" } ] } diff --git a/tests/expected_json/shadowing_abstract.shadowing-abstract.txt b/tests/expected_json/shadowing_abstract.shadowing-abstract.txt index fed0e9e24..93b722f63 100644 --- a/tests/expected_json/shadowing_abstract.shadowing-abstract.txt +++ b/tests/expected_json/shadowing_abstract.shadowing-abstract.txt @@ -1,5 +1,5 @@ -INFO:Detectors: + DerivedContract.owner (tests/shadowing_abstract.sol#7) shadows: - BaseContract.owner (tests/shadowing_abstract.sol#2) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing-from-abstract-contracts -INFO:Slither:tests/shadowing_abstract.sol analyzed (2 contracts), 1 result(s) found +tests/shadowing_abstract.sol analyzed (2 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/shadowing_builtin_symbols.shadowing-builtin.json b/tests/expected_json/shadowing_builtin_symbols.shadowing-builtin.json index a328fa79a..771dac106 100644 --- a/tests/expected_json/shadowing_builtin_symbols.shadowing-builtin.json +++ b/tests/expected_json/shadowing_builtin_symbols.shadowing-builtin.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "shadowing-builtin", - "impact": "Low", - "confidence": "High", - "description": "BaseContract.blockhash (state variable @ tests/shadowing_builtin_symbols.sol#4) shadows built-in symbol \"blockhash\"\n", "elements": [ { "type": "variable", @@ -52,13 +48,14 @@ } } } - ] - }, - { + ], + "description": "BaseContract.blockhash (tests/shadowing_builtin_symbols.sol#4) (state variable) shadows built-in symbol\"\n", + "markdown": "[BaseContract.blockhash](tests/shadowing_builtin_symbols.sol#L4) (state variable) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "BaseContract.now (state variable @ tests/shadowing_builtin_symbols.sol#5) shadows built-in symbol \"now\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -103,13 +100,14 @@ } } } - ] - }, - { + ], + "description": "BaseContract.now (tests/shadowing_builtin_symbols.sol#5) (state variable) shadows built-in symbol\"\n", + "markdown": "[BaseContract.now](tests/shadowing_builtin_symbols.sol#L5) (state variable) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "BaseContract.revert (event @ tests/shadowing_builtin_symbols.sol#7) shadows built-in symbol \"revert\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "event", @@ -155,13 +153,14 @@ "signature": "revert(bool)" } } - ] - }, - { + ], + "description": "BaseContractrevert(bool) (tests/shadowing_builtin_symbols.sol#7) (event) shadows built-in symbol\"\n", + "markdown": "[BaseContractrevert(bool)](tests/shadowing_builtin_symbols.sol#L7) (event) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "ExtendedContract.assert (function @ tests/shadowing_builtin_symbols.sol#13-15) shadows built-in symbol \"assert\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "function", @@ -210,13 +209,14 @@ "signature": "assert(bool)" } } - ] - }, - { + ], + "description": "ExtendedContract.assert(bool) (tests/shadowing_builtin_symbols.sol#13-15) (function) shadows built-in symbol\"\n", + "markdown": "[ExtendedContract.assert(bool)](tests/shadowing_builtin_symbols.sol#L13-L15) (function) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "ExtendedContract.assert.msg (local variable @ tests/shadowing_builtin_symbols.sol#14) shadows built-in symbol \"msg\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -285,13 +285,14 @@ } } } - ] - }, - { + ], + "description": "ExtendedContract.assert(bool).msg (tests/shadowing_builtin_symbols.sol#14) (local variable) shadows built-in symbol\"\n", + "markdown": "[ExtendedContract.assert(bool).msg](tests/shadowing_builtin_symbols.sol#L14) (local variable) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "ExtendedContract.ecrecover (state variable @ tests/shadowing_builtin_symbols.sol#11) shadows built-in symbol \"ecrecover\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -337,13 +338,14 @@ } } } - ] - }, - { + ], + "description": "ExtendedContract.ecrecover (tests/shadowing_builtin_symbols.sol#11) (state variable) shadows built-in symbol\"\n", + "markdown": "[ExtendedContract.ecrecover](tests/shadowing_builtin_symbols.sol#L11) (state variable) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "FurtherExtendedContract.require (modifier @ tests/shadowing_builtin_symbols.sol#23-28) shadows built-in symbol \"require\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "function", @@ -400,13 +402,14 @@ "signature": "require()" } } - ] - }, - { + ], + "description": "FurtherExtendedContract.require() (tests/shadowing_builtin_symbols.sol#23-28) (modifier) shadows built-in symbol\"\n", + "markdown": "[FurtherExtendedContract.require()](tests/shadowing_builtin_symbols.sol#L23-L28) (modifier) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "FurtherExtendedContract.require.keccak256 (local variable @ tests/shadowing_builtin_symbols.sol#25) shadows built-in symbol \"keccak256\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -483,13 +486,14 @@ } } } - ] - }, - { + ], + "description": "FurtherExtendedContract.require().keccak256 (tests/shadowing_builtin_symbols.sol#25) (local variable) shadows built-in symbol\"\n", + "markdown": "[FurtherExtendedContract.require().keccak256](tests/shadowing_builtin_symbols.sol#L25) (local variable) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "FurtherExtendedContract.require.sha3 (local variable @ tests/shadowing_builtin_symbols.sol#26) shadows built-in symbol \"sha3\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -566,13 +570,14 @@ } } } - ] - }, - { + ], + "description": "FurtherExtendedContract.require().sha3 (tests/shadowing_builtin_symbols.sol#26) (local variable) shadows built-in symbol\"\n", + "markdown": "[FurtherExtendedContract.require().sha3](tests/shadowing_builtin_symbols.sol#L26) (local variable) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "FurtherExtendedContract.blockhash (state variable @ tests/shadowing_builtin_symbols.sol#19) shadows built-in symbol \"blockhash\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -623,13 +628,14 @@ } } } - ] - }, - { + ], + "description": "FurtherExtendedContract.blockhash (tests/shadowing_builtin_symbols.sol#19) (state variable) shadows built-in symbol\"\n", + "markdown": "[FurtherExtendedContract.blockhash](tests/shadowing_builtin_symbols.sol#L19) (state variable) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "FurtherExtendedContract.this (state variable @ tests/shadowing_builtin_symbols.sol#20) shadows built-in symbol \"this\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -680,13 +686,14 @@ } } } - ] - }, - { + ], + "description": "FurtherExtendedContract.this (tests/shadowing_builtin_symbols.sol#20) (state variable) shadows built-in symbol\"\n", + "markdown": "[FurtherExtendedContract.this](tests/shadowing_builtin_symbols.sol#L20) (state variable) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "FurtherExtendedContract.abi (state variable @ tests/shadowing_builtin_symbols.sol#21) shadows built-in symbol \"abi\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -737,13 +744,14 @@ } } } - ] - }, - { + ], + "description": "FurtherExtendedContract.abi (tests/shadowing_builtin_symbols.sol#21) (state variable) shadows built-in symbol\"\n", + "markdown": "[FurtherExtendedContract.abi](tests/shadowing_builtin_symbols.sol#L21) (state variable) shadows built-in symbol\"\n", "check": "shadowing-builtin", "impact": "Low", - "confidence": "High", - "description": "Reserved.mutable (state variable @ tests/shadowing_builtin_symbols.sol#32) shadows built-in symbol \"mutable\"\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -786,7 +794,12 @@ } } } - ] + ], + "description": "Reserved.mutable (tests/shadowing_builtin_symbols.sol#32) (state variable) shadows built-in symbol\"\n", + "markdown": "[Reserved.mutable](tests/shadowing_builtin_symbols.sol#L32) (state variable) shadows built-in symbol\"\n", + "check": "shadowing-builtin", + "impact": "Low", + "confidence": "High" } ] } diff --git a/tests/expected_json/shadowing_builtin_symbols.shadowing-builtin.txt b/tests/expected_json/shadowing_builtin_symbols.shadowing-builtin.txt index 18d9c370a..18473dd98 100644 --- a/tests/expected_json/shadowing_builtin_symbols.shadowing-builtin.txt +++ b/tests/expected_json/shadowing_builtin_symbols.shadowing-builtin.txt @@ -1,16 +1,16 @@ -INFO:Detectors: -BaseContract.blockhash (state variable @ tests/shadowing_builtin_symbols.sol#4) shadows built-in symbol "blockhash" -BaseContract.now (state variable @ tests/shadowing_builtin_symbols.sol#5) shadows built-in symbol "now" -BaseContract.revert (event @ tests/shadowing_builtin_symbols.sol#7) shadows built-in symbol "revert" -ExtendedContract.assert (function @ tests/shadowing_builtin_symbols.sol#13-15) shadows built-in symbol "assert" -ExtendedContract.assert.msg (local variable @ tests/shadowing_builtin_symbols.sol#14) shadows built-in symbol "msg" -ExtendedContract.ecrecover (state variable @ tests/shadowing_builtin_symbols.sol#11) shadows built-in symbol "ecrecover" -FurtherExtendedContract.require (modifier @ tests/shadowing_builtin_symbols.sol#23-28) shadows built-in symbol "require" -FurtherExtendedContract.require.keccak256 (local variable @ tests/shadowing_builtin_symbols.sol#25) shadows built-in symbol "keccak256" -FurtherExtendedContract.require.sha3 (local variable @ tests/shadowing_builtin_symbols.sol#26) shadows built-in symbol "sha3" -FurtherExtendedContract.blockhash (state variable @ tests/shadowing_builtin_symbols.sol#19) shadows built-in symbol "blockhash" -FurtherExtendedContract.this (state variable @ tests/shadowing_builtin_symbols.sol#20) shadows built-in symbol "this" -FurtherExtendedContract.abi (state variable @ tests/shadowing_builtin_symbols.sol#21) shadows built-in symbol "abi" -Reserved.mutable (state variable @ tests/shadowing_builtin_symbols.sol#32) shadows built-in symbol "mutable" + +BaseContract.blockhash (tests/shadowing_builtin_symbols.sol#4) (state variable) shadows built-in symbol" +BaseContract.now (tests/shadowing_builtin_symbols.sol#5) (state variable) shadows built-in symbol" +BaseContractrevert(bool) (tests/shadowing_builtin_symbols.sol#7) (event) shadows built-in symbol" +ExtendedContract.assert(bool) (tests/shadowing_builtin_symbols.sol#13-15) (function) shadows built-in symbol" +ExtendedContract.assert(bool).msg (tests/shadowing_builtin_symbols.sol#14) (local variable) shadows built-in symbol" +ExtendedContract.ecrecover (tests/shadowing_builtin_symbols.sol#11) (state variable) shadows built-in symbol" +FurtherExtendedContract.require() (tests/shadowing_builtin_symbols.sol#23-28) (modifier) shadows built-in symbol" +FurtherExtendedContract.require().keccak256 (tests/shadowing_builtin_symbols.sol#25) (local variable) shadows built-in symbol" +FurtherExtendedContract.require().sha3 (tests/shadowing_builtin_symbols.sol#26) (local variable) shadows built-in symbol" +FurtherExtendedContract.blockhash (tests/shadowing_builtin_symbols.sol#19) (state variable) shadows built-in symbol" +FurtherExtendedContract.this (tests/shadowing_builtin_symbols.sol#20) (state variable) shadows built-in symbol" +FurtherExtendedContract.abi (tests/shadowing_builtin_symbols.sol#21) (state variable) shadows built-in symbol" +Reserved.mutable (tests/shadowing_builtin_symbols.sol#32) (state variable) shadows built-in symbol" Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#builtin-symbol-shadowing -INFO:Slither:tests/shadowing_builtin_symbols.sol analyzed (4 contracts), 13 result(s) found +tests/shadowing_builtin_symbols.sol analyzed (4 contracts with 1 detectors), 13 result(s) found diff --git a/tests/expected_json/shadowing_local_variable.shadowing-local.json b/tests/expected_json/shadowing_local_variable.shadowing-local.json index 616a637df..407cdbfb5 100644 --- a/tests/expected_json/shadowing_local_variable.shadowing-local.json +++ b/tests/expected_json/shadowing_local_variable.shadowing-local.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "shadowing-local", - "impact": "Low", - "confidence": "High", - "description": "FurtherExtendedContract.shadowingParent.x (local variable @ tests/shadowing_local_variable.sol#25) shadows:\n\t- FurtherExtendedContract.x (state variable @ tests/shadowing_local_variable.sol#17)\n\t- ExtendedContract.x (state variable @ tests/shadowing_local_variable.sol#9)\n\t- BaseContract.x (state variable @ tests/shadowing_local_variable.sol#4)\n", "elements": [ { "type": "variable", @@ -211,13 +207,14 @@ } } } - ] - }, - { + ], + "description": "FurtherExtendedContract.shadowingParent(uint256).x (tests/shadowing_local_variable.sol#25) shadows:\n\t- FurtherExtendedContract.x (tests/shadowing_local_variable.sol#17) (state variable)\n\t- ExtendedContract.x (tests/shadowing_local_variable.sol#9) (state variable)\n\t- BaseContract.x (tests/shadowing_local_variable.sol#4) (state variable)\n", + "markdown": "[FurtherExtendedContract.shadowingParent(uint256).x](tests/shadowing_local_variable.sol#L25) shadows:\n\t- [FurtherExtendedContract.x](tests/shadowing_local_variable.sol#L17) (state variable)\n\t- [ExtendedContract.x](tests/shadowing_local_variable.sol#L9) (state variable)\n\t- [BaseContract.x](tests/shadowing_local_variable.sol#L4) (state variable)\n", "check": "shadowing-local", "impact": "Low", - "confidence": "High", - "description": "FurtherExtendedContract.shadowingParent.y (local variable @ tests/shadowing_local_variable.sol#25) shadows:\n\t- BaseContract.y (state variable @ tests/shadowing_local_variable.sol#5)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -329,13 +326,14 @@ } } } - ] - }, - { + ], + "description": "FurtherExtendedContract.shadowingParent(uint256).y (tests/shadowing_local_variable.sol#25) shadows:\n\t- BaseContract.y (tests/shadowing_local_variable.sol#5) (state variable)\n", + "markdown": "[FurtherExtendedContract.shadowingParent(uint256).y](tests/shadowing_local_variable.sol#L25) shadows:\n\t- [BaseContract.y](tests/shadowing_local_variable.sol#L5) (state variable)\n", "check": "shadowing-local", "impact": "Low", - "confidence": "High", - "description": "FurtherExtendedContract.shadowingParent.z (local variable @ tests/shadowing_local_variable.sol#25) shadows:\n\t- ExtendedContract.z (function @ tests/shadowing_local_variable.sol#11)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -451,13 +449,14 @@ "signature": "z()" } } - ] - }, - { + ], + "description": "FurtherExtendedContract.shadowingParent(uint256).z (tests/shadowing_local_variable.sol#25) shadows:\n\t- ExtendedContract.z() (tests/shadowing_local_variable.sol#11) (function)\n", + "markdown": "[FurtherExtendedContract.shadowingParent(uint256).z](tests/shadowing_local_variable.sol#L25) shadows:\n\t- [ExtendedContract.z()](tests/shadowing_local_variable.sol#L11) (function)\n", "check": "shadowing-local", "impact": "Low", - "confidence": "High", - "description": "FurtherExtendedContract.shadowingParent.w (local variable @ tests/shadowing_local_variable.sol#25) shadows:\n\t- FurtherExtendedContract.w (modifier @ tests/shadowing_local_variable.sol#20-23)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -580,13 +579,14 @@ "signature": "w()" } } - ] - }, - { + ], + "description": "FurtherExtendedContract.shadowingParent(uint256).w (tests/shadowing_local_variable.sol#25) shadows:\n\t- FurtherExtendedContract.w() (tests/shadowing_local_variable.sol#20-23) (modifier)\n", + "markdown": "[FurtherExtendedContract.shadowingParent(uint256).w](tests/shadowing_local_variable.sol#L25) shadows:\n\t- [FurtherExtendedContract.w()](tests/shadowing_local_variable.sol#L20-L23) (modifier)\n", "check": "shadowing-local", "impact": "Low", - "confidence": "High", - "description": "FurtherExtendedContract.shadowingParent.v (local variable @ tests/shadowing_local_variable.sol#25) shadows:\n\t- ExtendedContract.v (event @ tests/shadowing_local_variable.sol#13)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -702,7 +702,12 @@ "signature": "v()" } } - ] + ], + "description": "FurtherExtendedContract.shadowingParent(uint256).v (tests/shadowing_local_variable.sol#25) shadows:\n\t- ExtendedContractv() (tests/shadowing_local_variable.sol#13) (event)\n", + "markdown": "[FurtherExtendedContract.shadowingParent(uint256).v](tests/shadowing_local_variable.sol#L25) shadows:\n\t- [ExtendedContractv()](tests/shadowing_local_variable.sol#L13) (event)\n", + "check": "shadowing-local", + "impact": "Low", + "confidence": "High" } ] } diff --git a/tests/expected_json/shadowing_local_variable.shadowing-local.txt b/tests/expected_json/shadowing_local_variable.shadowing-local.txt index 944c3bd1b..40eb29c54 100644 --- a/tests/expected_json/shadowing_local_variable.shadowing-local.txt +++ b/tests/expected_json/shadowing_local_variable.shadowing-local.txt @@ -1,15 +1,15 @@ -INFO:Detectors: -FurtherExtendedContract.shadowingParent.x (local variable @ tests/shadowing_local_variable.sol#25) shadows: - - FurtherExtendedContract.x (state variable @ tests/shadowing_local_variable.sol#17) - - ExtendedContract.x (state variable @ tests/shadowing_local_variable.sol#9) - - BaseContract.x (state variable @ tests/shadowing_local_variable.sol#4) -FurtherExtendedContract.shadowingParent.y (local variable @ tests/shadowing_local_variable.sol#25) shadows: - - BaseContract.y (state variable @ tests/shadowing_local_variable.sol#5) -FurtherExtendedContract.shadowingParent.z (local variable @ tests/shadowing_local_variable.sol#25) shadows: - - ExtendedContract.z (function @ tests/shadowing_local_variable.sol#11) -FurtherExtendedContract.shadowingParent.w (local variable @ tests/shadowing_local_variable.sol#25) shadows: - - FurtherExtendedContract.w (modifier @ tests/shadowing_local_variable.sol#20-23) -FurtherExtendedContract.shadowingParent.v (local variable @ tests/shadowing_local_variable.sol#25) shadows: - - ExtendedContract.v (event @ tests/shadowing_local_variable.sol#13) + +FurtherExtendedContract.shadowingParent(uint256).x (tests/shadowing_local_variable.sol#25) shadows: + - FurtherExtendedContract.x (tests/shadowing_local_variable.sol#17) (state variable) + - ExtendedContract.x (tests/shadowing_local_variable.sol#9) (state variable) + - BaseContract.x (tests/shadowing_local_variable.sol#4) (state variable) +FurtherExtendedContract.shadowingParent(uint256).y (tests/shadowing_local_variable.sol#25) shadows: + - BaseContract.y (tests/shadowing_local_variable.sol#5) (state variable) +FurtherExtendedContract.shadowingParent(uint256).z (tests/shadowing_local_variable.sol#25) shadows: + - ExtendedContract.z() (tests/shadowing_local_variable.sol#11) (function) +FurtherExtendedContract.shadowingParent(uint256).w (tests/shadowing_local_variable.sol#25) shadows: + - FurtherExtendedContract.w() (tests/shadowing_local_variable.sol#20-23) (modifier) +FurtherExtendedContract.shadowingParent(uint256).v (tests/shadowing_local_variable.sol#25) shadows: + - ExtendedContractv() (tests/shadowing_local_variable.sol#13) (event) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing -INFO:Slither:tests/shadowing_local_variable.sol analyzed (3 contracts), 5 result(s) found +tests/shadowing_local_variable.sol analyzed (3 contracts with 1 detectors), 5 result(s) found diff --git a/tests/expected_json/shadowing_state_variable.shadowing-state.json b/tests/expected_json/shadowing_state_variable.shadowing-state.json index 2833ee769..2fa620ae0 100644 --- a/tests/expected_json/shadowing_state_variable.shadowing-state.json +++ b/tests/expected_json/shadowing_state_variable.shadowing-state.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "shadowing-state", - "impact": "High", - "confidence": "High", - "description": "DerivedContract.owner (tests/shadowing_state_variable.sol#12) shadows:\n\t- BaseContract.owner (tests/shadowing_state_variable.sol#2)\n", "elements": [ { "type": "variable", @@ -103,7 +99,12 @@ } } } - ] + ], + "description": "DerivedContract.owner (tests/shadowing_state_variable.sol#12) shadows:\n\t- BaseContract.owner (tests/shadowing_state_variable.sol#2)\n", + "markdown": "[DerivedContract.owner](tests/shadowing_state_variable.sol#L12) shadows:\n\t- [BaseContract.owner](tests/shadowing_state_variable.sol#L2)\n", + "check": "shadowing-state", + "impact": "High", + "confidence": "High" } ] } diff --git a/tests/expected_json/shadowing_state_variable.shadowing-state.txt b/tests/expected_json/shadowing_state_variable.shadowing-state.txt index 965837378..5109991c2 100644 --- a/tests/expected_json/shadowing_state_variable.shadowing-state.txt +++ b/tests/expected_json/shadowing_state_variable.shadowing-state.txt @@ -1,5 +1,5 @@ -INFO:Detectors: + DerivedContract.owner (tests/shadowing_state_variable.sol#12) shadows: - BaseContract.owner (tests/shadowing_state_variable.sol#2) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing -INFO:Slither:tests/shadowing_state_variable.sol analyzed (2 contracts), 1 result(s) found +tests/shadowing_state_variable.sol analyzed (2 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/solc_version_incorrect.solc-version.json b/tests/expected_json/solc_version_incorrect.solc-version.json index eb0c2f514..af9d454de 100644 --- a/tests/expected_json/solc_version_incorrect.solc-version.json +++ b/tests/expected_json/solc_version_incorrect.solc-version.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "solc-version", - "impact": "Informational", - "confidence": "High", - "description": "Pragma version \"^0.4.23\" allows old versions (tests/solc_version_incorrect.sol#2)\n", "elements": [ { "type": "pragma", @@ -35,13 +31,14 @@ ] } } - ] - }, - { + ], + "description": "Pragma version^0.4.23 (tests/solc_version_incorrect.sol#2) allows old versions\n", + "markdown": "Pragma version[^0.4.23](tests/solc_version_incorrect.sol#L2) allows old versions\n", "check": "solc-version", "impact": "Informational", - "confidence": "High", - "description": "Pragma version \">=0.4.0<0.6.0\" allows old versions (tests/solc_version_incorrect.sol#3)\n", + "confidence": "High" + }, + { "elements": [ { "type": "pragma", @@ -72,7 +69,12 @@ ] } } - ] + ], + "description": "Pragma version>=0.4.0<0.6.0 (tests/solc_version_incorrect.sol#3) allows old versions\n", + "markdown": "Pragma version[>=0.4.0<0.6.0](tests/solc_version_incorrect.sol#L3) allows old versions\n", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/solc_version_incorrect.solc-version.txt b/tests/expected_json/solc_version_incorrect.solc-version.txt index 60a0c9707..d9432c890 100644 --- a/tests/expected_json/solc_version_incorrect.solc-version.txt +++ b/tests/expected_json/solc_version_incorrect.solc-version.txt @@ -1,5 +1,5 @@ -INFO:Detectors: -Pragma version "^0.4.23" allows old versions (tests/solc_version_incorrect.sol#2) -Pragma version ">=0.4.0<0.6.0" allows old versions (tests/solc_version_incorrect.sol#3) + +Pragma version^0.4.23 (tests/solc_version_incorrect.sol#2) allows old versions +Pragma version>=0.4.0<0.6.0 (tests/solc_version_incorrect.sol#3) allows old versions Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity -INFO:Slither:tests/solc_version_incorrect.sol analyzed (1 contracts), 2 result(s) found +tests/solc_version_incorrect.sol analyzed (1 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.json b/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.json index 00b47a15a..a199ac228 100644 --- a/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.json +++ b/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "solc-version", - "impact": "Informational", - "confidence": "High", - "description": "Pragma version \"^0.5.5\" is known to contain severe issue (https://solidity.readthedocs.io/en/v0.5.8/bugs.html) (None)\n", "elements": [ { "type": "pragma", @@ -33,13 +29,14 @@ ] } } - ] - }, - { + ], + "description": "Pragma version^0.5.5 (None) is known to contain severe issue (https://solidity.readthedocs.io/en/v0.5.8/bugs.html)\n", + "markdown": "Pragma version[^0.5.5](None) is known to contain severe issue (https://solidity.readthedocs.io/en/v0.5.8/bugs.html)\n", "check": "solc-version", "impact": "Informational", - "confidence": "High", - "description": "Pragma version \"0.5.7\" necessitates versions too recent to be trusted. Consider deploying with 0.5.3 (None)\n", + "confidence": "High" + }, + { "elements": [ { "type": "pragma", @@ -64,7 +61,12 @@ ] } } - ] + ], + "description": "Pragma version0.5.7 (None) necessitates versions too recent to be trusted. Consider deploying with 0.5.3\n", + "markdown": "Pragma version[0.5.7](None) necessitates versions too recent to be trusted. Consider deploying with 0.5.3\n", + "check": "solc-version", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.txt b/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.txt index 6673c1a56..0e09462e6 100644 --- a/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.txt +++ b/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.txt @@ -1,5 +1,5 @@ -INFO:Detectors: -Pragma version "^0.5.5" is known to contain severe issue (https://solidity.readthedocs.io/en/v0.5.8/bugs.html) (None) -Pragma version "0.5.7" necessitates versions too recent to be trusted. Consider deploying with 0.5.3 (None) + +Pragma version^0.5.5 (None) is known to contain severe issue (https://solidity.readthedocs.io/en/v0.5.8/bugs.html) +Pragma version0.5.7 (None) necessitates versions too recent to be trusted. Consider deploying with 0.5.3 Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity -INFO:Slither:tests/solc_version_incorrect_05.ast.json analyzed (1 contracts), 2 result(s) found +tests/solc_version_incorrect_05.ast.json analyzed (1 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/timestamp.timestamp.json b/tests/expected_json/timestamp.timestamp.json index f35e6f173..1819fe638 100644 --- a/tests/expected_json/timestamp.timestamp.json +++ b/tests/expected_json/timestamp.timestamp.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "timestamp", - "impact": "Low", - "confidence": "Medium", - "description": "Timestamp.bad0() (tests/timestamp.sol#4-6) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- require(bool)(block.timestamp == 0) (tests/timestamp.sol#5)\n", "elements": [ { "type": "function", @@ -149,13 +145,14 @@ } } } - ] - }, - { + ], + "description": "Timestamp.bad0() (tests/timestamp.sol#4-6) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- require(bool)(block.timestamp == 0) (tests/timestamp.sol#5)\n", + "markdown": "[Timestamp.bad0()](tests/timestamp.sol#L4-L6) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- [require(bool)(block.timestamp == 0)](tests/timestamp.sol#L5)\n", "check": "timestamp", "impact": "Low", - "confidence": "Medium", - "description": "Timestamp.bad1() (tests/timestamp.sol#8-11) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- require(bool)(time == 0) (tests/timestamp.sol#10)\n", + "confidence": "Medium" + }, + { "elements": [ { "type": "function", @@ -299,13 +296,14 @@ } } } - ] - }, - { + ], + "description": "Timestamp.bad1() (tests/timestamp.sol#8-11) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- require(bool)(time == 0) (tests/timestamp.sol#10)\n", + "markdown": "[Timestamp.bad1()](tests/timestamp.sol#L8-L11) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- [require(bool)(time == 0)](tests/timestamp.sol#L10)\n", "check": "timestamp", "impact": "Low", - "confidence": "Medium", - "description": "Timestamp.bad2() (tests/timestamp.sol#13-15) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- block.timestamp > 0 (tests/timestamp.sol#14)\n", + "confidence": "Medium" + }, + { "elements": [ { "type": "function", @@ -447,7 +445,12 @@ } } } - ] + ], + "description": "Timestamp.bad2() (tests/timestamp.sol#13-15) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- block.timestamp > 0 (tests/timestamp.sol#14)\n", + "markdown": "[Timestamp.bad2()](tests/timestamp.sol#L13-L15) uses timestamp for comparisons\n\tDangerous comparisons:\n\t- [block.timestamp > 0](tests/timestamp.sol#L14)\n", + "check": "timestamp", + "impact": "Low", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/timestamp.timestamp.txt b/tests/expected_json/timestamp.timestamp.txt index ef64d694e..f26348c0c 100644 --- a/tests/expected_json/timestamp.timestamp.txt +++ b/tests/expected_json/timestamp.timestamp.txt @@ -1,4 +1,4 @@ -INFO:Detectors: + Timestamp.bad0() (tests/timestamp.sol#4-6) uses timestamp for comparisons Dangerous comparisons: - require(bool)(block.timestamp == 0) (tests/timestamp.sol#5) @@ -9,4 +9,4 @@ Timestamp.bad2() (tests/timestamp.sol#13-15) uses timestamp for comparisons Dangerous comparisons: - block.timestamp > 0 (tests/timestamp.sol#14) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp -INFO:Slither:tests/timestamp.sol analyzed (1 contracts), 3 result(s) found +tests/timestamp.sol analyzed (1 contracts with 1 detectors), 3 result(s) found diff --git a/tests/expected_json/too_many_digits.too-many-digits.json b/tests/expected_json/too_many_digits.too-many-digits.json index 0e8cf635f..9e7a211f5 100644 --- a/tests/expected_json/too_many_digits.too-many-digits.json +++ b/tests/expected_json/too_many_digits.too-many-digits.json @@ -4,11 +4,89 @@ "results": { "detectors": [ { - "check": "too-many-digits", - "impact": "Informational", - "confidence": "Medium", - "description": "C.f (tests/too_many_digits.sol#9-15) uses literals with too many digits:\n\t- x1 = 0x000001\n", "elements": [ + { + "type": "function", + "name": "f", + "source_mapping": { + "start": 174, + "length": 195, + "filename_used": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_relative": "tests/too_many_digits.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_short": "tests/too_many_digits.sol", + "is_dependency": false, + "lines": [ + 9, + 10, + 11, + 12, + 13, + 14, + 15 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 25, + "length": 897, + "filename_used": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_relative": "tests/too_many_digits.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_short": "tests/too_many_digits.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "f()" + } + }, { "type": "node", "name": "x1 = 0x000001", @@ -111,14 +189,97 @@ } } } - ] - }, - { + ], + "description": "C.f() (tests/too_many_digits.sol#9-15) uses literals with too many digits:\n\t- x1 = 0x000001 (tests/too_many_digits.sol#10)\n", + "markdown": "[C.f()](tests/too_many_digits.sol#L9-L15) uses literals with too many digits:\n\t- [x1 = 0x000001](tests/too_many_digits.sol#L10)\n", "check": "too-many-digits", "impact": "Informational", - "confidence": "Medium", - "description": "C.f (tests/too_many_digits.sol#9-15) uses literals with too many digits:\n\t- x2 = 0x0000000000001\n", + "confidence": "Medium" + }, + { "elements": [ + { + "type": "function", + "name": "f", + "source_mapping": { + "start": 174, + "length": 195, + "filename_used": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_relative": "tests/too_many_digits.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_short": "tests/too_many_digits.sol", + "is_dependency": false, + "lines": [ + 9, + 10, + 11, + 12, + 13, + 14, + 15 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 25, + "length": 897, + "filename_used": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_relative": "tests/too_many_digits.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_short": "tests/too_many_digits.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "f()" + } + }, { "type": "node", "name": "x2 = 0x0000000000001", @@ -221,14 +382,97 @@ } } } - ] - }, - { + ], + "description": "C.f() (tests/too_many_digits.sol#9-15) uses literals with too many digits:\n\t- x2 = 0x0000000000001 (tests/too_many_digits.sol#11)\n", + "markdown": "[C.f()](tests/too_many_digits.sol#L9-L15) uses literals with too many digits:\n\t- [x2 = 0x0000000000001](tests/too_many_digits.sol#L11)\n", "check": "too-many-digits", "impact": "Informational", - "confidence": "Medium", - "description": "C.f (tests/too_many_digits.sol#9-15) uses literals with too many digits:\n\t- x3 = 1000000000000000000\n", + "confidence": "Medium" + }, + { "elements": [ + { + "type": "function", + "name": "f", + "source_mapping": { + "start": 174, + "length": 195, + "filename_used": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_relative": "tests/too_many_digits.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_short": "tests/too_many_digits.sol", + "is_dependency": false, + "lines": [ + 9, + 10, + 11, + 12, + 13, + 14, + 15 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 25, + "length": 897, + "filename_used": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_relative": "tests/too_many_digits.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_short": "tests/too_many_digits.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "f()" + } + }, { "type": "node", "name": "x3 = 1000000000000000000", @@ -331,14 +575,97 @@ } } } - ] - }, - { + ], + "description": "C.f() (tests/too_many_digits.sol#9-15) uses literals with too many digits:\n\t- x3 = 1000000000000000000 (tests/too_many_digits.sol#12)\n", + "markdown": "[C.f()](tests/too_many_digits.sol#L9-L15) uses literals with too many digits:\n\t- [x3 = 1000000000000000000](tests/too_many_digits.sol#L12)\n", "check": "too-many-digits", "impact": "Informational", - "confidence": "Medium", - "description": "C.f (tests/too_many_digits.sol#9-15) uses literals with too many digits:\n\t- x4 = 100000\n", + "confidence": "Medium" + }, + { "elements": [ + { + "type": "function", + "name": "f", + "source_mapping": { + "start": 174, + "length": 195, + "filename_used": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_relative": "tests/too_many_digits.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_short": "tests/too_many_digits.sol", + "is_dependency": false, + "lines": [ + 9, + 10, + 11, + 12, + 13, + 14, + 15 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 25, + "length": 897, + "filename_used": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_relative": "tests/too_many_digits.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_short": "tests/too_many_digits.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "f()" + } + }, { "type": "node", "name": "x4 = 100000", @@ -441,14 +768,95 @@ } } } - ] - }, - { + ], + "description": "C.f() (tests/too_many_digits.sol#9-15) uses literals with too many digits:\n\t- x4 = 100000 (tests/too_many_digits.sol#13)\n", + "markdown": "[C.f()](tests/too_many_digits.sol#L9-L15) uses literals with too many digits:\n\t- [x4 = 100000](tests/too_many_digits.sol#L13)\n", "check": "too-many-digits", "impact": "Informational", - "confidence": "Medium", - "description": "C.h (tests/too_many_digits.sol#20-24) uses literals with too many digits:\n\t- x2 = 100000\n", + "confidence": "Medium" + }, + { "elements": [ + { + "type": "function", + "name": "h", + "source_mapping": { + "start": 453, + "length": 113, + "filename_used": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_relative": "tests/too_many_digits.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_short": "tests/too_many_digits.sol", + "is_dependency": false, + "lines": [ + 20, + 21, + 22, + 23, + 24 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 25, + "length": 897, + "filename_used": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_relative": "tests/too_many_digits.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/too_many_digits.sol", + "filename_short": "tests/too_many_digits.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "h()" + } + }, { "type": "node", "name": "x2 = 100000", @@ -549,7 +957,12 @@ } } } - ] + ], + "description": "C.h() (tests/too_many_digits.sol#20-24) uses literals with too many digits:\n\t- x2 = 100000 (tests/too_many_digits.sol#22)\n", + "markdown": "[C.h()](tests/too_many_digits.sol#L20-L24) uses literals with too many digits:\n\t- [x2 = 100000](tests/too_many_digits.sol#L22)\n", + "check": "too-many-digits", + "impact": "Informational", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/too_many_digits.too-many-digits.txt b/tests/expected_json/too_many_digits.too-many-digits.txt index 4e5ecbaa1..621ba8e85 100644 --- a/tests/expected_json/too_many_digits.too-many-digits.txt +++ b/tests/expected_json/too_many_digits.too-many-digits.txt @@ -1,13 +1,13 @@  -C.f (tests/too_many_digits.sol#9-15) uses literals with too many digits: - - x1 = 0x000001 -C.f (tests/too_many_digits.sol#9-15) uses literals with too many digits: - - x2 = 0x0000000000001 -C.f (tests/too_many_digits.sol#9-15) uses literals with too many digits: - - x3 = 1000000000000000000 -C.f (tests/too_many_digits.sol#9-15) uses literals with too many digits: - - x4 = 100000 -C.h (tests/too_many_digits.sol#20-24) uses literals with too many digits: - - x2 = 100000 +C.f() (tests/too_many_digits.sol#9-15) uses literals with too many digits: + - x1 = 0x000001 (tests/too_many_digits.sol#10) +C.f() (tests/too_many_digits.sol#9-15) uses literals with too many digits: + - x2 = 0x0000000000001 (tests/too_many_digits.sol#11) +C.f() (tests/too_many_digits.sol#9-15) uses literals with too many digits: + - x3 = 1000000000000000000 (tests/too_many_digits.sol#12) +C.f() (tests/too_many_digits.sol#9-15) uses literals with too many digits: + - x4 = 100000 (tests/too_many_digits.sol#13) +C.h() (tests/too_many_digits.sol#20-24) uses literals with too many digits: + - x2 = 100000 (tests/too_many_digits.sol#22) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits -tests/too_many_digits.sol analyzed (1 contracts), 5 result(s) found +tests/too_many_digits.sol analyzed (1 contracts with 1 detectors), 5 result(s) found diff --git a/tests/expected_json/tx_origin-0.5.1.tx-origin.json b/tests/expected_json/tx_origin-0.5.1.tx-origin.json index 020e85f5e..c0efe7dd0 100644 --- a/tests/expected_json/tx_origin-0.5.1.tx-origin.json +++ b/tests/expected_json/tx_origin-0.5.1.tx-origin.json @@ -4,11 +4,71 @@ "results": { "detectors": [ { - "check": "tx-origin", - "impact": "Medium", - "confidence": "Medium", - "description": "TxOrigin.bug0() uses tx.origin for authorization: \"require(bool)(tx.origin == owner)\" (tests/tx_origin-0.5.1.sol#10)\n", "elements": [ + { + "type": "function", + "name": "bug0", + "source_mapping": { + "start": 127, + "length": 66, + "filename_used": "/home/travis/build/crytic/slither/tests/tx_origin-0.5.1.sol", + "filename_relative": "tests/tx_origin-0.5.1.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/tx_origin-0.5.1.sol", + "filename_short": "tests/tx_origin-0.5.1.sol", + "is_dependency": false, + "lines": [ + 9, + 10, + 11 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "TxOrigin", + "source_mapping": { + "start": 25, + "length": 442, + "filename_used": "/home/travis/build/crytic/slither/tests/tx_origin-0.5.1.sol", + "filename_relative": "tests/tx_origin-0.5.1.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/tx_origin-0.5.1.sol", + "filename_short": "tests/tx_origin-0.5.1.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "bug0()" + } + }, { "type": "node", "name": "require(bool)(tx.origin == owner)", @@ -93,14 +153,81 @@ } } } - ] - }, - { + ], + "description": "TxOrigin.bug0() (tests/tx_origin-0.5.1.sol#9-11) uses tx.origin for authorization: require(bool)(tx.origin == owner) (tests/tx_origin-0.5.1.sol#10)\n", + "markdown": "[TxOrigin.bug0()](tests/tx_origin-0.5.1.sol#L9-L11) uses tx.origin for authorization: [require(bool)(tx.origin == owner)](tests/tx_origin-0.5.1.sol#L10)\n", "check": "tx-origin", "impact": "Medium", - "confidence": "Medium", - "description": "TxOrigin.bug2() uses tx.origin for authorization: \"tx.origin != owner\" (tests/tx_origin-0.5.1.sol#14)\n", + "confidence": "Medium" + }, + { "elements": [ + { + "type": "function", + "name": "bug2", + "source_mapping": { + "start": 199, + "length": 95, + "filename_used": "/home/travis/build/crytic/slither/tests/tx_origin-0.5.1.sol", + "filename_relative": "tests/tx_origin-0.5.1.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/tx_origin-0.5.1.sol", + "filename_short": "tests/tx_origin-0.5.1.sol", + "is_dependency": false, + "lines": [ + 13, + 14, + 15, + 16, + 17 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "TxOrigin", + "source_mapping": { + "start": 25, + "length": 442, + "filename_used": "/home/travis/build/crytic/slither/tests/tx_origin-0.5.1.sol", + "filename_relative": "tests/tx_origin-0.5.1.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/tx_origin-0.5.1.sol", + "filename_short": "tests/tx_origin-0.5.1.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "bug2()" + } + }, { "type": "node", "name": "tx.origin != owner", @@ -187,7 +314,12 @@ } } } - ] + ], + "description": "TxOrigin.bug2() (tests/tx_origin-0.5.1.sol#13-17) uses tx.origin for authorization: tx.origin != owner (tests/tx_origin-0.5.1.sol#14)\n", + "markdown": "[TxOrigin.bug2()](tests/tx_origin-0.5.1.sol#L13-L17) uses tx.origin for authorization: [tx.origin != owner](tests/tx_origin-0.5.1.sol#L14)\n", + "check": "tx-origin", + "impact": "Medium", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/tx_origin-0.5.1.tx-origin.txt b/tests/expected_json/tx_origin-0.5.1.tx-origin.txt index 24811f6e4..e5e11d02f 100644 --- a/tests/expected_json/tx_origin-0.5.1.tx-origin.txt +++ b/tests/expected_json/tx_origin-0.5.1.tx-origin.txt @@ -1,5 +1,5 @@ -INFO:Detectors: -TxOrigin.bug0() uses tx.origin for authorization: "require(bool)(tx.origin == owner)" (tests/tx_origin-0.5.1.sol#10) -TxOrigin.bug2() uses tx.origin for authorization: "tx.origin != owner" (tests/tx_origin-0.5.1.sol#14) + +TxOrigin.bug0() (tests/tx_origin-0.5.1.sol#9-11) uses tx.origin for authorization: require(bool)(tx.origin == owner) (tests/tx_origin-0.5.1.sol#10) +TxOrigin.bug2() (tests/tx_origin-0.5.1.sol#13-17) uses tx.origin for authorization: tx.origin != owner (tests/tx_origin-0.5.1.sol#14) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin -INFO:Slither:tests/tx_origin-0.5.1.sol analyzed (1 contracts), 2 result(s) found +tests/tx_origin-0.5.1.sol analyzed (1 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/tx_origin.tx-origin.json b/tests/expected_json/tx_origin.tx-origin.json index baa703378..23f4673f4 100644 --- a/tests/expected_json/tx_origin.tx-origin.json +++ b/tests/expected_json/tx_origin.tx-origin.json @@ -4,11 +4,71 @@ "results": { "detectors": [ { - "check": "tx-origin", - "impact": "Medium", - "confidence": "Medium", - "description": "TxOrigin.bug0() uses tx.origin for authorization: \"require(bool)(tx.origin == owner)\" (tests/tx_origin.sol#10)\n", "elements": [ + { + "type": "function", + "name": "bug0", + "source_mapping": { + "start": 116, + "length": 60, + "filename_used": "/home/travis/build/crytic/slither/tests/tx_origin.sol", + "filename_relative": "tests/tx_origin.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/tx_origin.sol", + "filename_short": "tests/tx_origin.sol", + "is_dependency": false, + "lines": [ + 9, + 10, + 11 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "TxOrigin", + "source_mapping": { + "start": 28, + "length": 393, + "filename_used": "/home/travis/build/crytic/slither/tests/tx_origin.sol", + "filename_relative": "tests/tx_origin.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/tx_origin.sol", + "filename_short": "tests/tx_origin.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "bug0()" + } + }, { "type": "node", "name": "require(bool)(tx.origin == owner)", @@ -93,14 +153,81 @@ } } } - ] - }, - { + ], + "description": "TxOrigin.bug0() (tests/tx_origin.sol#9-11) uses tx.origin for authorization: require(bool)(tx.origin == owner) (tests/tx_origin.sol#10)\n", + "markdown": "[TxOrigin.bug0()](tests/tx_origin.sol#L9-L11) uses tx.origin for authorization: [require(bool)(tx.origin == owner)](tests/tx_origin.sol#L10)\n", "check": "tx-origin", "impact": "Medium", - "confidence": "Medium", - "description": "TxOrigin.bug2() uses tx.origin for authorization: \"tx.origin != owner\" (tests/tx_origin.sol#14)\n", + "confidence": "Medium" + }, + { "elements": [ + { + "type": "function", + "name": "bug2", + "source_mapping": { + "start": 182, + "length": 89, + "filename_used": "/home/travis/build/crytic/slither/tests/tx_origin.sol", + "filename_relative": "tests/tx_origin.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/tx_origin.sol", + "filename_short": "tests/tx_origin.sol", + "is_dependency": false, + "lines": [ + 13, + 14, + 15, + 16, + 17 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "TxOrigin", + "source_mapping": { + "start": 28, + "length": 393, + "filename_used": "/home/travis/build/crytic/slither/tests/tx_origin.sol", + "filename_relative": "tests/tx_origin.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/tx_origin.sol", + "filename_short": "tests/tx_origin.sol", + "is_dependency": false, + "lines": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "bug2()" + } + }, { "type": "node", "name": "tx.origin != owner", @@ -187,7 +314,12 @@ } } } - ] + ], + "description": "TxOrigin.bug2() (tests/tx_origin.sol#13-17) uses tx.origin for authorization: tx.origin != owner (tests/tx_origin.sol#14)\n", + "markdown": "[TxOrigin.bug2()](tests/tx_origin.sol#L13-L17) uses tx.origin for authorization: [tx.origin != owner](tests/tx_origin.sol#L14)\n", + "check": "tx-origin", + "impact": "Medium", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/tx_origin.tx-origin.txt b/tests/expected_json/tx_origin.tx-origin.txt index ad8f9b78a..c9f9fbc92 100644 --- a/tests/expected_json/tx_origin.tx-origin.txt +++ b/tests/expected_json/tx_origin.tx-origin.txt @@ -1,5 +1,5 @@ -INFO:Detectors: -TxOrigin.bug0() uses tx.origin for authorization: "require(bool)(tx.origin == owner)" (tests/tx_origin.sol#10) -TxOrigin.bug2() uses tx.origin for authorization: "tx.origin != owner" (tests/tx_origin.sol#14) + +TxOrigin.bug0() (tests/tx_origin.sol#9-11) uses tx.origin for authorization: require(bool)(tx.origin == owner) (tests/tx_origin.sol#10) +TxOrigin.bug2() (tests/tx_origin.sol#13-17) uses tx.origin for authorization: tx.origin != owner (tests/tx_origin.sol#14) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin -INFO:Slither:tests/tx_origin.sol analyzed (1 contracts), 2 result(s) found +tests/tx_origin.sol analyzed (1 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.json b/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.json index 3548d3215..19197cda8 100644 --- a/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.json +++ b/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.json @@ -4,11 +4,58 @@ "results": { "detectors": [ { - "check": "unchecked-lowlevel", - "impact": "Medium", - "confidence": "Medium", - "description": "MyConc.bad(address) (tests/unchecked_lowlevel-0.5.1.sol#2-4) ignores return value by low-level calls \"dst.call.value(msg.value)()\" (tests/unchecked_lowlevel-0.5.1.sol#3)\n", "elements": [ + { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 21, + "length": 96, + "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", + "filename_relative": "tests/unchecked_lowlevel-0.5.1.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", + "filename_short": "tests/unchecked_lowlevel-0.5.1.sol", + "is_dependency": false, + "lines": [ + 2, + 3, + 4 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "MyConc", + "source_mapping": { + "start": 0, + "length": 274, + "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", + "filename_relative": "tests/unchecked_lowlevel-0.5.1.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", + "filename_short": "tests/unchecked_lowlevel-0.5.1.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "bad(address)" + } + }, { "type": "node", "name": "dst.call.value(msg.value)()", @@ -79,59 +126,13 @@ } } } - }, - { - "type": "function", - "name": "bad", - "source_mapping": { - "start": 21, - "length": 96, - "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", - "filename_relative": "tests/unchecked_lowlevel-0.5.1.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", - "filename_short": "tests/unchecked_lowlevel-0.5.1.sol", - "is_dependency": false, - "lines": [ - 2, - 3, - 4 - ], - "starting_column": 5, - "ending_column": 6 - }, - "type_specific_fields": { - "parent": { - "type": "contract", - "name": "MyConc", - "source_mapping": { - "start": 0, - "length": 274, - "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", - "filename_relative": "tests/unchecked_lowlevel-0.5.1.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", - "filename_short": "tests/unchecked_lowlevel-0.5.1.sol", - "is_dependency": false, - "lines": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11 - ], - "starting_column": 1, - "ending_column": 2 - } - }, - "signature": "bad(address)" - } } - ] + ], + "description": "MyConc.bad(address) (tests/unchecked_lowlevel-0.5.1.sol#2-4) ignores return value by dst.call.value(msg.value)() (tests/unchecked_lowlevel-0.5.1.sol#3)\n", + "markdown": "[MyConc.bad(address)](tests/unchecked_lowlevel-0.5.1.sol#L2-L4) ignores return value by [dst.call.value(msg.value)()](tests/unchecked_lowlevel-0.5.1.sol#L3)\n", + "check": "unchecked-lowlevel", + "impact": "Medium", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.txt b/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.txt index 42dbda5b4..59a0478e0 100644 --- a/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.txt +++ b/tests/expected_json/unchecked_lowlevel-0.5.1.unchecked-lowlevel.txt @@ -1,4 +1,4 @@ -INFO:Detectors: -MyConc.bad(address) (tests/unchecked_lowlevel-0.5.1.sol#2-4) ignores return value by low-level calls "dst.call.value(msg.value)()" (tests/unchecked_lowlevel-0.5.1.sol#3) + +MyConc.bad(address) (tests/unchecked_lowlevel-0.5.1.sol#2-4) ignores return value by dst.call.value(msg.value)() (tests/unchecked_lowlevel-0.5.1.sol#3) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls -INFO:Slither:tests/unchecked_lowlevel-0.5.1.sol analyzed (1 contracts), 1 result(s) found +tests/unchecked_lowlevel-0.5.1.sol analyzed (1 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.json b/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.json index 9c964c90b..5c51078ad 100644 --- a/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.json +++ b/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.json @@ -4,11 +4,57 @@ "results": { "detectors": [ { - "check": "unchecked-lowlevel", - "impact": "Medium", - "confidence": "Medium", - "description": "MyConc.bad(address) (tests/unchecked_lowlevel.sol#2-4) ignores return value by low-level calls \"dst.call.value(msg.value)()\" (tests/unchecked_lowlevel.sol#3)\n", "elements": [ + { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 21, + "length": 88, + "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", + "filename_relative": "tests/unchecked_lowlevel.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", + "filename_short": "tests/unchecked_lowlevel.sol", + "is_dependency": false, + "lines": [ + 2, + 3, + 4 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "MyConc", + "source_mapping": { + "start": 0, + "length": 214, + "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", + "filename_relative": "tests/unchecked_lowlevel.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", + "filename_short": "tests/unchecked_lowlevel.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "bad(address)" + } + }, { "type": "node", "name": "dst.call.value(msg.value)()", @@ -78,58 +124,13 @@ } } } - }, - { - "type": "function", - "name": "bad", - "source_mapping": { - "start": 21, - "length": 88, - "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", - "filename_relative": "tests/unchecked_lowlevel.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", - "filename_short": "tests/unchecked_lowlevel.sol", - "is_dependency": false, - "lines": [ - 2, - 3, - 4 - ], - "starting_column": 5, - "ending_column": 6 - }, - "type_specific_fields": { - "parent": { - "type": "contract", - "name": "MyConc", - "source_mapping": { - "start": 0, - "length": 214, - "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", - "filename_relative": "tests/unchecked_lowlevel.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", - "filename_short": "tests/unchecked_lowlevel.sol", - "is_dependency": false, - "lines": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10 - ], - "starting_column": 1, - "ending_column": 2 - } - }, - "signature": "bad(address)" - } } - ] + ], + "description": "MyConc.bad(address) (tests/unchecked_lowlevel.sol#2-4) ignores return value by dst.call.value(msg.value)() (tests/unchecked_lowlevel.sol#3)\n", + "markdown": "[MyConc.bad(address)](tests/unchecked_lowlevel.sol#L2-L4) ignores return value by [dst.call.value(msg.value)()](tests/unchecked_lowlevel.sol#L3)\n", + "check": "unchecked-lowlevel", + "impact": "Medium", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.txt b/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.txt index 18ab55207..7506fb57b 100644 --- a/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.txt +++ b/tests/expected_json/unchecked_lowlevel.unchecked-lowlevel.txt @@ -1,4 +1,4 @@ -INFO:Detectors: -MyConc.bad(address) (tests/unchecked_lowlevel.sol#2-4) ignores return value by low-level calls "dst.call.value(msg.value)()" (tests/unchecked_lowlevel.sol#3) + +MyConc.bad(address) (tests/unchecked_lowlevel.sol#2-4) ignores return value by dst.call.value(msg.value)() (tests/unchecked_lowlevel.sol#3) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls -INFO:Slither:tests/unchecked_lowlevel.sol analyzed (1 contracts), 1 result(s) found +tests/unchecked_lowlevel.sol analyzed (1 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/unchecked_send-0.5.1.unchecked-send.json b/tests/expected_json/unchecked_send-0.5.1.unchecked-send.json index 26bf7efdd..0ac4d1e2e 100644 --- a/tests/expected_json/unchecked_send-0.5.1.unchecked-send.json +++ b/tests/expected_json/unchecked_send-0.5.1.unchecked-send.json @@ -4,11 +4,65 @@ "results": { "detectors": [ { - "check": "unchecked-send", - "impact": "Medium", - "confidence": "Medium", - "description": "MyConc.bad(address) (tests/unchecked_send-0.5.1.sol#2-4) ignores return value by send calls \"dst.send(msg.value)\" (tests/unchecked_send-0.5.1.sol#3)\n", "elements": [ + { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 21, + "length": 86, + "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", + "filename_relative": "tests/unchecked_send-0.5.1.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", + "filename_short": "tests/unchecked_send-0.5.1.sol", + "is_dependency": false, + "lines": [ + 2, + 3, + 4 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "MyConc", + "source_mapping": { + "start": 0, + "length": 419, + "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", + "filename_relative": "tests/unchecked_send-0.5.1.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", + "filename_short": "tests/unchecked_send-0.5.1.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "bad(address)" + } + }, { "type": "node", "name": "dst.send(msg.value)", @@ -86,66 +140,13 @@ } } } - }, - { - "type": "function", - "name": "bad", - "source_mapping": { - "start": 21, - "length": 86, - "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", - "filename_relative": "tests/unchecked_send-0.5.1.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", - "filename_short": "tests/unchecked_send-0.5.1.sol", - "is_dependency": false, - "lines": [ - 2, - 3, - 4 - ], - "starting_column": 5, - "ending_column": 6 - }, - "type_specific_fields": { - "parent": { - "type": "contract", - "name": "MyConc", - "source_mapping": { - "start": 0, - "length": 419, - "filename_used": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", - "filename_relative": "tests/unchecked_send-0.5.1.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", - "filename_short": "tests/unchecked_send-0.5.1.sol", - "is_dependency": false, - "lines": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18 - ], - "starting_column": 1, - "ending_column": 2 - } - }, - "signature": "bad(address)" - } } - ] + ], + "description": "MyConc.bad(address) (tests/unchecked_send-0.5.1.sol#2-4) ignores return value by dst.send(msg.value) (tests/unchecked_send-0.5.1.sol#3)\n", + "markdown": "[MyConc.bad(address)](tests/unchecked_send-0.5.1.sol#L2-L4) ignores return value by [dst.send(msg.value)](tests/unchecked_send-0.5.1.sol#L3)\n", + "check": "unchecked-send", + "impact": "Medium", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/unchecked_send-0.5.1.unchecked-send.txt b/tests/expected_json/unchecked_send-0.5.1.unchecked-send.txt index 9feafa034..62d6a01ef 100644 --- a/tests/expected_json/unchecked_send-0.5.1.unchecked-send.txt +++ b/tests/expected_json/unchecked_send-0.5.1.unchecked-send.txt @@ -1,4 +1,4 @@ -INFO:Detectors: -MyConc.bad(address) (tests/unchecked_send-0.5.1.sol#2-4) ignores return value by send calls "dst.send(msg.value)" (tests/unchecked_send-0.5.1.sol#3) + +MyConc.bad(address) (tests/unchecked_send-0.5.1.sol#2-4) ignores return value by dst.send(msg.value) (tests/unchecked_send-0.5.1.sol#3) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send -INFO:Slither:tests/unchecked_send-0.5.1.sol analyzed (1 contracts), 1 result(s) found +tests/unchecked_send-0.5.1.sol analyzed (1 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/uninitialized-0.5.1.uninitialized-state.json b/tests/expected_json/uninitialized-0.5.1.uninitialized-state.json index eca28e3ca..6b1497e20 100644 --- a/tests/expected_json/uninitialized-0.5.1.uninitialized-state.json +++ b/tests/expected_json/uninitialized-0.5.1.uninitialized-state.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "uninitialized-state", - "impact": "High", - "confidence": "High", - "description": "Uninitialized.destination (tests/uninitialized-0.5.1.sol#5) is never initialized. It is used in:\n\t- transfer (tests/uninitialized-0.5.1.sol#7-9)\n", "elements": [ { "type": "variable", @@ -104,13 +100,14 @@ "signature": "transfer()" } } - ] - }, - { + ], + "description": "Uninitialized.destination (tests/uninitialized-0.5.1.sol#5) is never initialized. It is used in:\n\t- Uninitialized.transfer() (tests/uninitialized-0.5.1.sol#7-9)\n", + "markdown": "[Uninitialized.destination](tests/uninitialized-0.5.1.sol#L5) is never initialized. It is used in:\n\t- [Uninitialized.transfer()](tests/uninitialized-0.5.1.sol#L7-L9)\n", "check": "uninitialized-state", "impact": "High", - "confidence": "High", - "description": "Test.balances (tests/uninitialized-0.5.1.sol#15) is never initialized. It is used in:\n\t- use (tests/uninitialized-0.5.1.sol#23-26)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -218,13 +215,14 @@ "signature": "use()" } } - ] - }, - { + ], + "description": "Test.balances (tests/uninitialized-0.5.1.sol#15) is never initialized. It is used in:\n\t- Test.use() (tests/uninitialized-0.5.1.sol#23-26)\n", + "markdown": "[Test.balances](tests/uninitialized-0.5.1.sol#L15) is never initialized. It is used in:\n\t- [Test.use()](tests/uninitialized-0.5.1.sol#L23-L26)\n", "check": "uninitialized-state", "impact": "High", - "confidence": "High", - "description": "Test2.st (tests/uninitialized-0.5.1.sol#45) is never initialized. It is used in:\n\t- use (tests/uninitialized-0.5.1.sol#53-56)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -338,13 +336,14 @@ "signature": "use()" } } - ] - }, - { + ], + "description": "Test2.st (tests/uninitialized-0.5.1.sol#45) is never initialized. It is used in:\n\t- Test2.use() (tests/uninitialized-0.5.1.sol#53-56)\n", + "markdown": "[Test2.st](tests/uninitialized-0.5.1.sol#L45) is never initialized. It is used in:\n\t- [Test2.use()](tests/uninitialized-0.5.1.sol#L53-L56)\n", "check": "uninitialized-state", "impact": "High", - "confidence": "High", - "description": "Test2.v (tests/uninitialized-0.5.1.sol#47) is never initialized. It is used in:\n\t- init (tests/uninitialized-0.5.1.sol#49-51)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -457,7 +456,12 @@ "signature": "init()" } } - ] + ], + "description": "Test2.v (tests/uninitialized-0.5.1.sol#47) is never initialized. It is used in:\n\t- Test2.init() (tests/uninitialized-0.5.1.sol#49-51)\n", + "markdown": "[Test2.v](tests/uninitialized-0.5.1.sol#L47) is never initialized. It is used in:\n\t- [Test2.init()](tests/uninitialized-0.5.1.sol#L49-L51)\n", + "check": "uninitialized-state", + "impact": "High", + "confidence": "High" } ] } diff --git a/tests/expected_json/uninitialized-0.5.1.uninitialized-state.txt b/tests/expected_json/uninitialized-0.5.1.uninitialized-state.txt index ea27bfd31..9d4d66e14 100644 --- a/tests/expected_json/uninitialized-0.5.1.uninitialized-state.txt +++ b/tests/expected_json/uninitialized-0.5.1.uninitialized-state.txt @@ -1,11 +1,11 @@ -INFO:Detectors: + Uninitialized.destination (tests/uninitialized-0.5.1.sol#5) is never initialized. It is used in: - - transfer (tests/uninitialized-0.5.1.sol#7-9) + - Uninitialized.transfer() (tests/uninitialized-0.5.1.sol#7-9) Test.balances (tests/uninitialized-0.5.1.sol#15) is never initialized. It is used in: - - use (tests/uninitialized-0.5.1.sol#23-26) + - Test.use() (tests/uninitialized-0.5.1.sol#23-26) Test2.st (tests/uninitialized-0.5.1.sol#45) is never initialized. It is used in: - - use (tests/uninitialized-0.5.1.sol#53-56) + - Test2.use() (tests/uninitialized-0.5.1.sol#53-56) Test2.v (tests/uninitialized-0.5.1.sol#47) is never initialized. It is used in: - - init (tests/uninitialized-0.5.1.sol#49-51) + - Test2.init() (tests/uninitialized-0.5.1.sol#49-51) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-state-variables -INFO:Slither:tests/uninitialized-0.5.1.sol analyzed (4 contracts), 4 result(s) found +tests/uninitialized-0.5.1.sol analyzed (4 contracts with 1 detectors), 4 result(s) found diff --git a/tests/expected_json/uninitialized.uninitialized-state.json b/tests/expected_json/uninitialized.uninitialized-state.json index 288a04851..9e598c619 100644 --- a/tests/expected_json/uninitialized.uninitialized-state.json +++ b/tests/expected_json/uninitialized.uninitialized-state.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "uninitialized-state", - "impact": "High", - "confidence": "High", - "description": "Uninitialized.destination (tests/uninitialized.sol#5) is never initialized. It is used in:\n\t- transfer (tests/uninitialized.sol#7-9)\n", "elements": [ { "type": "variable", @@ -104,13 +100,14 @@ "signature": "transfer()" } } - ] - }, - { + ], + "description": "Uninitialized.destination (tests/uninitialized.sol#5) is never initialized. It is used in:\n\t- Uninitialized.transfer() (tests/uninitialized.sol#7-9)\n", + "markdown": "[Uninitialized.destination](tests/uninitialized.sol#L5) is never initialized. It is used in:\n\t- [Uninitialized.transfer()](tests/uninitialized.sol#L7-L9)\n", "check": "uninitialized-state", "impact": "High", - "confidence": "High", - "description": "Test.balances (tests/uninitialized.sol#15) is never initialized. It is used in:\n\t- use (tests/uninitialized.sol#23-26)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -218,13 +215,14 @@ "signature": "use()" } } - ] - }, - { + ], + "description": "Test.balances (tests/uninitialized.sol#15) is never initialized. It is used in:\n\t- Test.use() (tests/uninitialized.sol#23-26)\n", + "markdown": "[Test.balances](tests/uninitialized.sol#L15) is never initialized. It is used in:\n\t- [Test.use()](tests/uninitialized.sol#L23-L26)\n", "check": "uninitialized-state", "impact": "High", - "confidence": "High", - "description": "Test2.st (tests/uninitialized.sol#45) is never initialized. It is used in:\n\t- use (tests/uninitialized.sol#53-56)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -338,13 +336,14 @@ "signature": "use()" } } - ] - }, - { + ], + "description": "Test2.st (tests/uninitialized.sol#45) is never initialized. It is used in:\n\t- Test2.use() (tests/uninitialized.sol#53-56)\n", + "markdown": "[Test2.st](tests/uninitialized.sol#L45) is never initialized. It is used in:\n\t- [Test2.use()](tests/uninitialized.sol#L53-L56)\n", "check": "uninitialized-state", "impact": "High", - "confidence": "High", - "description": "Test2.v (tests/uninitialized.sol#47) is never initialized. It is used in:\n\t- init (tests/uninitialized.sol#49-51)\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -457,7 +456,12 @@ "signature": "init()" } } - ] + ], + "description": "Test2.v (tests/uninitialized.sol#47) is never initialized. It is used in:\n\t- Test2.init() (tests/uninitialized.sol#49-51)\n", + "markdown": "[Test2.v](tests/uninitialized.sol#L47) is never initialized. It is used in:\n\t- [Test2.init()](tests/uninitialized.sol#L49-L51)\n", + "check": "uninitialized-state", + "impact": "High", + "confidence": "High" } ] } diff --git a/tests/expected_json/uninitialized.uninitialized-state.txt b/tests/expected_json/uninitialized.uninitialized-state.txt index a516750bf..43fd9bb17 100644 --- a/tests/expected_json/uninitialized.uninitialized-state.txt +++ b/tests/expected_json/uninitialized.uninitialized-state.txt @@ -1,11 +1,11 @@ -INFO:Detectors: + Uninitialized.destination (tests/uninitialized.sol#5) is never initialized. It is used in: - - transfer (tests/uninitialized.sol#7-9) + - Uninitialized.transfer() (tests/uninitialized.sol#7-9) Test.balances (tests/uninitialized.sol#15) is never initialized. It is used in: - - use (tests/uninitialized.sol#23-26) + - Test.use() (tests/uninitialized.sol#23-26) Test2.st (tests/uninitialized.sol#45) is never initialized. It is used in: - - use (tests/uninitialized.sol#53-56) + - Test2.use() (tests/uninitialized.sol#53-56) Test2.v (tests/uninitialized.sol#47) is never initialized. It is used in: - - init (tests/uninitialized.sol#49-51) + - Test2.init() (tests/uninitialized.sol#49-51) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-state-variables -INFO:Slither:tests/uninitialized.sol analyzed (4 contracts), 4 result(s) found +tests/uninitialized.sol analyzed (4 contracts with 1 detectors), 4 result(s) found diff --git a/tests/expected_json/uninitialized_local_variable.uninitialized-local.json b/tests/expected_json/uninitialized_local_variable.uninitialized-local.json index 7434ab404..b401a27f4 100644 --- a/tests/expected_json/uninitialized_local_variable.uninitialized-local.json +++ b/tests/expected_json/uninitialized_local_variable.uninitialized-local.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "uninitialized-local", - "impact": "Medium", - "confidence": "Medium", - "description": "uint_not_init in Uninitialized.func() (tests/uninitialized_local_variable.sol#4) is a local variable never initialiazed\n", "elements": [ { "type": "variable", @@ -79,59 +75,13 @@ } } } - }, - { - "type": "function", - "name": "func", - "source_mapping": { - "start": 29, - "length": 143, - "filename_used": "/home/travis/build/crytic/slither/tests/uninitialized_local_variable.sol", - "filename_relative": "tests/uninitialized_local_variable.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/uninitialized_local_variable.sol", - "filename_short": "tests/uninitialized_local_variable.sol", - "is_dependency": false, - "lines": [ - 3, - 4, - 5, - 6, - 7 - ], - "starting_column": 5, - "ending_column": 6 - }, - "type_specific_fields": { - "parent": { - "type": "contract", - "name": "Uninitialized", - "source_mapping": { - "start": 0, - "length": 179, - "filename_used": "/home/travis/build/crytic/slither/tests/uninitialized_local_variable.sol", - "filename_relative": "tests/uninitialized_local_variable.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/uninitialized_local_variable.sol", - "filename_short": "tests/uninitialized_local_variable.sol", - "is_dependency": false, - "lines": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9 - ], - "starting_column": 1, - "ending_column": 2 - } - }, - "signature": "func()" - } } - ] + ], + "description": "Uninitialized.func().uint_not_init (tests/uninitialized_local_variable.sol#4) is a local variable never initialiazed\n", + "markdown": "[Uninitialized.func().uint_not_init](tests/uninitialized_local_variable.sol#L4) is a local variable never initialiazed\n", + "check": "uninitialized-local", + "impact": "Medium", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/uninitialized_local_variable.uninitialized-local.txt b/tests/expected_json/uninitialized_local_variable.uninitialized-local.txt index 6a013ffd9..6d5827508 100644 --- a/tests/expected_json/uninitialized_local_variable.uninitialized-local.txt +++ b/tests/expected_json/uninitialized_local_variable.uninitialized-local.txt @@ -1,4 +1,4 @@ -INFO:Detectors: -uint_not_init in Uninitialized.func() (tests/uninitialized_local_variable.sol#4) is a local variable never initialiazed + +Uninitialized.func().uint_not_init (tests/uninitialized_local_variable.sol#4) is a local variable never initialiazed Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables -INFO:Slither:tests/uninitialized_local_variable.sol analyzed (1 contracts), 1 result(s) found +tests/uninitialized_local_variable.sol analyzed (1 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.json b/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.json index 08364d527..7c587e3bd 100644 --- a/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.json +++ b/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "uninitialized-storage", - "impact": "High", - "confidence": "High", - "description": "st_bug in Uninitialized.func() (tests/uninitialized_storage_pointer.sol#10) is a storage variable never initialiazed\n", "elements": [ { "type": "variable", @@ -85,65 +81,13 @@ } } } - }, - { - "type": "function", - "name": "func", - "source_mapping": { - "start": 67, - "length": 143, - "filename_used": "/home/travis/build/crytic/slither/tests/uninitialized_storage_pointer.sol", - "filename_relative": "tests/uninitialized_storage_pointer.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/uninitialized_storage_pointer.sol", - "filename_short": "tests/uninitialized_storage_pointer.sol", - "is_dependency": false, - "lines": [ - 7, - 8, - 9, - 10, - 11, - 12 - ], - "starting_column": 5, - "ending_column": 6 - }, - "type_specific_fields": { - "parent": { - "type": "contract", - "name": "Uninitialized", - "source_mapping": { - "start": 0, - "length": 217, - "filename_used": "/home/travis/build/crytic/slither/tests/uninitialized_storage_pointer.sol", - "filename_relative": "tests/uninitialized_storage_pointer.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/uninitialized_storage_pointer.sol", - "filename_short": "tests/uninitialized_storage_pointer.sol", - "is_dependency": false, - "lines": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14 - ], - "starting_column": 1, - "ending_column": 2 - } - }, - "signature": "func()" - } } - ] + ], + "description": "Uninitialized.func().st_bug (tests/uninitialized_storage_pointer.sol#10) is a storage variable never initialiazed\n", + "markdown": "[Uninitialized.func().st_bug](tests/uninitialized_storage_pointer.sol#L10) is a storage variable never initialiazed\n", + "check": "uninitialized-storage", + "impact": "High", + "confidence": "High" } ] } diff --git a/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.txt b/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.txt index 486ff5ec1..6c104545b 100644 --- a/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.txt +++ b/tests/expected_json/uninitialized_storage_pointer.uninitialized-storage.txt @@ -1,4 +1,4 @@ -INFO:Detectors: -st_bug in Uninitialized.func() (tests/uninitialized_storage_pointer.sol#10) is a storage variable never initialiazed + +Uninitialized.func().st_bug (tests/uninitialized_storage_pointer.sol#10) is a storage variable never initialiazed Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-storage-variables -INFO:Slither:tests/uninitialized_storage_pointer.sol analyzed (1 contracts), 1 result(s) found +tests/uninitialized_storage_pointer.sol analyzed (1 contracts with 1 detectors), 1 result(s) found diff --git a/tests/expected_json/unused_return.unused-return.json b/tests/expected_json/unused_return.unused-return.json index e597b7392..1b84cb75f 100644 --- a/tests/expected_json/unused_return.unused-return.json +++ b/tests/expected_json/unused_return.unused-return.json @@ -4,11 +4,75 @@ "results": { "detectors": [ { - "check": "unused-return", - "impact": "Medium", - "confidence": "Medium", - "description": "User.test(Target) (tests/unused_return.sol#17-29) ignores return value by external calls \"t.f()\" (tests/unused_return.sol#18)\n", "elements": [ + { + "type": "function", + "name": "test", + "source_mapping": { + "start": 239, + "length": 354, + "filename_used": "/home/travis/build/crytic/slither/tests/unused_return.sol", + "filename_relative": "tests/unused_return.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/unused_return.sol", + "filename_short": "tests/unused_return.sol", + "is_dependency": false, + "lines": [ + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "User", + "source_mapping": { + "start": 189, + "length": 406, + "filename_used": "/home/travis/build/crytic/slither/tests/unused_return.sol", + "filename_relative": "tests/unused_return.sol", + "filename_absolute": "/home/travis/build/crytic/slither/tests/unused_return.sol", + "filename_short": "tests/unused_return.sol", + "is_dependency": false, + "lines": [ + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "test(Target)" + } + }, { "type": "node", "name": "t.f()", @@ -96,7 +160,16 @@ } } } - }, + } + ], + "description": "User.test(Target) (tests/unused_return.sol#17-29) ignores return value by t.f() (tests/unused_return.sol#18)\n", + "markdown": "[User.test(Target)](tests/unused_return.sol#L17-L29) ignores return value by [t.f()](tests/unused_return.sol#L18)\n", + "check": "unused-return", + "impact": "Medium", + "confidence": "Medium" + }, + { + "elements": [ { "type": "function", "name": "test", @@ -164,15 +237,7 @@ }, "signature": "test(Target)" } - } - ] - }, - { - "check": "unused-return", - "impact": "Medium", - "confidence": "Medium", - "description": "User.test(Target) (tests/unused_return.sol#17-29) ignores return value by external calls \"a.add(0)\" (tests/unused_return.sol#22)\n", - "elements": [ + }, { "type": "node", "name": "a.add(0)", @@ -260,76 +325,13 @@ } } } - }, - { - "type": "function", - "name": "test", - "source_mapping": { - "start": 239, - "length": 354, - "filename_used": "/home/travis/build/crytic/slither/tests/unused_return.sol", - "filename_relative": "tests/unused_return.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/unused_return.sol", - "filename_short": "tests/unused_return.sol", - "is_dependency": false, - "lines": [ - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29 - ], - "starting_column": 5, - "ending_column": 6 - }, - "type_specific_fields": { - "parent": { - "type": "contract", - "name": "User", - "source_mapping": { - "start": 189, - "length": 406, - "filename_used": "/home/travis/build/crytic/slither/tests/unused_return.sol", - "filename_relative": "tests/unused_return.sol", - "filename_absolute": "/home/travis/build/crytic/slither/tests/unused_return.sol", - "filename_short": "tests/unused_return.sol", - "is_dependency": false, - "lines": [ - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30 - ], - "starting_column": 1, - "ending_column": 2 - } - }, - "signature": "test(Target)" - } } - ] + ], + "description": "User.test(Target) (tests/unused_return.sol#17-29) ignores return value by a.add(0) (tests/unused_return.sol#22)\n", + "markdown": "[User.test(Target)](tests/unused_return.sol#L17-L29) ignores return value by [a.add(0)](tests/unused_return.sol#L22)\n", + "check": "unused-return", + "impact": "Medium", + "confidence": "Medium" } ] } diff --git a/tests/expected_json/unused_return.unused-return.txt b/tests/expected_json/unused_return.unused-return.txt index cae24dcf1..82ac0d99a 100644 --- a/tests/expected_json/unused_return.unused-return.txt +++ b/tests/expected_json/unused_return.unused-return.txt @@ -1,5 +1,5 @@ -INFO:Detectors: -User.test(Target) (tests/unused_return.sol#17-29) ignores return value by external calls "t.f()" (tests/unused_return.sol#18) -User.test(Target) (tests/unused_return.sol#17-29) ignores return value by external calls "a.add(0)" (tests/unused_return.sol#22) + +User.test(Target) (tests/unused_return.sol#17-29) ignores return value by t.f() (tests/unused_return.sol#18) +User.test(Target) (tests/unused_return.sol#17-29) ignores return value by a.add(0) (tests/unused_return.sol#22) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return -INFO:Slither:tests/unused_return.sol analyzed (3 contracts), 2 result(s) found +tests/unused_return.sol analyzed (3 contracts with 1 detectors), 2 result(s) found diff --git a/tests/expected_json/unused_state.unused-state.json b/tests/expected_json/unused_state.unused-state.json index 3a01bcb4a..58eec6bc6 100644 --- a/tests/expected_json/unused_state.unused-state.json +++ b/tests/expected_json/unused_state.unused-state.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "unused-state", - "impact": "Informational", - "confidence": "High", - "description": "A.unused (tests/unused_state.sol#4) is never used in B\n", "elements": [ { "type": "variable", @@ -76,13 +72,14 @@ "ending_column": 2 } } - ] - }, - { + ], + "description": "A.unused (tests/unused_state.sol#4) is never used in B (tests/unused_state.sol#11-16)\n", + "markdown": "[A.unused](tests/unused_state.sol#L4) is never used in [B](tests/unused_state.sol#L11-L16)\n", "check": "unused-state", "impact": "Informational", - "confidence": "High", - "description": "A.unused2 (tests/unused_state.sol#5) is never used in B\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -151,13 +148,14 @@ "ending_column": 2 } } - ] - }, - { + ], + "description": "A.unused2 (tests/unused_state.sol#5) is never used in B (tests/unused_state.sol#11-16)\n", + "markdown": "[A.unused2](tests/unused_state.sol#L5) is never used in [B](tests/unused_state.sol#L11-L16)\n", "check": "unused-state", "impact": "Informational", - "confidence": "High", - "description": "A.unused3 (tests/unused_state.sol#6) is never used in B\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -226,13 +224,14 @@ "ending_column": 2 } } - ] - }, - { + ], + "description": "A.unused3 (tests/unused_state.sol#6) is never used in B (tests/unused_state.sol#11-16)\n", + "markdown": "[A.unused3](tests/unused_state.sol#L6) is never used in [B](tests/unused_state.sol#L11-L16)\n", "check": "unused-state", "impact": "Informational", - "confidence": "High", - "description": "A.unused4 (tests/unused_state.sol#7) is never used in B\n", + "confidence": "High" + }, + { "elements": [ { "type": "variable", @@ -301,7 +300,12 @@ "ending_column": 2 } } - ] + ], + "description": "A.unused4 (tests/unused_state.sol#7) is never used in B (tests/unused_state.sol#11-16)\n", + "markdown": "[A.unused4](tests/unused_state.sol#L7) is never used in [B](tests/unused_state.sol#L11-L16)\n", + "check": "unused-state", + "impact": "Informational", + "confidence": "High" } ] } diff --git a/tests/expected_json/unused_state.unused-state.txt b/tests/expected_json/unused_state.unused-state.txt index 66be3708e..c719aa7ad 100644 --- a/tests/expected_json/unused_state.unused-state.txt +++ b/tests/expected_json/unused_state.unused-state.txt @@ -1,7 +1,7 @@ -INFO:Detectors: -A.unused (tests/unused_state.sol#4) is never used in B -A.unused2 (tests/unused_state.sol#5) is never used in B -A.unused3 (tests/unused_state.sol#6) is never used in B -A.unused4 (tests/unused_state.sol#7) is never used in B + +A.unused (tests/unused_state.sol#4) is never used in B (tests/unused_state.sol#11-16) +A.unused2 (tests/unused_state.sol#5) is never used in B (tests/unused_state.sol#11-16) +A.unused3 (tests/unused_state.sol#6) is never used in B (tests/unused_state.sol#11-16) +A.unused4 (tests/unused_state.sol#7) is never used in B (tests/unused_state.sol#11-16) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variables -INFO:Slither:tests/unused_state.sol analyzed (2 contracts), 4 result(s) found +tests/unused_state.sol analyzed (2 contracts with 1 detectors), 4 result(s) found diff --git a/tests/expected_json/void-cst.void-cst.json b/tests/expected_json/void-cst.void-cst.json index ab97b9d7d..1bb590390 100644 --- a/tests/expected_json/void-cst.void-cst.json +++ b/tests/expected_json/void-cst.void-cst.json @@ -4,10 +4,6 @@ "results": { "detectors": [ { - "check": "void-cst", - "impact": "Low", - "confidence": "High", - "description": "Void constructor called in D.constructor() (tests/void-cst.sol#10-12):\n\t-C() tests/void-cst.sol#10\n", "elements": [ { "type": "function", @@ -123,7 +119,12 @@ } } } - ] + ], + "description": "Void constructor called in D.constructor() (tests/void-cst.sol#10-12):\n\t- C() (tests/void-cst.sol#10)\n", + "markdown": "Void constructor called in [D.constructor()](tests/void-cst.sol#L10-L12):\n\t- [C()](tests/void-cst.sol#L10)\n", + "check": "void-cst", + "impact": "Low", + "confidence": "High" } ] } diff --git a/tests/expected_json/void-cst.void-cst.txt b/tests/expected_json/void-cst.void-cst.txt index cc3473967..95daeabe6 100644 --- a/tests/expected_json/void-cst.void-cst.txt +++ b/tests/expected_json/void-cst.void-cst.txt @@ -1,5 +1,5 @@ -INFO:Detectors: + Void constructor called in D.constructor() (tests/void-cst.sol#10-12): - -C() tests/void-cst.sol#10 + - C() (tests/void-cst.sol#10) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#void-constructor -INFO:Slither:tests/void-cst.sol analyzed (2 contracts), 1 result(s) found +tests/void-cst.sol analyzed (2 contracts with 1 detectors), 1 result(s) found From f70e89bf12c1d5211050ea2b7de7bc785af42778 Mon Sep 17 00:00:00 2001 From: Josselin Date: Tue, 12 Nov 2019 10:19:30 +0100 Subject: [PATCH 2/2] Create utils.output.Output class to handle json output Remove add*_json function --- .../slither_my_plugin/detectors/example.py | 2 +- slither/__main__.py | 4 +- slither/detectors/abstract_detector.py | 72 +-- .../detectors/attributes/const_functions.py | 8 +- .../detectors/attributes/constant_pragma.py | 4 +- .../detectors/attributes/incorrect_solc.py | 2 +- slither/detectors/attributes/locked_ether.py | 2 +- .../erc/incorrect_erc20_interface.py | 2 +- .../erc/incorrect_erc721_interface.py | 4 +- .../erc/unindexed_event_parameters.py | 8 +- slither/detectors/examples/backdoor.py | 4 +- slither/detectors/functions/arbitrary_send.py | 4 +- .../detectors/functions/complex_function.py | 7 +- .../detectors/functions/external_function.py | 4 +- slither/detectors/functions/suicidal.py | 4 +- .../naming_convention/naming_convention.py | 60 +-- .../detectors/operations/block_timestamp.py | 4 +- .../detectors/operations/low_level_calls.py | 4 +- .../operations/unused_return_values.py | 4 +- .../detectors/operations/void_constructor.py | 4 +- .../detectors/reentrancy/reentrancy_benign.py | 12 +- .../detectors/reentrancy/reentrancy_eth.py | 12 +- .../reentrancy_read_before_write.py | 10 +- slither/detectors/shadowing/abstract.py | 4 +- .../detectors/shadowing/builtin_symbols.py | 4 +- slither/detectors/shadowing/local.py | 4 +- slither/detectors/shadowing/state.py | 5 +- slither/detectors/source/rtlo.py | 11 +- slither/detectors/statements/assembly.py | 4 +- slither/detectors/statements/calls_in_loop.py | 4 +- .../statements/controlled_delegatecall.py | 4 +- .../detectors/statements/deprecated_calls.py | 4 +- .../statements/incorrect_strict_equality.py | 4 +- .../detectors/statements/too_many_digits.py | 4 +- slither/detectors/statements/tx_origin.py | 5 +- .../possible_const_state_variables.py | 2 +- .../uninitialized_local_variables.py | 2 +- .../uninitialized_state_variables.py | 2 +- .../uninitialized_storage_variables.py | 2 +- .../variables/unused_state_variables.py | 2 +- slither/printers/abstract_printer.py | 32 +- slither/printers/call/call_graph.py | 6 +- slither/printers/functions/authorization.py | 6 +- slither/printers/functions/cfg.py | 6 +- slither/printers/guidance/echidna.py | 4 +- slither/printers/inheritance/inheritance.py | 4 +- .../printers/inheritance/inheritance_graph.py | 6 +- slither/printers/summary/constructor_calls.py | 83 ++-- slither/printers/summary/contract.py | 15 +- slither/printers/summary/data_depenency.py | 6 +- slither/printers/summary/function.py | 6 +- slither/printers/summary/function_ids.py | 6 +- slither/printers/summary/human_summary.py | 9 +- slither/printers/summary/modifier_calls.py | 6 +- slither/printers/summary/require_calls.py | 6 +- slither/printers/summary/slithir.py | 32 +- slither/printers/summary/slithir_ssa.py | 22 +- slither/printers/summary/variable_order.py | 7 +- slither/slither.py | 2 +- slither/tools/erc_conformance/__main__.py | 6 +- slither/tools/erc_conformance/erc/erc20.py | 8 +- slither/tools/erc_conformance/erc/ercs.py | 57 ++- slither/tools/kspec_coverage/analysis.py | 43 +- slither/tools/upgradeability/__main__.py | 12 +- .../upgradeability/check_initialization.py | 28 +- .../check_variable_initialization.py | 8 +- .../upgradeability/compare_function_ids.py | 32 +- .../upgradeability/compare_variables_order.py | 22 +- .../tools/upgradeability/constant_checks.py | 26 +- slither/utils/json_utils.py | 452 ----------------- slither/utils/output.py | 454 ++++++++++++++++++ 71 files changed, 826 insertions(+), 894 deletions(-) delete mode 100644 slither/utils/json_utils.py create mode 100644 slither/utils/output.py diff --git a/plugin_example/slither_my_plugin/detectors/example.py b/plugin_example/slither_my_plugin/detectors/example.py index ed850d361..5d5a8811e 100644 --- a/plugin_example/slither_my_plugin/detectors/example.py +++ b/plugin_example/slither_my_plugin/detectors/example.py @@ -23,6 +23,6 @@ class Example(AbstractDetector): info = 'This is an example!' - json = self.generate_json_result(info) + json = self.generate_result(info) return [json] diff --git a/slither/__main__.py b/slither/__main__.py index 699134c58..e982b8cde 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -19,7 +19,7 @@ from slither.detectors.abstract_detector import (AbstractDetector, from slither.printers import all_printers from slither.printers.abstract_printer import AbstractPrinter from slither.slither import Slither -from slither.utils.json_utils import output_json +from slither.utils.output import output_to_json from slither.utils.output_capture import StandardOutputCapture from slither.utils.colors import red, yellow, set_colorization_enabled from slither.utils.command_line import (output_detectors, output_results_to_markdown, @@ -638,7 +638,7 @@ def main_impl(all_detector_classes, all_printer_classes): 'stderr': StandardOutputCapture.get_stderr_output() } StandardOutputCapture.disable() - output_json(None if outputting_json_stdout else args.json, output_error, json_results) + output_to_json(None if outputting_json_stdout else args.json, output_error, json_results) # Exit with the appropriate status code if output_error: diff --git a/slither/detectors/abstract_detector.py b/slither/detectors/abstract_detector.py index 06a6ae8fa..765b79d15 100644 --- a/slither/detectors/abstract_detector.py +++ b/slither/detectors/abstract_detector.py @@ -4,7 +4,7 @@ import re from slither.utils.colors import green, yellow, red from slither.formatters.exceptions import FormatImpossible from slither.formatters.utils.patches import apply_patch, create_diff -from slither.utils import json_utils +from slither.utils.output import Output class IncorrectDetectorInitialization(Exception): @@ -103,10 +103,12 @@ class AbstractDetector(metaclass=abc.ABCMeta): @abc.abstractmethod def _detect(self): """TODO Documentation""" - return + return [] def detect(self): all_results = self._detect() + # Keep only dictionaries + all_results = [r.data for r in all_results] results = [] # only keep valid result, and remove dupplicate [results.append(r) for r in all_results if self.slither.valid_result(r) and r not in results] @@ -170,65 +172,17 @@ class AbstractDetector(metaclass=abc.ABCMeta): def color(self): return classification_colors[self.IMPACT] - def generate_json_result(self, info, additional_fields=None): - d = json_utils.generate_json_result(info, - additional_fields, - standard_format=self.STANDARD_JSON, - markdown_root=self.slither.markdown_root) + def generate_result(self, info, additional_fields=None): + output = Output(info, + additional_fields, + standard_format=self.STANDARD_JSON, + markdown_root=self.slither.markdown_root) - d['check'] = self.ARGUMENT - d['impact'] = classification_txt[self.IMPACT] - d['confidence'] = classification_txt[self.CONFIDENCE] + output.data['check'] = self.ARGUMENT + output.data['impact'] = classification_txt[self.IMPACT] + output.data['confidence'] = classification_txt[self.CONFIDENCE] - return d - - @staticmethod - def add_variable_to_json(e, d, additional_fields=None): - json_utils.add_variable_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_variables_to_json(e, d): - json_utils.add_variables_to_json(e, d) - - @staticmethod - def add_contract_to_json(e, d, additional_fields=None): - json_utils.add_contract_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_function_to_json(e, d, additional_fields=None): - json_utils.add_function_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_functions_to_json(e, d, additional_fields=None): - json_utils.add_functions_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_enum_to_json(e, d, additional_fields=None): - json_utils.add_enum_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_struct_to_json(e, d, additional_fields=None): - json_utils.add_struct_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_event_to_json(e, d, additional_fields=None): - json_utils.add_event_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_pragma_to_json(e, d, additional_fields=None): - json_utils.add_pragma_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_node_to_json(e, d, additional_fields=None): - json_utils.add_node_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_nodes_to_json(e, d): - json_utils.add_nodes_to_json(e, d) - - @staticmethod - def add_other_to_json(name, source_mapping, d, slither, additional_fields=None): - json_utils.add_other_to_json(name, source_mapping, d, slither, additional_fields=additional_fields) + return output @staticmethod def _format(slither, result): diff --git a/slither/detectors/attributes/const_functions.py b/slither/detectors/attributes/const_functions.py index 99247b91b..6e892a626 100644 --- a/slither/detectors/attributes/const_functions.py +++ b/slither/detectors/attributes/const_functions.py @@ -59,9 +59,9 @@ All the calls to `get` revert, breaking Bob's smart contract execution.''' attr = 'view' if f.view else 'pure' info = [f, f' is declared {attr} but contains assembly code\n'] - json = self.generate_json_result(info, {'contains_assembly': True}) + res = self.generate_result(info, {'contains_assembly': True}) - results.append(json) + results.append(res) variables_written = f.all_state_variables_written() if variables_written: @@ -72,9 +72,9 @@ All the calls to `get` revert, breaking Bob's smart contract execution.''' for variable_written in variables_written: info += ['\t- ', variable_written, '\n'] - json = self.generate_json_result(info, {'contains_assembly': False}) + res = self.generate_result(info, {'contains_assembly': False}) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/attributes/constant_pragma.py b/slither/detectors/attributes/constant_pragma.py index d931d6a3d..b7d593357 100644 --- a/slither/detectors/attributes/constant_pragma.py +++ b/slither/detectors/attributes/constant_pragma.py @@ -36,9 +36,9 @@ class ConstantPragma(AbstractDetector): for p in pragma: info += ["\t- ", p, "\n"] - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/attributes/incorrect_solc.py b/slither/detectors/attributes/incorrect_solc.py index 6a48bc3c7..f63a2bdf2 100644 --- a/slither/detectors/attributes/incorrect_solc.py +++ b/slither/detectors/attributes/incorrect_solc.py @@ -102,7 +102,7 @@ Use Solidity 0.4.25 or 0.5.3. Consider using the latest version of Solidity for for (reason, p) in disallowed_pragmas: info = ["Pragma version", p, f" {reason}\n"] - json = self.generate_json_result(info) + json = self.generate_result(info) results.append(json) diff --git a/slither/detectors/attributes/locked_ether.py b/slither/detectors/attributes/locked_ether.py index 3de56c00c..97ffb0db2 100644 --- a/slither/detectors/attributes/locked_ether.py +++ b/slither/detectors/attributes/locked_ether.py @@ -80,7 +80,7 @@ Every ether sent to `Locked` will be lost.''' info += [f"\t - ", function, "\n"] info += "\tBut does not have a function to withdraw the ether\n" - json = self.generate_json_result(info) + json = self.generate_result(info) results.append(json) diff --git a/slither/detectors/erc/incorrect_erc20_interface.py b/slither/detectors/erc/incorrect_erc20_interface.py index a9aa4ad77..b7782a66a 100644 --- a/slither/detectors/erc/incorrect_erc20_interface.py +++ b/slither/detectors/erc/incorrect_erc20_interface.py @@ -88,7 +88,7 @@ contract Token{ if functions: for function in functions: info = [c, " has incorrect ERC20 function interface:", function, "\n"] - json = self.generate_json_result(info) + json = self.generate_result(info) results.append(json) diff --git a/slither/detectors/erc/incorrect_erc721_interface.py b/slither/detectors/erc/incorrect_erc721_interface.py index bce1695b1..e6a484631 100644 --- a/slither/detectors/erc/incorrect_erc721_interface.py +++ b/slither/detectors/erc/incorrect_erc721_interface.py @@ -87,8 +87,8 @@ contract Token{ if functions: for function in functions: info = [c, " has incorrect ERC721 function interface:", function, "\n"] - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/erc/unindexed_event_parameters.py b/slither/detectors/erc/unindexed_event_parameters.py index 1e382da59..096c63f16 100644 --- a/slither/detectors/erc/unindexed_event_parameters.py +++ b/slither/detectors/erc/unindexed_event_parameters.py @@ -76,12 +76,10 @@ In this case, Transfer and Approval events should have the 'indexed' keyword on info = ["ERC20 event ", event, f"does not index parameter {parameter}\n"] # Add the events to the JSON (note: we do not add the params/vars as they have no source mapping). - json = self.generate_json_result(info) + res = self.generate_result(info) - self.add_event_to_json(event, json, { - "parameter_name": parameter.name - }) - results.append(json) + res.add(event, {"parameter_name": parameter.name}) + results.append(res) return results diff --git a/slither/detectors/examples/backdoor.py b/slither/detectors/examples/backdoor.py index d9f00979e..76511d018 100644 --- a/slither/detectors/examples/backdoor.py +++ b/slither/detectors/examples/backdoor.py @@ -29,8 +29,8 @@ class Backdoor(AbstractDetector): info = ['Backdoor function found in ', f, '\n'] # Add the result in result - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/functions/arbitrary_send.py b/slither/detectors/functions/arbitrary_send.py index 4a14873a9..2c608e73a 100644 --- a/slither/detectors/functions/arbitrary_send.py +++ b/slither/detectors/functions/arbitrary_send.py @@ -114,8 +114,8 @@ Bob calls `setDestination` and `withdraw`. As a result he withdraws the contract for node in nodes: info += ['\t- ', node, '\n'] - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/functions/complex_function.py b/slither/detectors/functions/complex_function.py index fae9a0923..21add9239 100644 --- a/slither/detectors/functions/complex_function.py +++ b/slither/detectors/functions/complex_function.py @@ -31,6 +31,7 @@ class ComplexFunction(AbstractDetector): CAUSE_EXTERNAL_CALL = "external_calls" CAUSE_STATE_VARS = "state_vars" + STANDARD_JSON = True @staticmethod def detect_complex_func(func): @@ -104,14 +105,14 @@ class ComplexFunction(AbstractDetector): info = info + "\n" self.log(info) - json = self.generate_json_result(info) - self.add_function_to_json(func, json, { + res = self.generate_result(info) + res.add(func, { 'high_number_of_external_calls': cause == self.CAUSE_EXTERNAL_CALL, 'high_number_of_branches': cause == self.CAUSE_CYCLOMATIC, 'high_number_of_state_variables': cause == self.CAUSE_STATE_VARS }) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/functions/external_function.py b/slither/detectors/functions/external_function.py index 7b48be5ba..f5d9aad61 100644 --- a/slither/detectors/functions/external_function.py +++ b/slither/detectors/functions/external_function.py @@ -187,9 +187,9 @@ class ExternalFunction(AbstractDetector): for other_function_definition in all_function_definitions: info += [f"\t- ", other_function_definition, "\n"] - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/functions/suicidal.py b/slither/detectors/functions/suicidal.py index 2dc28cf13..a3599fcad 100644 --- a/slither/detectors/functions/suicidal.py +++ b/slither/detectors/functions/suicidal.py @@ -75,8 +75,8 @@ Bob calls `kill` and destructs the contract.''' info = [func, " allows anyone to destruct the contract\n"] - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/naming_convention/naming_convention.py b/slither/detectors/naming_convention/naming_convention.py index 93825e419..3f07d1cba 100644 --- a/slither/detectors/naming_convention/naming_convention.py +++ b/slither/detectors/naming_convention/naming_convention.py @@ -62,34 +62,34 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 if not self.is_cap_words(contract.name): info = ["Contract ", contract, " is not in CapWords\n"] - json = self.generate_json_result(info) - self.add_contract_to_json(contract, json, { + res = self.generate_result(info) + res.add(contract, { "target": "contract", "convention": "CapWords" }) - results.append(json) + results.append(res) for struct in contract.structures_declared: if not self.is_cap_words(struct.name): info = ["Struct ", struct, " is not in CapWords\n"] - json = self.generate_json_result(info) - self.add_struct_to_json(struct, json, { + res = self.generate_result(info) + res.add(struct, { "target": "structure", "convention": "CapWords" }) - results.append(json) + results.append(res) for event in contract.events_declared: if not self.is_cap_words(event.name): info = ["Event ", event, " is not in CapWords\n"] - json = self.generate_json_result(info) - self.add_event_to_json(event, json, { + res = self.generate_result(info) + res.add(event, { "target": "event", "convention": "CapWords" }) - results.append(json) + results.append(res) for func in contract.functions_declared: if func.is_constructor: @@ -101,12 +101,12 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 continue info = ["Function ", func, " is not in mixedCase\n"] - json = self.generate_json_result(info) - self.add_function_to_json(func, json, { + res = self.generate_result(info) + res.add(func, { "target": "function", "convention": "mixedCase" }) - results.append(json) + results.append(res) for argument in func.parameters: # Ignore parameter names that are not specified i.e. empty strings @@ -119,24 +119,24 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 if not correct_naming: info = ["Parameter ", argument, " is not in mixedCase\n"] - json = self.generate_json_result(info) - self.add_variable_to_json(argument, json, { + res = self.generate_result(info) + res.add(argument, { "target": "parameter", "convention": "mixedCase" }) - results.append(json) + results.append(res) for var in contract.state_variables_declared: if self.should_avoid_name(var.name): if not self.is_upper_case_with_underscores(var.name): info = ["Variable ", var," used l, O, I, which should not be used\n"] - json = self.generate_json_result(info) - self.add_variable_to_json(var, json, { + res = self.generate_result(info) + res.add(var, { "target": "variable", "convention": "l_O_I_should_not_be_used" }) - results.append(json) + results.append(res) if var.is_constant is True: # For ERC20 compatibility @@ -146,12 +146,12 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 if not self.is_upper_case_with_underscores(var.name): info = ["Constant ", var," is not in UPPER_CASE_WITH_UNDERSCORES\n"] - json = self.generate_json_result(info) - self.add_variable_to_json(var, json, { + res = self.generate_result(info) + res.add(var, { "target": "variable_constant", "convention": "UPPER_CASE_WITH_UNDERSCORES" }) - results.append(json) + results.append(res) else: if var.visibility == 'private': @@ -161,34 +161,34 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2 if not correct_naming: info = ["Variable ", var, " is not in mixedCase\n"] - json = self.generate_json_result(info) - self.add_variable_to_json(var, json, { + res = self.generate_result(info) + res.add(var, { "target": "variable", "convention": "mixedCase" }) - results.append(json) + results.append(res) for enum in contract.enums_declared: if not self.is_cap_words(enum.name): info = ["Enum ", enum, " is not in CapWords\n"] - json = self.generate_json_result(info) - self.add_enum_to_json(enum, json, { + res = self.generate_result(info) + res.add(enum, { "target": "enum", "convention": "CapWords" }) - results.append(json) + results.append(res) for modifier in contract.modifiers_declared: if not self.is_mixed_case(modifier.name): info = ["Modifier ", modifier, " is not in mixedCase\n"] - json = self.generate_json_result(info) - self.add_function_to_json(modifier, json, { + res = self.generate_result(info) + res.add(modifier, { "target": "modifier", "convention": "mixedCase" }) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/operations/block_timestamp.py b/slither/detectors/operations/block_timestamp.py index 23ad8e178..6dc76ae50 100644 --- a/slither/detectors/operations/block_timestamp.py +++ b/slither/detectors/operations/block_timestamp.py @@ -75,8 +75,8 @@ class Timestamp(AbstractDetector): for node in nodes: info += ['\t- ', node, '\n'] - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/operations/low_level_calls.py b/slither/detectors/operations/low_level_calls.py index c22ff8139..1a46a9909 100644 --- a/slither/detectors/operations/low_level_calls.py +++ b/slither/detectors/operations/low_level_calls.py @@ -53,8 +53,8 @@ class LowLevelCalls(AbstractDetector): for node in nodes: info += ['\t- ', node, '\n'] - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/operations/unused_return_values.py b/slither/detectors/operations/unused_return_values.py index a8233a6d8..b1e2b6d08 100644 --- a/slither/detectors/operations/unused_return_values.py +++ b/slither/detectors/operations/unused_return_values.py @@ -76,9 +76,9 @@ contract MyConc{ for node in unused_return: info = [f, f" ignores return value by ", node, "\n"] - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/operations/void_constructor.py b/slither/detectors/operations/void_constructor.py index 181a5ae50..74abd1329 100644 --- a/slither/detectors/operations/void_constructor.py +++ b/slither/detectors/operations/void_constructor.py @@ -39,7 +39,7 @@ By reading B's constructor definition, the reader might assume that `A()` initia info = ["Void constructor called in ", cst, ":\n"] info += ["\t- ", node, "\n"] - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/reentrancy/reentrancy_benign.py b/slither/detectors/reentrancy/reentrancy_benign.py index 79dfec78f..2ff6e8475 100644 --- a/slither/detectors/reentrancy/reentrancy_benign.py +++ b/slither/detectors/reentrancy/reentrancy_benign.py @@ -95,14 +95,14 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr # Create our JSON result - json = self.generate_json_result(info) + res = self.generate_result(info) # Add the function with the re-entrancy first - self.add_function_to_json(func, json) + res.add(func) # Add all underlying calls in the function which are potentially problematic. for call_info in calls: - self.add_node_to_json(call_info, json, { + res.add(call_info, { "underlying_type": "external_calls" }) @@ -111,18 +111,18 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr # If the calls are not the same ones that send eth, add the eth sending nodes. if calls != send_eth: for call_info in send_eth: - self.add_node_to_json(call_info, json, { + res.add(call_info, { "underlying_type": "external_calls_sending_eth" }) # Add all variables written via nodes which write them. for (v, node) in varsWritten: - self.add_node_to_json(node, json, { + res.add(node, { "underlying_type": "variables_written", "variable_name": v.name }) # Append our result - results.append(json) + results.append(res) return results diff --git a/slither/detectors/reentrancy/reentrancy_eth.py b/slither/detectors/reentrancy/reentrancy_eth.py index b0d501ec1..a5f0c0365 100644 --- a/slither/detectors/reentrancy/reentrancy_eth.py +++ b/slither/detectors/reentrancy/reentrancy_eth.py @@ -95,14 +95,14 @@ Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw m info += ['\t- ', v, ' in ', node, '\n'] # Create our JSON result - json = self.generate_json_result(info) + res = self.generate_result(info) # Add the function with the re-entrancy first - self.add_function_to_json(func, json) + res.add(func) # Add all underlying calls in the function which are potentially problematic. for call_info in calls: - self.add_node_to_json(call_info, json, { + res.add(call_info, { "underlying_type": "external_calls" }) @@ -111,18 +111,18 @@ Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw m # If the calls are not the same ones that send eth, add the eth sending nodes. if calls != send_eth: for call_info in send_eth: - self.add_node_to_json(call_info, json, { + res.add(call_info, { "underlying_type": "external_calls_sending_eth" }) # Add all variables written via nodes which write them. for (v, node) in varsWritten: - self.add_node_to_json(node, json, { + res.add(node, { "underlying_type": "variables_written", "variable_name": v.name }) # Append our result - results.append(json) + results.append(res) return results diff --git a/slither/detectors/reentrancy/reentrancy_read_before_write.py b/slither/detectors/reentrancy/reentrancy_read_before_write.py index 6389847fc..f28b5b615 100644 --- a/slither/detectors/reentrancy/reentrancy_read_before_write.py +++ b/slither/detectors/reentrancy/reentrancy_read_before_write.py @@ -88,25 +88,25 @@ Do not report reentrancies that involve ethers (see `reentrancy-eth`)''' info += ['\t- ', v, ' in ', node, '\n'] # Create our JSON result - json = self.generate_json_result(info) + res = self.generate_result(info) # Add the function with the re-entrancy first - self.add_function_to_json(func, json) + res.add(func) # Add all underlying calls in the function which are potentially problematic. for call_info in calls: - self.add_node_to_json(call_info, json, { + res.add(call_info, { "underlying_type": "external_calls" }) # Add all variables written via nodes which write them. for (v, node) in varsWritten: - self.add_node_to_json(node, json, { + res.add(node, { "underlying_type": "variables_written", "variable_name": v.name }) # Append our result - results.append(json) + results.append(res) return results diff --git a/slither/detectors/shadowing/abstract.py b/slither/detectors/shadowing/abstract.py index f2e7c7119..d882a09a3 100644 --- a/slither/detectors/shadowing/abstract.py +++ b/slither/detectors/shadowing/abstract.py @@ -69,8 +69,8 @@ contract DerivedContract is BaseContract{ for var in variables: info += ["\t- ", var, "\n"] - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/shadowing/builtin_symbols.py b/slither/detectors/shadowing/builtin_symbols.py index c0bf4e8b0..1af228c5a 100644 --- a/slither/detectors/shadowing/builtin_symbols.py +++ b/slither/detectors/shadowing/builtin_symbols.py @@ -127,7 +127,7 @@ contract Bug { info = [shadow_object, f' ({shadow_type}) shadows built-in symbol"\n'] - json = self.generate_json_result(info) - results.append(json) + res = self.generate_result(info) + results.append(res) return results diff --git a/slither/detectors/shadowing/local.py b/slither/detectors/shadowing/local.py index 0da45cf99..7f00f495d 100644 --- a/slither/detectors/shadowing/local.py +++ b/slither/detectors/shadowing/local.py @@ -109,8 +109,8 @@ contract Bug { info += ["\t- ", overshadowed_entry[1], f" ({overshadowed_entry[0]})\n"] # Generate relevant JSON data for this shadowing definition. - json = self.generate_json_result(info) + res = self.generate_result(info) - results.append(json) + results.append(res) return results diff --git a/slither/detectors/shadowing/state.py b/slither/detectors/shadowing/state.py index b5df61151..81421cd2d 100644 --- a/slither/detectors/shadowing/state.py +++ b/slither/detectors/shadowing/state.py @@ -80,9 +80,8 @@ contract DerivedContract is BaseContract{ for var in variables: info += ["\t- ", var, "\n"] - json = self.generate_json_result(info) - - results.append(json) + res = self.generate_result(info) + results.append(res) return results diff --git a/slither/detectors/source/rtlo.py b/slither/detectors/source/rtlo.py index 135b5aa6a..d69201334 100644 --- a/slither/detectors/source/rtlo.py +++ b/slither/detectors/source/rtlo.py @@ -73,12 +73,11 @@ contract Token # We have a patch, so pattern.find will return at least one result info += f"\t- {pattern.findall(source_encoded)[0]}\n" - json = self.generate_json_result(info) - self.add_other_to_json("rtlo-character", - (filename, idx, len(self.RTLO_CHARACTER_ENCODED)), - json, - self.slither) - results.append(json) + res = self.generate_result(info) + res.add_other("rtlo-character", + (filename, idx, len(self.RTLO_CHARACTER_ENCODED)), + self.slither) + results.append(res) # Advance the start index for the next iteration start_index = result_index + 1 diff --git a/slither/detectors/statements/assembly.py b/slither/detectors/statements/assembly.py index af65f2331..bf84dab7a 100644 --- a/slither/detectors/statements/assembly.py +++ b/slither/detectors/statements/assembly.py @@ -56,7 +56,7 @@ class Assembly(AbstractDetector): for node in nodes: info += ["\t- ", node, "\n"] - json = self.generate_json_result(info) - results.append(json) + res = self.generate_result(info) + results.append(res) return results diff --git a/slither/detectors/statements/calls_in_loop.py b/slither/detectors/statements/calls_in_loop.py index b2dfd5c11..cf115c858 100644 --- a/slither/detectors/statements/calls_in_loop.py +++ b/slither/detectors/statements/calls_in_loop.py @@ -88,7 +88,7 @@ If one of the destinations has a fallback function which reverts, `bad` will alw func = node.function info = [func, " has external calls inside a loop: ", node, "\n"] - json = self.generate_json_result(info) - results.append(json) + res = self.generate_result(info) + results.append(res) return results diff --git a/slither/detectors/statements/controlled_delegatecall.py b/slither/detectors/statements/controlled_delegatecall.py index 0dcff87bc..987757847 100644 --- a/slither/detectors/statements/controlled_delegatecall.py +++ b/slither/detectors/statements/controlled_delegatecall.py @@ -51,7 +51,7 @@ Bob calls `delegate` and delegates the execution to its malicious contract. As a for node in nodes: node_info = func_info + ['\t- ', node,'\n'] - json = self.generate_json_result(node_info) - results.append(json) + res = self.generate_result(node_info) + results.append(res) return results diff --git a/slither/detectors/statements/deprecated_calls.py b/slither/detectors/statements/deprecated_calls.py index de8b8e860..b56a807c5 100644 --- a/slither/detectors/statements/deprecated_calls.py +++ b/slither/detectors/statements/deprecated_calls.py @@ -157,7 +157,7 @@ contract ContractWithDeprecatedReferences { for (dep_id, original_desc, recommended_disc) in deprecated_entries: info += [f"\t- Usage of \"{original_desc}\" should be replaced with \"{recommended_disc}\"\n"] - json = self.generate_json_result(info) - results.append(json) + res = self.generate_result(info) + results.append(res) return results diff --git a/slither/detectors/statements/incorrect_strict_equality.py b/slither/detectors/statements/incorrect_strict_equality.py index 01faf4d62..b0b47d025 100644 --- a/slither/detectors/statements/incorrect_strict_equality.py +++ b/slither/detectors/statements/incorrect_strict_equality.py @@ -120,7 +120,7 @@ contract Crowdsale{ for node in nodes: node_info = func_info + [f"\t- ", node, "\n"] - json = self.generate_json_result(node_info) - results.append(json) + res = self.generate_result(node_info) + results.append(res) return results diff --git a/slither/detectors/statements/too_many_digits.py b/slither/detectors/statements/too_many_digits.py index 0e6591546..32d4ab93c 100644 --- a/slither/detectors/statements/too_many_digits.py +++ b/slither/detectors/statements/too_many_digits.py @@ -69,7 +69,7 @@ Use: node_info = func_info + ['\n\t- ', node,'\n'] # Add the result in result - json = self.generate_json_result(node_info) - results.append(json) + res = self.generate_result(node_info) + results.append(res) return results diff --git a/slither/detectors/statements/tx_origin.py b/slither/detectors/statements/tx_origin.py index 8f2b9968b..adc274b10 100644 --- a/slither/detectors/statements/tx_origin.py +++ b/slither/detectors/statements/tx_origin.py @@ -69,8 +69,7 @@ Bob is the owner of `TxOrigin`. Bob calls Eve's contract. Eve's contract calls ` for node in nodes: info = [func, " uses tx.origin for authorization: ", node, "\n"] - json = self.generate_json_result(info) - - results.append(json) + res = self.generate_result(info) + results.append(res) return results diff --git a/slither/detectors/variables/possible_const_state_variables.py b/slither/detectors/variables/possible_const_state_variables.py index eaed2dac8..2d6d40b06 100644 --- a/slither/detectors/variables/possible_const_state_variables.py +++ b/slither/detectors/variables/possible_const_state_variables.py @@ -89,7 +89,7 @@ class ConstCandidateStateVars(AbstractDetector): # Create a result for each finding for v in constable_variables: info = [v, " should be constant\n"] - json = self.generate_json_result(info) + json = self.generate_result(info) results.append(json) return results diff --git a/slither/detectors/variables/uninitialized_local_variables.py b/slither/detectors/variables/uninitialized_local_variables.py index cc0ff0968..09d185208 100644 --- a/slither/detectors/variables/uninitialized_local_variables.py +++ b/slither/detectors/variables/uninitialized_local_variables.py @@ -99,7 +99,7 @@ Bob calls `transfer`. As a result, the ethers are sent to the address 0x0 and ar for(function, uninitialized_local_variable) in all_results: info = [uninitialized_local_variable, " is a local variable never initialiazed\n"] - json = self.generate_json_result(info) + json = self.generate_result(info) results.append(json) return results diff --git a/slither/detectors/variables/uninitialized_state_variables.py b/slither/detectors/variables/uninitialized_state_variables.py index 8eaa784e6..795d74e39 100644 --- a/slither/detectors/variables/uninitialized_state_variables.py +++ b/slither/detectors/variables/uninitialized_state_variables.py @@ -93,7 +93,7 @@ Initialize all the variables. If a variable is meant to be initialized to zero, for f in functions: info += ["\t- ", f, "\n"] - json = self.generate_json_result(info) + json = self.generate_result(info) results.append(json) return results diff --git a/slither/detectors/variables/uninitialized_storage_variables.py b/slither/detectors/variables/uninitialized_storage_variables.py index f77f95d2a..7efa3391b 100644 --- a/slither/detectors/variables/uninitialized_storage_variables.py +++ b/slither/detectors/variables/uninitialized_storage_variables.py @@ -102,7 +102,7 @@ Bob calls `func`. As a result, `owner` is override to 0. for(function, uninitialized_storage_variable) in self.results: info = [uninitialized_storage_variable, " is a storage variable never initialiazed\n"] - json = self.generate_json_result(info) + json = self.generate_result(info) results.append(json) return results diff --git a/slither/detectors/variables/unused_state_variables.py b/slither/detectors/variables/unused_state_variables.py index def3d2804..d1b4f2179 100644 --- a/slither/detectors/variables/unused_state_variables.py +++ b/slither/detectors/variables/unused_state_variables.py @@ -61,7 +61,7 @@ class UnusedStateVars(AbstractDetector): if unusedVars: for var in unusedVars: info = [var, " is never used in ", c, "\n"] - json = self.generate_json_result(info) + json = self.generate_result(info) results.append(json) return results diff --git a/slither/printers/abstract_printer.py b/slither/printers/abstract_printer.py index 3c7331138..ceaa75d5d 100644 --- a/slither/printers/abstract_printer.py +++ b/slither/printers/abstract_printer.py @@ -1,6 +1,6 @@ import abc -from slither.utils import json_utils +from slither.utils import output class IncorrectPrinterInitialization(Exception): @@ -33,38 +33,14 @@ class AbstractPrinter(metaclass=abc.ABCMeta): self.logger.info(info) - def generate_json_result(self, info, additional_fields=None): + def generate_output(self, info, additional_fields=None): if additional_fields is None: additional_fields = {} - d = json_utils.generate_json_result(info, additional_fields) - d['printer'] = self.ARGUMENT + d = output.Output(info, additional_fields) + d.data['printer'] = self.ARGUMENT return d - @staticmethod - def add_contract_to_json(e, d, additional_fields=None): - json_utils.add_contract_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_function_to_json(e, d, additional_fields=None): - json_utils.add_function_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_functions_to_json(e, d, additional_fields=None): - json_utils.add_functions_to_json(e, d, additional_fields=additional_fields) - - @staticmethod - def add_file_to_json(e, content, d, additional_fields=None): - json_utils.add_file_to_json(e, content, d, additional_fields) - - @staticmethod - def add_pretty_table_to_json(e, content, d, additional_fields=None): - json_utils.add_pretty_table_to_json(e, content, d, additional_fields) - - @staticmethod - def add_other_to_json(name, source_mapping, d, slither, additional_fields=None): - json_utils.add_other_to_json(name, source_mapping, d, slither, additional_fields) - @abc.abstractmethod def output(self, filename): """TODO Documentation""" diff --git a/slither/printers/call/call_graph.py b/slither/printers/call/call_graph.py index 2f224ece0..8710e82ed 100644 --- a/slither/printers/call/call_graph.py +++ b/slither/printers/call/call_graph.py @@ -176,9 +176,9 @@ class PrinterCallGraph(AbstractPrinter): results.append((filename, content)) self.info(info) - json = self.generate_json_result(info) + res = self.generate_output(info) for filename, content in results: - self.add_file_to_json(filename, content, json) + res.add_file(filename, content) - return json + return res diff --git a/slither/printers/functions/authorization.py b/slither/printers/functions/authorization.py index 72fc532b3..24f606f1a 100644 --- a/slither/printers/functions/authorization.py +++ b/slither/printers/functions/authorization.py @@ -48,8 +48,8 @@ class PrinterWrittenVariablesAndAuthorization(AbstractPrinter): txt += str(table) + '\n' self.info(txt) - json = self.generate_json_result(txt) + res = self.generate_output(txt) for name, table in all_tables: - self.add_pretty_table_to_json(table, name, json) + res.add_pretty_table(table, name) - return json \ No newline at end of file + return res \ No newline at end of file diff --git a/slither/printers/functions/cfg.py b/slither/printers/functions/cfg.py index 191d63b5c..a8b53a3be 100644 --- a/slither/printers/functions/cfg.py +++ b/slither/printers/functions/cfg.py @@ -31,7 +31,7 @@ class CFG(AbstractPrinter): self.info(info) - json = self.generate_json_result(info) + res = self.generate_output(info) for filename, content in all_files: - self.add_file_to_json(filename, content, json) - return json \ No newline at end of file + res.add_file(filename, content) + return res \ No newline at end of file diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index f2034aa17..ab17cd15b 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -140,4 +140,6 @@ class Echidna(AbstractPrinter): self.info(json.dumps(d, indent=4)) - return d \ No newline at end of file + res = self.generate_output(json.dumps(d, indent=4)) + + return res \ No newline at end of file diff --git a/slither/printers/inheritance/inheritance.py b/slither/printers/inheritance/inheritance.py index f3b970dfc..e6b2972fb 100644 --- a/slither/printers/inheritance/inheritance.py +++ b/slither/printers/inheritance/inheritance.py @@ -75,6 +75,6 @@ class PrinterInheritance(AbstractPrinter): result['base_to_child'][base.name]['not_immediate'] = list(map(str, immediate)) self.info(info) - json = self.generate_json_result(info, additional_fields=result) + res = self.generate_output(info, additional_fields=result) - return json + return res diff --git a/slither/printers/inheritance/inheritance_graph.py b/slither/printers/inheritance/inheritance_graph.py index 52f4f32e2..de527809a 100644 --- a/slither/printers/inheritance/inheritance_graph.py +++ b/slither/printers/inheritance/inheritance_graph.py @@ -172,7 +172,7 @@ class PrinterInheritanceGraph(AbstractPrinter): with open(filename, 'w', encoding='utf8') as f: f.write(content) - json = self.generate_json_result(info) - self.add_file_to_json(filename, content, json) + res = self.generate_output(info) + res.add_file(filename, content) - return json \ No newline at end of file + return res \ No newline at end of file diff --git a/slither/printers/summary/constructor_calls.py b/slither/printers/summary/constructor_calls.py index d0edb93be..aae307827 100644 --- a/slither/printers/summary/constructor_calls.py +++ b/slither/printers/summary/constructor_calls.py @@ -2,46 +2,51 @@ Module printing summary of the contract """ from slither.printers.abstract_printer import AbstractPrinter - +from slither.utils import output class ConstructorPrinter(AbstractPrinter): - WIKI = 'https://github.com/crytic/slither/wiki/Printer-documentation#constructor-calls' - ARGUMENT = 'constructor-calls' - HELP = 'Print the constructors executed' - - def _get_soruce_code(self,cst): - src_mapping = cst.source_mapping - content= self.slither.source_code[src_mapping['filename_absolute']] - start = src_mapping['start'] - end = src_mapping['start'] + src_mapping['length'] - initial_space = src_mapping['starting_column'] - return ' ' * initial_space + content[start:end] + WIKI = 'https://github.com/crytic/slither/wiki/Printer-documentation#constructor-calls' + ARGUMENT = 'constructor-calls' + HELP = 'Print the constructors executed' + + def _get_soruce_code(self, cst): + src_mapping = cst.source_mapping + content = self.slither.source_code[src_mapping['filename_absolute']] + start = src_mapping['start'] + end = src_mapping['start'] + src_mapping['length'] + initial_space = src_mapping['starting_column'] + return ' ' * initial_space + content[start:end] + + def output(self, _filename): + info = '' + for contract in self.contracts: + stack_name = [] + stack_definition = [] + info += "\n\nContact Name: " + contract.name + info += " Constructor Call Sequence: " + cst = contract.constructors_declared + if cst: + stack_name.append(contract.name) + stack_definition.append(self._get_soruce_code(cst)) + for inherited_contract in contract.inheritance: + cst = inherited_contract.constructors_declared + if cst: + stack_name.append(inherited_contract.name) + stack_definition.append(self._get_soruce_code(cst)) + if len(stack_name) > 0: + info += " " + ' '.join(stack_name[len(stack_name) - 1]) + count = len(stack_name) - 2 + while count >= 0: + info += "-->" + ' '.join(stack_name[count]) + count = count - 1 + info += "\n Constructor Definitions:" + count = len(stack_definition) - 1 + while count >= 0: + info += "\n Contract name:" + str(stack_name[count]) + info += "\n" + str(stack_definition[count]) + count = count - 1 - def output(self,_filename): - for contract in self.contracts: - stack_name = [] - stack_definition = [] - print("\n\nContact Name:",contract.name) - print(" Constructor Call Sequence: ", sep=' ', end='', flush=True) - cst = contract.constructors_declared - if cst: - stack_name.append(contract.name) - stack_definition.append(self._get_soruce_code(cst)) - for inherited_contract in contract.inheritance: - cst = inherited_contract.constructors_declared - if cst: - stack_name.append(inherited_contract.name) - stack_definition.append(self._get_soruce_code(cst)) - if len(stack_name)>0: - print(" ",stack_name[len(stack_name)-1], sep=' ', end='', flush=True) - count = len(stack_name)-2 - while count>=0: - print("-->",stack_name[count], sep=' ', end='', flush=True) - count= count-1 - print("\n Constructor Definitions:") - count = len(stack_definition)-1 - while count>=0: - print("\n Contract name:", stack_name[count]) - print ("\n", stack_definition[count]) - count = count-1 + self.info(info) + res = output.Output(info) + return res diff --git a/slither/printers/summary/contract.py b/slither/printers/summary/contract.py index df7742281..e8f91d897 100644 --- a/slither/printers/summary/contract.py +++ b/slither/printers/summary/contract.py @@ -3,6 +3,7 @@ """ import collections from slither.printers.abstract_printer import AbstractPrinter +from slither.utils import output from slither.utils.colors import blue, green, magenta @@ -24,7 +25,7 @@ class ContractSummary(AbstractPrinter): all_contracts = [] for c in self.contracts: txt += blue("\n+ Contract %s\n" % c.name) - additional_fields = {"elements": []} + additional_fields = output.Output('') # Order the function with # contract_declarer -> list_functions @@ -47,15 +48,15 @@ class ContractSummary(AbstractPrinter): if function.visibility not in ['external', 'public', 'internal', 'private']: txt += " - {}  ({})\n".format(function, function.visibility) - self.add_function_to_json(function, additional_fields, additional_fields={"visibility": - function.visibility}) + additional_fields.add(function, additional_fields={"visibility": + function.visibility}) - all_contracts.append((c, additional_fields)) + all_contracts.append((c, additional_fields.data)) self.info(txt) - json = self.generate_json_result(txt) + res = self.generate_output(txt) for contract, additional_fields in all_contracts: - self.add_contract_to_json(contract, json, additional_fields=additional_fields) + res.add(contract, additional_fields=additional_fields) - return json + return res diff --git a/slither/printers/summary/data_depenency.py b/slither/printers/summary/data_depenency.py index cbd36fcdb..7e657ca0b 100644 --- a/slither/printers/summary/data_depenency.py +++ b/slither/printers/summary/data_depenency.py @@ -51,8 +51,8 @@ class DataDependency(AbstractPrinter): all_txt += txt all_tables.append((c.name, table)) - json = self.generate_json_result(all_txt) + res = self.generate_output(all_txt) for name, table in all_tables: - self.add_pretty_table_to_json(table, name, json) + res.add_pretty_table(table, name) - return json + return res diff --git a/slither/printers/summary/function.py b/slither/printers/summary/function.py index e9a71a965..f144c9736 100644 --- a/slither/printers/summary/function.py +++ b/slither/printers/summary/function.py @@ -70,8 +70,8 @@ class FunctionSummary(AbstractPrinter): all_tables.append((name, table)) all_txt += txt - json = self.generate_json_result(all_txt) + res = self.generate_output(all_txt) for name, table in all_tables: - self.add_pretty_table_to_json(table, name, json) + res.add_pretty_table(table, name) - return json + return res diff --git a/slither/printers/summary/function_ids.py b/slither/printers/summary/function_ids.py index 5aee6529c..dc1560e5d 100644 --- a/slither/printers/summary/function_ids.py +++ b/slither/printers/summary/function_ids.py @@ -37,8 +37,8 @@ class FunctionIds(AbstractPrinter): self.info(txt) - json = self.generate_json_result(txt) + res = self.generate_output(txt) for name, table in all_tables: - self.add_pretty_table_to_json(table, name, json) + res.add_pretty_table(table, name) - return json \ No newline at end of file + return res \ No newline at end of file diff --git a/slither/printers/summary/human_summary.py b/slither/printers/summary/human_summary.py index 156e353fa..9c986065d 100644 --- a/slither/printers/summary/human_summary.py +++ b/slither/printers/summary/human_summary.py @@ -4,6 +4,7 @@ Module printing summary of the contract import logging from slither.printers.abstract_printer import AbstractPrinter +from slither.utils import output from slither.utils.code_complexity import compute_cyclomatic_complexity from slither.utils.colors import green, red, yellow from slither.utils.standard_libraries import is_standard_library @@ -205,6 +206,7 @@ class PrinterHumanSummary(AbstractPrinter): 'ercs': [], } + lines_number = self._lines_number() if lines_number: total_lines, total_dep_lines = lines_number @@ -241,6 +243,7 @@ class PrinterHumanSummary(AbstractPrinter): self.info(txt) + results_contract = output.Output('') for contract in self.slither.contracts_derived: optimization, info, low, medium, high = self._get_detectors_result() contract_d = {'contract_name': contract.name, @@ -262,9 +265,11 @@ class PrinterHumanSummary(AbstractPrinter): contract_d['erc20_can_mint'] = False contract_d['erc20_race_condition_mitigated'] = race_condition_mitigated - self.add_contract_to_json(contract, results['contracts'], additional_fields=contract_d) + results_contract.add_contract(contract, additional_fields=contract_d) + + results['contracts']['elements'] = results_contract.elements - json = self.generate_json_result(txt, additional_fields=results) + json = self.generate_output(txt, additional_fields=results) return json diff --git a/slither/printers/summary/modifier_calls.py b/slither/printers/summary/modifier_calls.py index fbc62c90d..4d3cb7182 100644 --- a/slither/printers/summary/modifier_calls.py +++ b/slither/printers/summary/modifier_calls.py @@ -40,8 +40,8 @@ class Modifiers(AbstractPrinter): txt += "\n"+str(table) self.info(txt) - json = self.generate_json_result(all_txt) + res = self.generate_output(all_txt) for name, table in all_tables: - self.add_pretty_table_to_json(table, name, json) + res.add_pretty_table(table, name) - return json \ No newline at end of file + return res \ No newline at end of file diff --git a/slither/printers/summary/require_calls.py b/slither/printers/summary/require_calls.py index 51c67284d..25ae4af74 100644 --- a/slither/printers/summary/require_calls.py +++ b/slither/printers/summary/require_calls.py @@ -45,8 +45,8 @@ class RequireOrAssert(AbstractPrinter): all_tables.append((contract.name, table)) all_txt += txt - json = self.generate_json_result(all_txt) + res = self.generate_output(all_txt) for name, table in all_tables: - self.add_pretty_table_to_json(table, name, json) + res.add_pretty_table(table, name) - return json + return res diff --git a/slither/printers/summary/slithir.py b/slither/printers/summary/slithir.py index 3466d0212..f75c8b062 100644 --- a/slither/printers/summary/slithir.py +++ b/slither/printers/summary/slithir.py @@ -4,8 +4,8 @@ from slither.printers.abstract_printer import AbstractPrinter -class PrinterSlithIR(AbstractPrinter): +class PrinterSlithIR(AbstractPrinter): ARGUMENT = 'slithir' HELP = 'Print the slithIR representation of the functions' @@ -20,30 +20,32 @@ class PrinterSlithIR(AbstractPrinter): txt = "" for contract in self.contracts: - print('Contract {}'.format(contract.name)) + txt += 'Contract {}'.format(contract.name) for function in contract.functions: - print(f'\tFunction {function.canonical_name} {"" if function.is_shadowed else "(*)"}') + txt += f'\tFunction {function.canonical_name} {"" if function.is_shadowed else "(*)"}' for node in function.nodes: if node.expression: - print('\t\tExpression: {}'.format(node.expression)) - print('\t\tIRs:') + txt += '\t\tExpression: {}'.format(node.expression) + txt += '\t\tIRs:' for ir in node.irs: - print('\t\t\t{}'.format(ir)) + txt += '\t\t\t{}'.format(ir) elif node.irs: - print('\t\tIRs:') + txt += '\t\tIRs:' for ir in node.irs: - print('\t\t\t{}'.format(ir)) + txt += '\t\t\t{}'.format(ir) for modifier_statement in function.modifiers_statements: - print(f'\t\tModifier Call {modifier_statement.entry_point.expression}') + txt += f'\t\tModifier Call {modifier_statement.entry_point.expression}' for modifier_statement in function.explicit_base_constructor_calls_statements: - print(f'\t\tConstructor Call {modifier_statement.entry_point.expression}') + txt += f'\t\tConstructor Call {modifier_statement.entry_point.expression}' for modifier in contract.modifiers: - print('\tModifier {}'.format(modifier.canonical_name)) + txt += '\tModifier {}'.format(modifier.canonical_name) for node in modifier.nodes: - print(node) + txt += str(node) if node.expression: - print('\t\tExpression: {}'.format(node.expression)) - print('\t\tIRs:') + txt += '\t\tExpression: {}'.format(node.expression) + txt += '\t\tIRs:' for ir in node.irs: - print('\t\t\t{}'.format(ir)) + txt += '\t\t\t{}'.format(ir) self.info(txt) + res = self.generate_output(txt) + return res diff --git a/slither/printers/summary/slithir_ssa.py b/slither/printers/summary/slithir_ssa.py index 37acd457e..26d962401 100644 --- a/slither/printers/summary/slithir_ssa.py +++ b/slither/printers/summary/slithir_ssa.py @@ -21,24 +21,26 @@ class PrinterSlithIRSSA(AbstractPrinter): txt = "" for contract in self.contracts: - print('Contract {}'.format(contract.name)) + txt += 'Contract {}'.format(contract.name) for function in contract.functions: - print('\tFunction {}'.format(function.canonical_name)) + txt += '\tFunction {}'.format(function.canonical_name) for node in function.nodes: if node.expression: - print('\t\tExpression: {}'.format(node.expression)) + txt += '\t\tExpression: {}'.format(node.expression) if node.irs_ssa: - print('\t\tIRs:') + txt += '\t\tIRs:' for ir in node.irs_ssa: - print('\t\t\t{}'.format(ir)) + txt += '\t\t\t{}'.format(ir) for modifier in contract.modifiers: - print('\tModifier {}'.format(modifier.canonical_name)) + txt += '\tModifier {}'.format(modifier.canonical_name) for node in modifier.nodes: - print(node) + txt += str(node) if node.expression: - print('\t\tExpression: {}'.format(node.expression)) + txt += '\t\tExpression: {}'.format(node.expression) if node.irs_ssa: - print('\t\tIRs:') + txt += '\t\tIRs:' for ir in node.irs_ssa: - print('\t\t\t{}'.format(ir)) + txt += '\t\t\t{}'.format(ir) self.info(txt) + res = self.generate_output(txt) + return res diff --git a/slither/printers/summary/variable_order.py b/slither/printers/summary/variable_order.py index ffee1f940..1e78cf1df 100644 --- a/slither/printers/summary/variable_order.py +++ b/slither/printers/summary/variable_order.py @@ -36,8 +36,7 @@ class VariableOrder(AbstractPrinter): self.info(txt) - json = self.generate_json_result(txt) + res = self.generate_output(txt) for name, table in all_tables: - self.add_pretty_table_to_json(table, name, json) - - return json \ No newline at end of file + res.add_pretty_table(table, name) + return res \ No newline at end of file diff --git a/slither/slither.py b/slither/slither.py index 1dbf9e7ce..55698de74 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -165,7 +165,7 @@ class Slither(SlitherSolc): :return: List of registered printers outputs. """ - return [p.output(self.filename) for p in self._printers] + return [p.output(self.filename).data for p in self._printers] def _check_common_things(self, thing_name, cls, base_cls, instances_list): diff --git a/slither/tools/erc_conformance/__main__.py b/slither/tools/erc_conformance/__main__.py index f581db047..fe0fbb845 100644 --- a/slither/tools/erc_conformance/__main__.py +++ b/slither/tools/erc_conformance/__main__.py @@ -5,7 +5,7 @@ from collections import defaultdict from slither import Slither from crytic_compile import cryticparser from slither.utils.erc import ERCS -from slither.utils.json_utils import output_json +from slither.utils.output import output_to_json from .erc.ercs import generic_erc_checks from .erc.erc20 import check_erc20 @@ -59,7 +59,7 @@ def parse_args(): def _log_error(err, args): if args.json: - output_json(args.json, str(err), {"upgradeability-check": []}) + output_to_json(args.json, str(err), {"upgradeability-check": []}) logger.error(err) @@ -92,7 +92,7 @@ def main(): return if args.json: - output_json(args.json, None, {"upgradeability-check": ret}) + output_to_json(args.json, None, {"upgradeability-check": ret}) if __name__ == '__main__': diff --git a/slither/tools/erc_conformance/erc/erc20.py b/slither/tools/erc_conformance/erc/erc20.py index 3143ed34d..25473bc84 100644 --- a/slither/tools/erc_conformance/erc/erc20.py +++ b/slither/tools/erc_conformance/erc/erc20.py @@ -1,6 +1,6 @@ import logging -from slither.utils import json_utils +from slither.utils import output logger = logging.getLogger("Slither-conformance") @@ -18,9 +18,9 @@ def approval_race_condition(contract, ret): txt = f'\t[ ] {contract.name} is not protected for the ERC20 approval race condition' logger.info(txt) - lack_of_erc20_race_condition_protection = json_utils.generate_json_result(txt) - json_utils.add_contract_to_json(contract, lack_of_erc20_race_condition_protection) - ret["lack_of_erc20_race_condition_protection"].append(lack_of_erc20_race_condition_protection) + lack_of_erc20_race_condition_protection = output.Output(txt) + lack_of_erc20_race_condition_protection.add(contract) + ret["lack_of_erc20_race_condition_protection"].append(lack_of_erc20_race_condition_protection.data) def check_erc20(contract, ret, explored=None): diff --git a/slither/tools/erc_conformance/erc/ercs.py b/slither/tools/erc_conformance/erc/ercs.py index 523609263..5af000357 100644 --- a/slither/tools/erc_conformance/erc/ercs.py +++ b/slither/tools/erc_conformance/erc/ercs.py @@ -1,7 +1,7 @@ import logging from slither.slithir.operations import EventCall -from slither.utils import json_utils +from slither.utils import output from slither.utils.type import export_nested_types_from_variable, export_return_type_from_variable logger = logging.getLogger("Slither-conformance") @@ -25,12 +25,12 @@ def _check_signature(erc_function, contract, ret): if not state_variable_as_function or not state_variable_as_function.visibility in ['public', 'external']: txt = f'[ ] {sig} is missing {"" if required else "(optional)"}' logger.info(txt) - missing_func = json_utils.generate_json_result(txt, additional_fields={ + missing_func = output.Output(txt, additional_fields={ "function": sig, "required": required }) - json_utils.add_contract_to_json(contract, missing_func) - ret["missing_function"].append(missing_func) + missing_func.add(contract) + ret["missing_function"].append(missing_func.data) return types = [str(x) for x in export_nested_types_from_variable(state_variable_as_function)] @@ -38,12 +38,12 @@ def _check_signature(erc_function, contract, ret): if types != parameters: txt = f'[ ] {sig} is missing {"" if required else "(optional)"}' logger.info(txt) - missing_func = json_utils.generate_json_result(txt, additional_fields={ + missing_func = output.Output(txt, additional_fields={ "function": sig, "required": required }) - json_utils.add_contract_to_json(contract, missing_func) - ret["missing_function"].append(missing_func) + missing_func.add(contract) + ret["missing_function"].append(missing_func.data) return function_return_type = [export_return_type_from_variable(state_variable_as_function)] @@ -65,12 +65,12 @@ def _check_signature(erc_function, contract, ret): txt = f'\t[ ] {sig} -> () should return {return_type}' logger.info(txt) - incorrect_return = json_utils.generate_json_result(txt, additional_fields={ + incorrect_return = output.Output(txt, additional_fields={ "expected_return_type": return_type, "actual_return_type": function_return_type }) - json_utils.add_function_to_json(function, incorrect_return) - ret["incorrect_return_type"].append(incorrect_return) + incorrect_return.add(function) + ret["incorrect_return_type"].append(incorrect_return.data) elif not return_type: txt = f'\t[✓] {sig} -> () (correct return type)' @@ -79,12 +79,12 @@ def _check_signature(erc_function, contract, ret): txt = f'\t[ ] {sig} -> () should return {return_type}' logger.info(txt) - incorrect_return = json_utils.generate_json_result(txt, additional_fields={ + incorrect_return = output.Output(txt, additional_fields={ "expected_return_type": return_type, "actual_return_type": function_return_type }) - json_utils.add_function_to_json(function, incorrect_return) - ret["incorrect_return_type"].append(incorrect_return) + incorrect_return.add(function) + ret["incorrect_return_type"].append(incorrect_return.data) if view: if function_view: @@ -94,9 +94,9 @@ def _check_signature(erc_function, contract, ret): txt = f'\t[ ] {sig} should be view' logger.info(txt) - should_be_view = json_utils.generate_json_result(txt) - json_utils.add_function_to_json(function, should_be_view) - ret["should_be_view"].append(should_be_view) + should_be_view = output.Output(txt) + should_be_view.add(function) + ret["should_be_view"].append(should_be_view.data) if events: for event in events: @@ -106,11 +106,11 @@ def _check_signature(erc_function, contract, ret): txt = f'\t[ ] Must emit be view {event_sig}' logger.info(txt) - missing_event_emmited = json_utils.generate_json_result(txt, additional_fields={ + missing_event_emmited = output.Output(txt, additional_fields={ "missing_event": event_sig }) - json_utils.add_function_to_json(function, missing_event_emmited) - ret["missing_event_emmited"].append(missing_event_emmited) + missing_event_emmited.add(function) + ret["missing_event_emmited"].append(missing_event_emmited.data) else: event_found = False @@ -127,11 +127,11 @@ def _check_signature(erc_function, contract, ret): txt = f'\t[ ] Must emit be view {event_sig}' logger.info(txt) - missing_event_emmited = json_utils.generate_json_result(txt, additional_fields={ + missing_event_emmited = output.Output(txt, additional_fields={ "missing_event": event_sig }) - json_utils.add_function_to_json(function, missing_event_emmited) - ret["missing_event_emmited"].append(missing_event_emmited) + missing_event_emmited.add(function) + ret["missing_event_emmited"].append(missing_event_emmited.data) def _check_events(erc_event, contract, ret): @@ -146,12 +146,11 @@ def _check_events(erc_event, contract, ret): txt = f'[ ] {sig} is missing' logger.info(txt) - missing_event = json_utils.generate_json_result(txt, additional_fields={ + missing_event = output.Output(txt, additional_fields={ "event": sig }) - json_utils.add_contract_to_json(contract, missing_event) - ret["missing_event"].append(missing_event) - + missing_event.add(contract) + ret["missing_event"].append(missing_event.data) return txt = f'[✓] {sig} is present' @@ -166,11 +165,11 @@ def _check_events(erc_event, contract, ret): txt = f'\t[ ] parameter {i} should be indexed' logger.info(txt) - missing_event_index = json_utils.generate_json_result(txt, additional_fields={ + missing_event_index = output.Output(txt, additional_fields={ "missing_index": i }) - json_utils.add_event_to_json(event, missing_event_index) - ret["missing_event_index"].append(missing_event_index) + missing_event_index.add_event(event) + ret["missing_event_index"].append(missing_event_index.data) def generic_erc_checks(contract, erc_functions, erc_events, ret, explored=None): diff --git a/slither/tools/kspec_coverage/analysis.py b/slither/tools/kspec_coverage/analysis.py index 6ca9f9a83..d2daf03d0 100755 --- a/slither/tools/kspec_coverage/analysis.py +++ b/slither/tools/kspec_coverage/analysis.py @@ -4,17 +4,19 @@ import logging from slither.core.declarations import Function from slither.core.variables.variable import Variable from slither.utils.colors import yellow, green, red -from slither.utils import json_utils +from slither.utils import output logging.basicConfig(level=logging.WARNING) logger = logging.getLogger('Slither.kspec') + def _refactor_type(type): return { 'uint': 'uint256', 'int': 'int256' }.get(type, type) + def _get_all_covered_kspec_functions(target): # Create a set of our discovered functions which are covered covered_functions = set() @@ -56,9 +58,10 @@ def _get_slither_functions(slither): # TODO: integrate state variables all_functions_declared += list(set([s for s in slither.state_variables if s.visibility in ['public', 'external']])) slither_functions = {(function.contract.name, function.full_name): function for function in all_functions_declared} - + return slither_functions + def _generate_output(kspec, message, color, generate_json): info = "" for function in kspec: @@ -67,12 +70,13 @@ def _generate_output(kspec, message, color, generate_json): logger.info(color(info)) if generate_json: - json_kspec_present = json_utils.generate_json_result(info) + json_kspec_present = output.Output(info) for function in kspec: - json_utils.add_function_to_json(function, json_kspec_present) - return json_kspec_present + json_kspec_present.add(function) + return json_kspec_present.data return None + def _generate_output_unresolved(kspec, message, color, generate_json): info = "" for contract, function in kspec: @@ -81,8 +85,8 @@ def _generate_output_unresolved(kspec, message, color, generate_json): logger.info(color(info)) if generate_json: - json_kspec_present = json_utils.generate_json_result(info, additional_fields={"signatures": kspec}) - return json_kspec_present + json_kspec_present = output.Output(info, additional_fields={"signatures": kspec}) + return json_kspec_present.data return None @@ -95,7 +99,6 @@ def _run_coverage_analysis(args, slither, kspec_functions): kspec_functions_resolved = kspec_functions & slither_functions_set kspec_functions_unresolved = kspec_functions - kspec_functions_resolved - kspec_missing = [] kspec_present = [] @@ -114,23 +117,24 @@ def _run_coverage_analysis(args, slither, kspec_functions): red, args.json) json_kspec_missing_variables = _generate_output([f for f in kspec_missing if isinstance(f, Variable)], - "[ ] (Missing variable)", - yellow, - args.json) + "[ ] (Missing variable)", + yellow, + args.json) json_kspec_unresolved = _generate_output_unresolved(kspec_functions_unresolved, "[ ] (Unresolved)", yellow, args.json) - + # Handle unresolved kspecs if args.json: - json_utils.output_json(args.json, None, { - "functions_present": json_kspec_present, - "functions_missing": json_kspec_missing_functions, - "variables_missing": json_kspec_missing_variables, - "functions_unresolved": json_kspec_unresolved - }) - + output.output_to_json(args.json, None, { + "functions_present": json_kspec_present, + "functions_missing": json_kspec_missing_functions, + "variables_missing": json_kspec_missing_variables, + "functions_unresolved": json_kspec_unresolved + }) + + def run_analysis(args, slither, kspec): # Get all of our kspec'd functions (tuple(contract_name, function_name)). if ',' in kspec: @@ -143,4 +147,3 @@ def run_analysis(args, slither, kspec): # Run coverage analysis _run_coverage_analysis(args, slither, kspec_functions) - diff --git a/slither/tools/upgradeability/__main__.py b/slither/tools/upgradeability/__main__.py index 305a43dae..df43a7dfb 100644 --- a/slither/tools/upgradeability/__main__.py +++ b/slither/tools/upgradeability/__main__.py @@ -7,7 +7,7 @@ from slither import Slither from crytic_compile import cryticparser from slither.exceptions import SlitherException from slither.utils.colors import red -from slither.utils.json_utils import output_json +from slither.utils.output import output_to_json from .compare_variables_order import compare_variables_order from .compare_function_ids import compare_function_ids @@ -135,7 +135,7 @@ def main(): info = 'Contract {} not found in {}'.format(v1_name, v1.filename) logger.error(red(info)) if args.json: - output_json(args.json, str(info), {"upgradeability-check": json_results}) + output_to_json(args.json, str(info), {"upgradeability-check": json_results}) return _checks_on_contract(v1_contract, json_results) @@ -153,7 +153,7 @@ def main(): info = 'Proxy {} not found in {}'.format(args.proxy_name, proxy.filename) logger.error(red(info)) if args.json: - output_json(args.json, str(info), {"upgradeability-check": json_results}) + output_to_json(args.json, str(info), {"upgradeability-check": json_results}) return json_results['proxy-present'] = True _checks_on_contract_and_proxy(v1_contract, proxy_contract, json_results) @@ -170,7 +170,7 @@ def main(): info = 'New logic contract {} not found in {}'.format(args.new_contract_name, v2.filename) logger.error(red(info)) if args.json: - output_json(args.json, str(info), {"upgradeability-check": json_results}) + output_to_json(args.json, str(info), {"upgradeability-check": json_results}) return json_results['contract_v2-present'] = True @@ -183,12 +183,12 @@ def main(): _checks_on_contract_update(v1_contract, v2_contract, json_results) if args.json: - output_json(args.json, None, {"upgradeability-check": json_results}) + output_to_json(args.json, None, {"upgradeability-check": json_results}) except SlitherException as e: logger.error(str(e)) if args.json: - output_json(args.json, str(e), {"upgradeability-check": json_results}) + output_to_json(args.json, str(e), {"upgradeability-check": json_results}) return # endregion diff --git a/slither/tools/upgradeability/check_initialization.py b/slither/tools/upgradeability/check_initialization.py index 446468389..4fe07801a 100644 --- a/slither/tools/upgradeability/check_initialization.py +++ b/slither/tools/upgradeability/check_initialization.py @@ -1,7 +1,7 @@ import logging from slither.slithir.operations import InternalCall -from slither.utils import json_utils +from slither.utils.output import Output from slither.utils.colors import red, yellow, green logger = logging.getLogger("Slither-check-upgradeability") @@ -74,9 +74,9 @@ def check_initialization(contract): initializer_modifier_missing = True info = f'{f.canonical_name} does not call the initializer modifier' logger.info(red(info)) - json_elem = json_utils.generate_json_result(info) - json_utils.add_function_to_json(f, json_elem) - results['missing-initializer-modifier'].append(json_elem) + res = Output(info) + res.add(f) + results['missing-initializer-modifier'].append(res.data) if not initializer_modifier_missing: logger.info(green('All the init functions have the initializer modifier')) @@ -103,10 +103,10 @@ def check_initialization(contract): for f in missing_calls: info = f'Missing call to {f.canonical_name} in {most_derived_init.canonical_name}' logger.info(red(info)) - json_elem = json_utils.generate_json_result(info) - json_utils.add_function_to_json(f, json_elem, {"is_most_derived_init_function": False}) - json_utils.add_function_to_json(most_derived_init, json_elem, {"is_most_derived_init_function": True}) - results['missing-calls'].append(json_elem) + res = Output(info) + res.add(f, {"is_most_derived_init_function": False}) + res.add(most_derived_init, {"is_most_derived_init_function": True}) + results['missing-calls'].append(res.data) missing_call = True if not missing_call: logger.info(green('No missing call to an init function found')) @@ -117,9 +117,9 @@ def check_initialization(contract): for f in double_calls: info = f'{f.canonical_name} is called multiple times in {most_derived_init.full_name}' logger.info(red(info)) - json_elem = json_utils.generate_json_result(info) - json_utils.add_function_to_json(f, json_elem) - results['multiple-calls'].append(json_elem) + res = Output(info) + res.add(f) + results['multiple-calls'].append(res.data) double_calls_found = True if not double_calls_found: logger.info(green('No double call to init functions found')) @@ -128,9 +128,9 @@ def check_initialization(contract): init_info = f'{contract.name} needs to be initialized by {most_derived_init.full_name}\n' logger.info(green('Check the deployement script to ensure that these functions are called:\n' + init_info)) - json_elem = json_utils.generate_json_result(init_info) - json_utils.add_function_to_json(most_derived_init, json_elem) - results['initialize_target'] = json_elem + res = Output(init_info) + res.add(most_derived_init) + results['initialize_target'] = res.data if not error_found: logger.info(green('No error found')) diff --git a/slither/tools/upgradeability/check_variable_initialization.py b/slither/tools/upgradeability/check_variable_initialization.py index cedfbc314..cb2473f67 100644 --- a/slither/tools/upgradeability/check_variable_initialization.py +++ b/slither/tools/upgradeability/check_variable_initialization.py @@ -1,6 +1,6 @@ import logging -from slither.utils import json_utils +from slither.utils import output from slither.utils.colors import red, green logger = logging.getLogger("Slither-check-upgradeability") @@ -20,9 +20,9 @@ def check_variable_initialization(contract): if s.initialized and not s.is_constant: info = f'{s.canonical_name} has an initial value ({s.source_mapping_str})' logger.info(red(info)) - json_elem = json_utils.generate_json_result(info) - json_utils.add_variable_to_json(s, json_elem) - results['variables-initialized'].append(json_elem) + res = output.Output(info) + res.add(s) + results['variables-initialized'].append(res.data) error_found = True if not error_found: diff --git a/slither/tools/upgradeability/compare_function_ids.py b/slither/tools/upgradeability/compare_function_ids.py index da7eda61e..34b63d8bf 100644 --- a/slither/tools/upgradeability/compare_function_ids.py +++ b/slither/tools/upgradeability/compare_function_ids.py @@ -4,10 +4,9 @@ ''' import logging -from slither import Slither from slither.core.declarations import Function from slither.exceptions import SlitherError -from slither.utils import json_utils +from slither.utils.output import Output from slither.utils.function import get_function_id from slither.utils.colors import red, green @@ -63,16 +62,10 @@ def compare_function_ids(implem, proxy): info = f'Function id collision found: {implem_function.canonical_name} ({implem_function.source_mapping_str}) {proxy_function.canonical_name} ({proxy_function.source_mapping_str})' logger.info(red(info)) - json_elem = json_utils.generate_json_result(info) - if isinstance(implem_function, Function): - json_utils.add_function_to_json(implem_function, json_elem) - else: - json_utils.add_variable_to_json(implem_function, json_elem) - if isinstance(proxy_function, Function): - json_utils.add_function_to_json(proxy_function, json_elem) - else: - json_utils.add_variable_to_json(proxy_function, json_elem) - results['function-id-collision'].append(json_elem) + res = Output(info) + res.add(implem_function) + res.add(proxy_function) + results['function-id-collision'].append(res.data) else: @@ -82,17 +75,10 @@ def compare_function_ids(implem, proxy): info = f'Shadowing between {implem_function.canonical_name} ({implem_function.source_mapping_str}) and {proxy_function.canonical_name} ({proxy_function.source_mapping_str})' logger.info(red(info)) - json_elem = json_utils.generate_json_result(info) - json_elem = json_utils.generate_json_result(info) - if isinstance(implem_function, Function): - json_utils.add_function_to_json(implem_function, json_elem) - else: - json_utils.add_variable_to_json(implem_function, json_elem) - if isinstance(proxy_function, Function): - json_utils.add_function_to_json(proxy_function, json_elem) - else: - json_utils.add_variable_to_json(proxy_function, json_elem) - results['shadowing'].append(json_elem) + res = Output(info) + res.add(implem_function) + res.add(proxy_function) + results['shadowing'].append(res.data) if not error_found: logger.info(green('No error found')) diff --git a/slither/tools/upgradeability/compare_variables_order.py b/slither/tools/upgradeability/compare_variables_order.py index 3b8fd9c30..ea5852d3f 100644 --- a/slither/tools/upgradeability/compare_variables_order.py +++ b/slither/tools/upgradeability/compare_variables_order.py @@ -3,7 +3,7 @@ ''' import logging -from slither.utils import json_utils +from slither.utils.output import Output from slither.utils.colors import red, green, yellow logger = logging.getLogger("Slither-check-upgradeability") @@ -32,9 +32,9 @@ def compare_variables_order(contract1, contract2, missing_variable_check=True): info = f'Variable only in {contract1.name}: {variable1.name} ({variable1.source_mapping_str})' logger.info(yellow(info)) - json_elem = json_utils.generate_json_result(info) - json_utils.add_variable_to_json(variable1, json_elem) - results['missing_variables'].append(json_elem) + res = Output(info) + res.add(variable1) + results['missing_variables'].append(res.data) error_found = True continue @@ -47,10 +47,10 @@ def compare_variables_order(contract1, contract2, missing_variable_check=True): info += f'\t Variable {idx} in {contract2.name}: {variable2.name} {variable2.type} ({variable2.source_mapping_str})\n' logger.info(red(info)) - json_elem = json_utils.generate_json_result(info, additional_fields={'index': idx}) - json_utils.add_variable_to_json(variable1, json_elem) - json_utils.add_variable_to_json(variable2, json_elem) - results['different-variables'].append(json_elem) + res = Output(info, additional_fields={'index': idx}) + res.add(variable1) + res.add(variable2) + results['different-variables'].append(res.data) error_found = True @@ -61,9 +61,9 @@ def compare_variables_order(contract1, contract2, missing_variable_check=True): info = f'Extra variables in {contract2.name}: {variable2.name} ({variable2.source_mapping_str})\n' logger.info(yellow(info)) - json_elem = json_utils.generate_json_result(info, additional_fields={'index': idx}) - json_utils.add_variable_to_json(variable2, json_elem) - results['extra-variables'].append(json_elem) + res = Output(info, additional_fields={'index': idx}) + res.add(variable2) + results['extra-variables'].append(res.data) idx = idx + 1 if not error_found: diff --git a/slither/tools/upgradeability/constant_checks.py b/slither/tools/upgradeability/constant_checks.py index d66b41fc2..e25924350 100644 --- a/slither/tools/upgradeability/constant_checks.py +++ b/slither/tools/upgradeability/constant_checks.py @@ -1,6 +1,6 @@ import logging -from slither.utils import json_utils +from slither.utils.output import Output from slither.utils.colors import red, yellow, green logger = logging.getLogger("Slither-check-upgradeability") @@ -49,30 +49,30 @@ def constant_conformance_check(contract_v1, contract_v2): info = f'{state_v1.canonical_name} ({state_v1.source_mapping_str}) was constant and {state_v2.canonical_name} is not ({state_v2.source_mapping_str})' logger.info(red(info)) - json_elem = json_utils.generate_json_result(info) - json_utils.add_variable_to_json(state_v1, json_elem) - json_utils.add_variable_to_json(state_v2, json_elem) - results['were_constants'].append(json_elem) + res = Output(info) + res.add(state_v1) + res.add(state_v2) + results['were_constants'].append(res.data) error_found = True elif state_v2.is_constant: info = f'{state_v1.canonical_name} ({state_v1.source_mapping_str}) was not constant but {state_v2.canonical_name} is ({state_v2.source_mapping_str})' logger.info(red(info)) - json_elem = json_utils.generate_json_result(info) - json_utils.add_variable_to_json(state_v1, json_elem) - json_utils.add_variable_to_json(state_v2, json_elem) - results['became_constants'].append(json_elem) + res = Output(info) + res.add(state_v1) + res.add(state_v2) + results['became_constants'].append(res.data) error_found = True else: info = f'{state_v1.canonical_name} not found in {contract_v2.name}, not check was done' logger.info(yellow(info)) - json_elem = json_utils.generate_json_result(info) - json_utils.add_variable_to_json(state_v1, json_elem) - json_utils.add_contract_to_json(contract_v2, json_elem) - results['not_found_in_v2'].append(json_elem) + res = Output(info) + res.add(state_v1) + res.add(contract_v2) + results['not_found_in_v2'].append(res.data) error_found = True diff --git a/slither/utils/json_utils.py b/slither/utils/json_utils.py deleted file mode 100644 index 3ae2b8862..000000000 --- a/slither/utils/json_utils.py +++ /dev/null @@ -1,452 +0,0 @@ -import os -import json -import logging -from collections import OrderedDict - -from slither.core.cfg.node import Node -from slither.core.declarations import Contract, Function, Enum, Event, Structure, Pragma -from slither.core.source_mapping.source_mapping import SourceMapping -from slither.core.variables.variable import Variable -from slither.exceptions import SlitherError -from slither.utils.colors import yellow - -logger = logging.getLogger("Slither") - - -################################################################################### -################################################################################### -# region Output -################################################################################### -################################################################################### - -def output_json(filename, error, results): - """ - - :param filename: Filename where the json will be written. If None or "-", write to stdout - :param error: Error to report - :param results: Results to report - :param logger: Logger where to log potential info - :return: - """ - # Create our encapsulated JSON result. - json_result = { - "success": error is None, - "error": error, - "results": results - } - - if filename == "-": - filename = None - - # Determine if we should output to stdout - if filename is None: - # Write json to console - print(json.dumps(json_result)) - else: - # Write json to file - if os.path.isfile(filename): - logger.info(yellow(f'{filename} exists already, the overwrite is prevented')) - else: - with open(filename, 'w', encoding='utf8') as f: - json.dump(json_result, f, indent=2) - - -# endregion -################################################################################### -################################################################################### -# region Json generation -################################################################################### -################################################################################### - -def _convert_to_description(d): - if isinstance(d, str): - return d - - if not isinstance(d, SourceMapping): - raise SlitherError(f'{d} does not inherit from SourceMapping, conversion impossible') - - if isinstance(d, Node): - if d.expression: - return f'{d.expression} ({d.source_mapping_str})' - else: - return f'{str(d)} ({d.source_mapping_str})' - - if hasattr(d, 'canonical_name'): - return f'{d.canonical_name} ({d.source_mapping_str})' - - if hasattr(d, 'name'): - return f'{d.name} ({d.source_mapping_str})' - - raise SlitherError(f'{type(d)} cannot be converted (no name, or canonical_name') - -def _convert_to_markdown(d, markdown_root): - if isinstance(d, str): - return d - - if not isinstance(d, SourceMapping): - raise SlitherError(f'{d} does not inherit from SourceMapping, conversion impossible') - - if isinstance(d, Node): - if d.expression: - return f'[{d.expression}]({d.source_mapping_to_markdown(markdown_root)})' - else: - return f'[{str(d)}]({d.source_mapping_to_markdown(markdown_root)})' - - if hasattr(d, 'canonical_name'): - return f'[{d.canonical_name}]({d.source_mapping_to_markdown(markdown_root)})' - - if hasattr(d, 'name'): - return f'[{d.name}]({d.source_mapping_to_markdown(markdown_root)})' - - raise SlitherError(f'{type(d)} cannot be converted (no name, or canonical_name') - -def generate_json_result(info, additional_fields=None, markdown_root='', standard_format=False): - if additional_fields is None: - additional_fields = {} - d = OrderedDict() - d['elements'] = [] - d['description'] = ''.join(_convert_to_description(d) for d in info) - d['markdown'] = ''.join(_convert_to_markdown(d, markdown_root) for d in info) - - if standard_format: - to_add = [i for i in info if not isinstance(i, str)] - - for add in to_add: - if isinstance(add, Variable): - add_variable_to_json(add, d) - elif isinstance(add, Contract): - add_contract_to_json(add, d) - elif isinstance(add, Function): - add_function_to_json(add, d) - elif isinstance(add, Enum): - add_enum_to_json(add, d) - elif isinstance(add, Event): - add_event_to_json(add, d) - elif isinstance(add, Structure): - add_struct_to_json(add, d) - elif isinstance(add, Pragma): - add_pragma_to_json(add, d) - elif isinstance(add, Node): - add_node_to_json(add, d) - else: - raise SlitherError(f'Impossible to add {type(add)} to the json') - - if additional_fields: - d['additional_fields'] = additional_fields - - return d - - -# endregion -################################################################################### -################################################################################### -# region Internal functions -################################################################################### -################################################################################### - -def _create_base_element(type, name, source_mapping, type_specific_fields=None, additional_fields=None): - if additional_fields is None: - additional_fields = {} - if type_specific_fields is None: - type_specific_fields = {} - element = {'type': type, - 'name': name, - 'source_mapping': source_mapping} - if type_specific_fields: - element['type_specific_fields'] = type_specific_fields - if additional_fields: - element['additional_fields'] = additional_fields - return element - - -def _create_parent_element(element): - from slither.core.children.child_contract import ChildContract - from slither.core.children.child_function import ChildFunction - from slither.core.children.child_inheritance import ChildInheritance - if isinstance(element, ChildInheritance): - if element.contract_declarer: - contract = {'elements': []} - add_contract_to_json(element.contract_declarer, contract) - return contract['elements'][0] - elif isinstance(element, ChildContract): - if element.contract: - contract = {'elements': []} - add_contract_to_json(element.contract, contract) - return contract['elements'][0] - elif isinstance(element, ChildFunction): - if element.function: - function = {'elements': []} - add_function_to_json(element.function, function) - return function['elements'][0] - return None - - -# endregion -################################################################################### -################################################################################### -# region Variables -################################################################################### -################################################################################### - -def add_variable_to_json(variable, d, additional_fields=None): - if additional_fields is None: - additional_fields = {} - type_specific_fields = { - 'parent': _create_parent_element(variable) - } - element = _create_base_element('variable', - variable.name, - variable.source_mapping, - type_specific_fields, - additional_fields) - d['elements'].append(element) - - -def add_variables_to_json(variables, d): - for variable in sorted(variables, key=lambda x: x.name): - add_variable_to_json(variable, d) - - -# endregion -################################################################################### -################################################################################### -# region Contract -################################################################################### -################################################################################### - -def add_contract_to_json(contract, d, additional_fields=None): - if additional_fields is None: - additional_fields = {} - element = _create_base_element('contract', - contract.name, - contract.source_mapping, - {}, - additional_fields) - d['elements'].append(element) - - -# endregion -################################################################################### -################################################################################### -# region Functions -################################################################################### -################################################################################### - -def add_function_to_json(function, d, additional_fields=None): - if additional_fields is None: - additional_fields = {} - type_specific_fields = { - 'parent': _create_parent_element(function), - 'signature': function.full_name - } - element = _create_base_element('function', - function.name, - function.source_mapping, - type_specific_fields, - additional_fields) - d['elements'].append(element) - - -def add_functions_to_json(functions, d, additional_fields=None): - if additional_fields is None: - additional_fields = {} - for function in sorted(functions, key=lambda x: x.name): - add_function_to_json(function, d, additional_fields) - - -# endregion -################################################################################### -################################################################################### -# region Enum -################################################################################### -################################################################################### - - -def add_enum_to_json(enum, d, additional_fields=None): - if additional_fields is None: - additional_fields = {} - type_specific_fields = { - 'parent': _create_parent_element(enum) - } - element = _create_base_element('enum', - enum.name, - enum.source_mapping, - type_specific_fields, - additional_fields) - d['elements'].append(element) - - -# endregion -################################################################################### -################################################################################### -# region Structures -################################################################################### -################################################################################### - -def add_struct_to_json(struct, d, additional_fields=None): - if additional_fields is None: - additional_fields = {} - type_specific_fields = { - 'parent': _create_parent_element(struct) - } - element = _create_base_element('struct', - struct.name, - struct.source_mapping, - type_specific_fields, - additional_fields) - d['elements'].append(element) - - -# endregion -################################################################################### -################################################################################### -# region Events -################################################################################### -################################################################################### - -def add_event_to_json(event, d, additional_fields=None): - if additional_fields is None: - additional_fields = {} - type_specific_fields = { - 'parent': _create_parent_element(event), - 'signature': event.full_name - } - element = _create_base_element('event', - event.name, - event.source_mapping, - type_specific_fields, - additional_fields) - - d['elements'].append(element) - - -# endregion -################################################################################### -################################################################################### -# region Nodes -################################################################################### -################################################################################### - -def add_node_to_json(node, d, additional_fields=None): - if additional_fields is None: - additional_fields = {} - type_specific_fields = { - 'parent': _create_parent_element(node), - } - node_name = str(node.expression) if node.expression else "" - element = _create_base_element('node', - node_name, - node.source_mapping, - type_specific_fields, - additional_fields) - d['elements'].append(element) - - -def add_nodes_to_json(nodes, d): - for node in sorted(nodes, key=lambda x: x.node_id): - add_node_to_json(node, d) - - -# endregion -################################################################################### -################################################################################### -# region Pragma -################################################################################### -################################################################################### - -def add_pragma_to_json(pragma, d, additional_fields=None): - if additional_fields is None: - additional_fields = {} - type_specific_fields = { - 'directive': pragma.directive - } - element = _create_base_element('pragma', - pragma.version, - pragma.source_mapping, - type_specific_fields, - additional_fields) - d['elements'].append(element) - - -# endregion -################################################################################### -################################################################################### -# region File -################################################################################### -################################################################################### - - -def add_file_to_json(filename, content, d, additional_fields=None): - if additional_fields is None: - additional_fields = {} - type_specific_fields = { - 'filename': filename, - 'content': content - } - element = _create_base_element('file', - type_specific_fields, - additional_fields) - - d['elements'].append(element) - - -# endregion -################################################################################### -################################################################################### -# region Pretty Table -################################################################################### -################################################################################### - - -def add_pretty_table_to_json(content, name, d, additional_fields=None): - if additional_fields is None: - additional_fields = {} - type_specific_fields = { - 'content': content, - 'name': name - } - element = _create_base_element('pretty_table', - type_specific_fields, - additional_fields) - - d['elements'].append(element) - - -# endregion -################################################################################### -################################################################################### -# region Others -################################################################################### -################################################################################### - -def add_other_to_json(name, source_mapping, d, slither, additional_fields=None): - # If this a tuple with (filename, start, end), convert it to a source mapping. - if additional_fields is None: - additional_fields = {} - if isinstance(source_mapping, tuple): - # Parse the source id - (filename, start, end) = source_mapping - source_id = next( - (source_unit_id for (source_unit_id, source_unit_filename) in slither.source_units.items() if - source_unit_filename == filename), -1) - - # Convert to a source mapping string - source_mapping = f"{start}:{end}:{source_id}" - - # If this is a source mapping string, parse it. - if isinstance(source_mapping, str): - source_mapping_str = source_mapping - source_mapping = SourceMapping() - source_mapping.set_offset(source_mapping_str, slither) - - # If this is a source mapping object, get the underlying source mapping dictionary - if isinstance(source_mapping, SourceMapping): - source_mapping = source_mapping.source_mapping - - # Create the underlying element and add it to our resulting json - element = _create_base_element('other', - name, - source_mapping, - {}, - additional_fields) - d['elements'].append(element) diff --git a/slither/utils/output.py b/slither/utils/output.py new file mode 100644 index 000000000..cbceef467 --- /dev/null +++ b/slither/utils/output.py @@ -0,0 +1,454 @@ +import os +import json +import logging +from collections import OrderedDict + +from slither.core.cfg.node import Node +from slither.core.declarations import Contract, Function, Enum, Event, Structure, Pragma +from slither.core.source_mapping.source_mapping import SourceMapping +from slither.core.variables.variable import Variable +from slither.exceptions import SlitherError +from slither.utils.colors import yellow + +logger = logging.getLogger("Slither") + + +################################################################################### +################################################################################### +# region Output +################################################################################### +################################################################################### + +def output_to_json(filename, error, results): + """ + + :param filename: Filename where the json will be written. If None or "-", write to stdout + :param error: Error to report + :param results: Results to report + :param logger: Logger where to log potential info + :return: + """ + # Create our encapsulated JSON result. + json_result = { + "success": error is None, + "error": error, + "results": results + } + + if filename == "-": + filename = None + + # Determine if we should output to stdout + if filename is None: + # Write json to console + print(json.dumps(json_result)) + else: + # Write json to file + if os.path.isfile(filename): + logger.info(yellow(f'{filename} exists already, the overwrite is prevented')) + else: + with open(filename, 'w', encoding='utf8') as f: + json.dump(json_result, f, indent=2) + + +# endregion +################################################################################### +################################################################################### +# region Json generation +################################################################################### +################################################################################### + +def _convert_to_description(d): + if isinstance(d, str): + return d + + if not isinstance(d, SourceMapping): + raise SlitherError(f'{d} does not inherit from SourceMapping, conversion impossible') + + if isinstance(d, Node): + if d.expression: + return f'{d.expression} ({d.source_mapping_str})' + else: + return f'{str(d)} ({d.source_mapping_str})' + + if hasattr(d, 'canonical_name'): + return f'{d.canonical_name} ({d.source_mapping_str})' + + if hasattr(d, 'name'): + return f'{d.name} ({d.source_mapping_str})' + + raise SlitherError(f'{type(d)} cannot be converted (no name, or canonical_name') + + +def _convert_to_markdown(d, markdown_root): + if isinstance(d, str): + return d + + if not isinstance(d, SourceMapping): + raise SlitherError(f'{d} does not inherit from SourceMapping, conversion impossible') + + if isinstance(d, Node): + if d.expression: + return f'[{d.expression}]({d.source_mapping_to_markdown(markdown_root)})' + else: + return f'[{str(d)}]({d.source_mapping_to_markdown(markdown_root)})' + + if hasattr(d, 'canonical_name'): + return f'[{d.canonical_name}]({d.source_mapping_to_markdown(markdown_root)})' + + if hasattr(d, 'name'): + return f'[{d.name}]({d.source_mapping_to_markdown(markdown_root)})' + + raise SlitherError(f'{type(d)} cannot be converted (no name, or canonical_name') + + +# endregion +################################################################################### +################################################################################### +# region Internal functions +################################################################################### +################################################################################### + +def _create_base_element(type, name, source_mapping, type_specific_fields=None, additional_fields=None): + if additional_fields is None: + additional_fields = {} + if type_specific_fields is None: + type_specific_fields = {} + element = {'type': type, + 'name': name, + 'source_mapping': source_mapping} + if type_specific_fields: + element['type_specific_fields'] = type_specific_fields + if additional_fields: + element['additional_fields'] = additional_fields + return element + + +def _create_parent_element(element): + from slither.core.children.child_contract import ChildContract + from slither.core.children.child_function import ChildFunction + from slither.core.children.child_inheritance import ChildInheritance + if isinstance(element, ChildInheritance): + if element.contract_declarer: + contract = Output('') + contract.add_contract(element.contract_declarer) + return contract.data['elements'][0] + elif isinstance(element, ChildContract): + if element.contract: + contract = Output('') + contract.add_contract(element.contract) + return contract.data['elements'][0] + elif isinstance(element, ChildFunction): + if element.function: + function = Output('') + function.add_function(element.function) + return function.data['elements'][0] + return None + + +class Output: + + def __init__(self, info, additional_fields=None, markdown_root='', standard_format=True): + if additional_fields is None: + additional_fields = {} + + # Allow info to be a string to simplify the API + if isinstance(info, str): + info = [info] + + self._data = OrderedDict() + self._data['elements'] = [] + self._data['description'] = ''.join(_convert_to_description(d) for d in info) + self._data['markdown'] = ''.join(_convert_to_markdown(d, markdown_root) for d in info) + + if standard_format: + to_add = [i for i in info if not isinstance(i, str)] + + for add in to_add: + self.add(add) + + if additional_fields: + self._data['additional_fields'] = additional_fields + + + def add(self, add, additional_fields=None): + if isinstance(add, Variable): + self.add_variable(add, additional_fields=additional_fields) + elif isinstance(add, Contract): + self.add_contract(add, additional_fields=additional_fields) + elif isinstance(add, Function): + self.add_function(add, additional_fields=additional_fields) + elif isinstance(add, Enum): + self.add_enum(add, additional_fields=additional_fields) + elif isinstance(add, Event): + self.add_event(add, additional_fields=additional_fields) + elif isinstance(add, Structure): + self.add_struct(add, additional_fields=additional_fields) + elif isinstance(add, Pragma): + self.add_pragma(add, additional_fields=additional_fields) + elif isinstance(add, Node): + self.add_node(add, additional_fields=additional_fields) + else: + raise SlitherError(f'Impossible to add {type(add)} to the json') + + @property + def data(self): + return self._data + + @property + def elements(self): + return self._data['elements'] + + # endregion + ################################################################################### + ################################################################################### + # region Variables + ################################################################################### + ################################################################################### + + def add_variable(self, variable, additional_fields=None): + if additional_fields is None: + additional_fields = {} + type_specific_fields = { + 'parent': _create_parent_element(variable) + } + element = _create_base_element('variable', + variable.name, + variable.source_mapping, + type_specific_fields, + additional_fields) + self._data['elements'].append(element) + + def add_variables_to_output(self, variables): + for variable in sorted(variables, key=lambda x: x.name): + self.add_variable(variable) + + # endregion + ################################################################################### + ################################################################################### + # region Contract + ################################################################################### + ################################################################################### + + def add_contract(self, contract, additional_fields=None): + if additional_fields is None: + additional_fields = {} + element = _create_base_element('contract', + contract.name, + contract.source_mapping, + {}, + additional_fields) + self._data['elements'].append(element) + + # endregion + ################################################################################### + ################################################################################### + # region Functions + ################################################################################### + ################################################################################### + + def add_function(self, function, additional_fields=None): + if additional_fields is None: + additional_fields = {} + type_specific_fields = { + 'parent': _create_parent_element(function), + 'signature': function.full_name + } + element = _create_base_element('function', + function.name, + function.source_mapping, + type_specific_fields, + additional_fields) + self._data['elements'].append(element) + + def add_functions(self, functions, additional_fields=None): + if additional_fields is None: + additional_fields = {} + for function in sorted(functions, key=lambda x: x.name): + self.add_function(function, additional_fields) + + # endregion + ################################################################################### + ################################################################################### + # region Enum + ################################################################################### + ################################################################################### + + def add_enum(self, enum, additional_fields=None): + if additional_fields is None: + additional_fields = {} + type_specific_fields = { + 'parent': _create_parent_element(enum) + } + element = _create_base_element('enum', + enum.name, + enum.source_mapping, + type_specific_fields, + additional_fields) + self._data['elements'].append(element) + + # endregion + ################################################################################### + ################################################################################### + # region Structures + ################################################################################### + ################################################################################### + + def add_struct(self, struct, additional_fields=None): + if additional_fields is None: + additional_fields = {} + type_specific_fields = { + 'parent': _create_parent_element(struct) + } + element = _create_base_element('struct', + struct.name, + struct.source_mapping, + type_specific_fields, + additional_fields) + self._data['elements'].append(element) + + # endregion + ################################################################################### + ################################################################################### + # region Events + ################################################################################### + ################################################################################### + + def add_event(self, event, additional_fields=None): + if additional_fields is None: + additional_fields = {} + type_specific_fields = { + 'parent': _create_parent_element(event), + 'signature': event.full_name + } + element = _create_base_element('event', + event.name, + event.source_mapping, + type_specific_fields, + additional_fields) + + self._data['elements'].append(element) + + # endregion + ################################################################################### + ################################################################################### + # region Nodes + ################################################################################### + ################################################################################### + + def add_node(self, node, additional_fields=None): + if additional_fields is None: + additional_fields = {} + type_specific_fields = { + 'parent': _create_parent_element(node), + } + node_name = str(node.expression) if node.expression else "" + element = _create_base_element('node', + node_name, + node.source_mapping, + type_specific_fields, + additional_fields) + self._data['elements'].append(element) + + def add_nodes(self, nodes): + for node in sorted(nodes, key=lambda x: x.node_id): + self.add_node(node) + + # endregion + ################################################################################### + ################################################################################### + # region Pragma + ################################################################################### + ################################################################################### + + def add_pragma(self, pragma, additional_fields=None): + if additional_fields is None: + additional_fields = {} + type_specific_fields = { + 'directive': pragma.directive + } + element = _create_base_element('pragma', + pragma.version, + pragma.source_mapping, + type_specific_fields, + additional_fields) + self._data['elements'].append(element) + + # endregion + ################################################################################### + ################################################################################### + # region File + ################################################################################### + ################################################################################### + + def add_file(self, filename, content, additional_fields=None): + if additional_fields is None: + additional_fields = {} + type_specific_fields = { + 'filename': filename, + 'content': content + } + element = _create_base_element('file', + type_specific_fields, + additional_fields) + + self._data['elements'].append(element) + + # endregion + ################################################################################### + ################################################################################### + # region Pretty Table + ################################################################################### + ################################################################################### + + def add_pretty_table(self, content, name, additional_fields=None): + if additional_fields is None: + additional_fields = {} + type_specific_fields = { + 'content': content, + 'name': name + } + element = _create_base_element('pretty_table', + type_specific_fields, + additional_fields) + + self._data['elements'].append(element) + + # endregion + ################################################################################### + ################################################################################### + # region Others + ################################################################################### + ################################################################################### + + def add_other(self, name, source_mapping, slither, additional_fields=None): + # If this a tuple with (filename, start, end), convert it to a source mapping. + if additional_fields is None: + additional_fields = {} + if isinstance(source_mapping, tuple): + # Parse the source id + (filename, start, end) = source_mapping + source_id = next( + (source_unit_id for (source_unit_id, source_unit_filename) in slither.source_units.items() if + source_unit_filename == filename), -1) + + # Convert to a source mapping string + source_mapping = f"{start}:{end}:{source_id}" + + # If this is a source mapping string, parse it. + if isinstance(source_mapping, str): + source_mapping_str = source_mapping + source_mapping = SourceMapping() + source_mapping.set_offset(source_mapping_str, slither) + + # If this is a source mapping object, get the underlying source mapping dictionary + if isinstance(source_mapping, SourceMapping): + source_mapping = source_mapping.source_mapping + + # Create the underlying element and add it to our resulting json + element = _create_base_element('other', + name, + source_mapping, + {}, + additional_fields) + self._data['elements'].append(element)