diff --git a/README.md b/README.md index 4d1351f05..d9c9ebe74 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ Slither is a Solidity static analysis framework written in Python 3. It runs a s - [Printers](#printers) - [Tools](#tools) - [How to Install](#how-to-install) +- [Getting Help](#getting-help) +- [Publications](#publications) ## Features @@ -178,7 +180,15 @@ Feel free to stop by our [Slack channel](https://empireslacking.herokuapp.com) ( Slither is licensed and distributed under the AGPLv3 license. [Contact us](mailto:opensource@trailofbits.com) if you're looking for an exception to the terms. -## Publication +## Publications + +### Trail of Bits publication - [Slither: A Static Analysis Framework For Smart Contracts](https://arxiv.org/abs/1908.09878), Josselin Feist, Gustavo Grieco, Alex Groce - WETSEB '19 +### External publications +- [ReJection: A AST-Based Reentrancy Vulnerability Detection Method](https://www.researchgate.net/publication/339354823_ReJection_A_AST-Based_Reentrancy_Vulnerability_Detection_Method), Rui Ma, Zefeng Jian, Guangyuan Chen, Ke Ma, Yujia Chen - CTCIS 19 +- [MPro: Combining Static and Symbolic Analysis forScalable Testing of Smart Contract](https://arxiv.org/pdf/1911.00570.pdf), William Zhang, Sebastian Banescu, Leodardo Pasos, Steven Stewart, Vijay Ganesh - ISSRE 2019 +- [ETHPLOIT: From Fuzzing to Efficient Exploit Generation against Smart Contracts](https://wcventure.github.io/FuzzingPaper/Paper/SANER20_ETHPLOIT.pdf), Qingzhao Zhang, Yizhuo Wang, Juanru Li, Siqi Ma - SANER 20 +- [Verification of Ethereum Smart Contracts: A Model Checking Approach](http://www.ijmlc.org/vol10/977-AM0059.pdf), Tam Bang, Hoang H Nguyen, Dung Nguyen, Toan Trieu, Tho Quan - IJMLC 20 + If you are using Slither on an academic work, consider applying to the [Crytic $10k Research Prize](https://blog.trailofbits.com/2019/11/13/announcing-the-crytic-10k-research-prize/). diff --git a/slither/printers/guidance/echidna.py b/slither/printers/guidance/echidna.py index 9deffa1fe..c3908ebab 100644 --- a/slither/printers/guidance/echidna.py +++ b/slither/printers/guidance/echidna.py @@ -71,7 +71,7 @@ def _is_constant(f: Function) -> bool: """ Heuristic: - If view/pure with Solidity >= 0.4 -> Return true - - If it contains assembly -> Return false (Slither doesn't analyze asm) + - If it contains assembly -> Return false (SlitherCore doesn't analyze asm) - Otherwise check for the rules from https://solidity.readthedocs.io/en/v0.5.0/contracts.html?highlight=pure#view-functions with an exception: internal dynamic call are not correctly handled, so we consider them as non-constant diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index 403127444..4572c6766 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -1051,7 +1051,7 @@ class FunctionSolc: node_parser.add_unparsed_expression(modifier) # The latest entry point is the entry point, or the latest modifier call if self._function.modifiers: - latest_entry_point = self._function.modifiers[-1].nodes[-1] + latest_entry_point = self._function.modifiers_statements[-1].nodes[-1] else: latest_entry_point = self._function.entry_point insert_node(latest_entry_point, node_parser.underlying_node) @@ -1132,6 +1132,9 @@ class FunctionSolc: node.set_sons([]) to_remove.append(node) self._function.nodes = [n for n in self._function.nodes if n not in to_remove] + for remove in to_remove: + if remove in self._node_to_nodesolc: + del self._node_to_nodesolc[remove] # endregion ################################################################################### @@ -1176,23 +1179,23 @@ class FunctionSolc: if node.type == NodeType.VARIABLE: condition_node.underlying_node.add_variable_declaration(node.variable_declaration) - true_node = self._new_node(NodeType.EXPRESSION, node.source_mapping) + true_node_parser = self._new_node(NodeType.EXPRESSION, node.source_mapping) if node.type == NodeType.VARIABLE: assert isinstance(true_expr, AssignmentOperation) # true_expr = true_expr.expression_right elif node.type == NodeType.RETURN: - true_node.type = NodeType.RETURN - true_node.underlying_node.add_expression(true_expr) - true_node.analyze_expressions(self) + true_node_parser.underlying_node.type = NodeType.RETURN + true_node_parser.underlying_node.add_expression(true_expr) + true_node_parser.analyze_expressions(self) - false_node = self._new_node(NodeType.EXPRESSION, node.source_mapping) + false_node_parser = self._new_node(NodeType.EXPRESSION, node.source_mapping) if node.type == NodeType.VARIABLE: assert isinstance(false_expr, AssignmentOperation) elif node.type == NodeType.RETURN: - false_node.type = NodeType.RETURN + false_node_parser.underlying_node.type = NodeType.RETURN # false_expr = false_expr.expression_right - false_node.underlying_node.add_expression(false_expr) - false_node.analyze_expressions(self) + false_node_parser.underlying_node.add_expression(false_expr) + false_node_parser.analyze_expressions(self) endif_node = self._new_node(NodeType.ENDIF, node.source_mapping) @@ -1206,14 +1209,15 @@ class FunctionSolc: son.add_father(endif_node.underlying_node) endif_node.underlying_node.add_son(son) - link_underlying_nodes(condition_node, true_node) - link_underlying_nodes(condition_node, false_node) + link_underlying_nodes(condition_node, true_node_parser) + link_underlying_nodes(condition_node, false_node_parser) - if true_node.type not in [NodeType.THROW, NodeType.RETURN]: - link_underlying_nodes(true_node, endif_node) - if false_node.type not in [NodeType.THROW, NodeType.RETURN]: - link_underlying_nodes(false_node, endif_node) + if true_node_parser.underlying_node.type not in [NodeType.THROW, NodeType.RETURN]: + link_underlying_nodes(true_node_parser, endif_node) + if false_node_parser.underlying_node.type not in [NodeType.THROW, NodeType.RETURN]: + link_underlying_nodes(false_node_parser, endif_node) self._function.nodes = [n for n in self._function.nodes if n.node_id != node.node_id] + del self._node_to_nodesolc[node] # endregion