block.timestamp detector:

- Add support for "now" (close #430)
- Clean detector and use type annotation
pull/447/head
Josselin 5 years ago
parent ce2199ae26
commit 8eb6d5c00f
  1. 59
      slither/detectors/operations/block_timestamp.py

@ -2,51 +2,37 @@
Module detecting dangerous use of block.timestamp Module detecting dangerous use of block.timestamp
""" """
from slither.core.declarations import Function from typing import List, Tuple
from slither.analyses.data_dependency.data_dependency import is_tainted, is_dependent
from slither.core.declarations.solidity_variables import (SolidityFunction, from slither.analyses.data_dependency.data_dependency import is_dependent
SolidityVariableComposed) from slither.core.cfg.node import Node
from slither.core.declarations import Function, Contract
from slither.core.declarations.solidity_variables import (SolidityVariableComposed, SolidityVariable)
from slither.detectors.abstract_detector import (AbstractDetector, from slither.detectors.abstract_detector import (AbstractDetector,
DetectorClassification) DetectorClassification)
from slither.slithir.operations import Binary, BinaryType from slither.slithir.operations import Binary, BinaryType
class Timestamp(AbstractDetector): def _timestamp(func: Function) -> List[Node]:
"""
"""
ARGUMENT = 'timestamp'
HELP = 'Dangerous usage of `block.timestamp`'
IMPACT = DetectorClassification.LOW
CONFIDENCE = DetectorClassification.MEDIUM
WIKI = 'https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp'
WIKI_TITLE = 'Block timestamp'
WIKI_DESCRIPTION = 'Dangerous usage of `block.timestamp`. `block.timestamp` can be manipulated by miners.'
WIKI_EXPLOIT_SCENARIO = '''"Bob's contract relies on `block.timestamp` for its randomness. Eve is a miner and manipulates `block.timestamp` to exploit Bob's contract.'''
WIKI_RECOMMENDATION = 'Avoid relying on `block.timestamp`.'
def timestamp(self, func):
"""
"""
ret = set() ret = set()
for node in func.nodes: for node in func.nodes:
if node.contains_require_or_assert(): if node.contains_require_or_assert():
for var in node.variables_read: for var in node.variables_read:
if is_dependent(var, SolidityVariableComposed('block.timestamp'), func.contract): if is_dependent(var, SolidityVariableComposed('block.timestamp'), func.contract):
ret.add(node) ret.add(node)
if is_dependent(var, SolidityVariable('now'), func.contract):
ret.add(node)
for ir in node.irs: for ir in node.irs:
if isinstance(ir, Binary) and BinaryType.return_bool(ir.type): if isinstance(ir, Binary) and BinaryType.return_bool(ir.type):
for var in ir.read: for var in ir.read:
if is_dependent(var, SolidityVariableComposed('block.timestamp'), func.contract): if is_dependent(var, SolidityVariableComposed('block.timestamp'), func.contract):
ret.add(node) ret.add(node)
if is_dependent(var, SolidityVariable('now'), func.contract):
ret.add(node)
return list(ret) return list(ret)
def detect_dangerous_timestamp(self, contract): def _detect_dangerous_timestamp(contract: Contract) -> List[Tuple[Function, List[Node]]]:
""" """
Args: Args:
contract (Contract) contract (Contract)
@ -55,18 +41,35 @@ class Timestamp(AbstractDetector):
""" """
ret = [] ret = []
for f in [f for f in contract.functions if f.contract_declarer == contract]: for f in [f for f in contract.functions if f.contract_declarer == contract]:
nodes = self.timestamp(f) nodes = _timestamp(f)
if nodes: if nodes:
ret.append((f, nodes)) ret.append((f, nodes))
return ret return ret
class Timestamp(AbstractDetector):
"""
"""
ARGUMENT = 'timestamp'
HELP = 'Dangerous usage of `block.timestamp`'
IMPACT = DetectorClassification.LOW
CONFIDENCE = DetectorClassification.MEDIUM
WIKI = 'https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp'
WIKI_TITLE = 'Block timestamp'
WIKI_DESCRIPTION = 'Dangerous usage of `block.timestamp`. `block.timestamp` can be manipulated by miners.'
WIKI_EXPLOIT_SCENARIO = '''"Bob's contract relies on `block.timestamp` for its randomness. Eve is a miner and manipulates `block.timestamp` to exploit Bob's contract.'''
WIKI_RECOMMENDATION = 'Avoid relying on `block.timestamp`.'
def _detect(self): def _detect(self):
""" """
""" """
results = [] results = []
for c in self.contracts: for c in self.contracts:
dangerous_timestamp = self.detect_dangerous_timestamp(c) dangerous_timestamp = _detect_dangerous_timestamp(c)
for (func, nodes) in dangerous_timestamp: for (func, nodes) in dangerous_timestamp:
info = [func, " uses timestamp for comparisons\n"] info = [func, " uses timestamp for comparisons\n"]

Loading…
Cancel
Save