diff --git a/mythril/analysis/call_helpers.py b/mythril/analysis/call_helpers.py index 32e10963..50285d3f 100644 --- a/mythril/analysis/call_helpers.py +++ b/mythril/analysis/call_helpers.py @@ -1,4 +1,5 @@ -"""This module provides helper functions for the analysis modules to deal with call functionality.""" +"""This module provides helper functions for the analysis modules to deal with +call functionality.""" from typing import Union from mythril.analysis.ops import VarType, Call, get_variable diff --git a/mythril/analysis/callgraph.py b/mythril/analysis/callgraph.py index a9f46d8f..d296c8e4 100644 --- a/mythril/analysis/callgraph.py +++ b/mythril/analysis/callgraph.py @@ -1,4 +1,5 @@ -"""This module contains the configuration and functions to create call graphs.""" +"""This module contains the configuration and functions to create call +graphs.""" import re diff --git a/mythril/analysis/modules/base.py b/mythril/analysis/modules/base.py index d75b5e02..797a3359 100644 --- a/mythril/analysis/modules/base.py +++ b/mythril/analysis/modules/base.py @@ -1,4 +1,5 @@ -"""This module contains the base class for all user-defined detection modules.""" +"""This module contains the base class for all user-defined detection +modules.""" import logging from typing import List @@ -8,7 +9,7 @@ log = logging.getLogger(__name__) class DetectionModule: """The base detection module. - + All custom-built detection modules must inherit from this class. """ @@ -22,11 +23,11 @@ class DetectionModule: ) -> None: """Initialize a new detection module. - :param name: - :param swc_id: - :param hooks: - :param description: - :param entrypoint: + :param name: + :param swc_id: + :param hooks: + :param description: + :param entrypoint: """ self.name = name self.swc_id = swc_id @@ -40,7 +41,7 @@ class DetectionModule: self.entrypoint = entrypoint def execute(self, statespace): - """ The entry point for execution, which is being called by Mythril. + """The entry point for execution, which is being called by Mythril. :param statespace: :return: diff --git a/mythril/analysis/modules/delegatecall.py b/mythril/analysis/modules/delegatecall.py index e91bd9d5..53991164 100644 --- a/mythril/analysis/modules/delegatecall.py +++ b/mythril/analysis/modules/delegatecall.py @@ -18,9 +18,7 @@ class DelegateCallModule(DetectionModule): """This module detects calldata being forwarded using DELEGATECALL.""" def __init__(self): - """ - - """ + """""" super().__init__( name="DELEGATECALL Usage in Fallback Function", swc_id=DELEGATECALL_TO_UNTRUSTED_CONTRACT, diff --git a/mythril/analysis/modules/dependence_on_predictable_vars.py b/mythril/analysis/modules/dependence_on_predictable_vars.py index c8a28ccd..26f80684 100644 --- a/mythril/analysis/modules/dependence_on_predictable_vars.py +++ b/mythril/analysis/modules/dependence_on_predictable_vars.py @@ -1,4 +1,5 @@ -"""This module contains the detection code for predictable variable dependence.""" +"""This module contains the detection code for predictable variable +dependence.""" import re from mythril.laser.ethereum.state.global_state import GlobalState from mythril.analysis.ops import Call, VarType @@ -14,12 +15,11 @@ log = logging.getLogger(__name__) class PredictableDependenceModule(DetectionModule): - """This module detects whether Ether is sent using predictable parameters.""" + """This module detects whether Ether is sent using predictable + parameters.""" def __init__(self): - """ - - """ + """""" super().__init__( name="Dependence of Predictable Variables", swc_id="{} {}".format(TIMESTAMP_DEPENDENCE, PREDICTABLE_VARS_DEPENDENCE), @@ -169,12 +169,15 @@ def _analyze_states(state: GlobalState) -> list: r = re.search(r"storage_([a-z0-9_&^]+)", str(constraint)) if r: # block.blockhash(storage_0) - """ - We actually can do better here by adding a constraint blockhash_block_storage_0 == 0 - and checking model satisfiability. When this is done, severity can be raised - from 'Informational' to 'Warning'. - Checking that storage at given index can be tainted is not necessary, since it usually contains - block.number of the 'commit' transaction in commit-reveal workflow. + """We actually can do better here by adding a constraint + blockhash_block_storage_0 == 0 and checking model + satisfiability. + + When this is done, severity can be raised from + 'Informational' to 'Warning'. Checking that storage + at given index can be tainted is not necessary, + since it usually contains block.number of the + 'commit' transaction in commit-reveal workflow. """ index = r.group(1) diff --git a/mythril/analysis/modules/deprecated_ops.py b/mythril/analysis/modules/deprecated_ops.py index 1923d47d..6a58cfb2 100644 --- a/mythril/analysis/modules/deprecated_ops.py +++ b/mythril/analysis/modules/deprecated_ops.py @@ -60,9 +60,7 @@ class DeprecatedOperationsModule(DetectionModule): """This module checks for the usage of deprecated op codes.""" def __init__(self): - """ - - """ + """""" super().__init__( name="Deprecated Operations", swc_id=DEPRICATED_FUNCTIONS_USAGE, diff --git a/mythril/analysis/modules/ether_thief.py b/mythril/analysis/modules/ether_thief.py index d2ddd8d7..624874c9 100644 --- a/mythril/analysis/modules/ether_thief.py +++ b/mythril/analysis/modules/ether_thief.py @@ -1,4 +1,5 @@ -"""This module contains the detection code for unauthorized ether withdrawal.""" +"""This module contains the detection code for unauthorized ether +withdrawal.""" from mythril.analysis.ops import * from mythril.analysis import solver from mythril.analysis.report import Issue @@ -83,12 +84,11 @@ def _analyze_state(state): class EtherThief(DetectionModule): - """This module search for cases where Ether can be withdrawn to a user-specified address.""" + """This module search for cases where Ether can be withdrawn to a user- + specified address.""" def __init__(self): - """ - - """ + """""" super().__init__( name="Ether Thief", swc_id=UNPROTECTED_ETHER_WITHDRAWAL, diff --git a/mythril/analysis/modules/exceptions.py b/mythril/analysis/modules/exceptions.py index 3933fcdb..991c50ca 100644 --- a/mythril/analysis/modules/exceptions.py +++ b/mythril/analysis/modules/exceptions.py @@ -56,14 +56,10 @@ def _analyze_state(state) -> list: class ReachableExceptionsModule(DetectionModule): - """ - - """ + """""" def __init__(self): - """ - - """ + """""" super().__init__( name="Reachable Exceptions", swc_id=ASSERT_VIOLATION, diff --git a/mythril/analysis/modules/external_calls.py b/mythril/analysis/modules/external_calls.py index 2f1a42c4..9f967711 100644 --- a/mythril/analysis/modules/external_calls.py +++ b/mythril/analysis/modules/external_calls.py @@ -1,4 +1,5 @@ -"""This module contains the detection code for potentially insecure low-level calls.""" +"""This module contains the detection code for potentially insecure low-level +calls.""" from mythril.analysis.report import Issue from mythril.analysis import solver from mythril.analysis.swc_data import REENTRANCY @@ -96,12 +97,11 @@ def _analyze_state(state): class ExternalCalls(DetectionModule): - """This module searches for low level calls (e.g. call.value()) that forward all gas to the callee.""" + """This module searches for low level calls (e.g. call.value()) that + forward all gas to the callee.""" def __init__(self): - """ - - """ + """""" super().__init__( name="External calls", swc_id=REENTRANCY, diff --git a/mythril/analysis/modules/integer.py b/mythril/analysis/modules/integer.py index 911e5f47..ff91bddc 100644 --- a/mythril/analysis/modules/integer.py +++ b/mythril/analysis/modules/integer.py @@ -1,4 +1,5 @@ -"""This module contains the detection code for integer overflows and underflows.""" +"""This module contains the detection code for integer overflows and +underflows.""" from mythril.analysis import solver from mythril.analysis.report import Issue from mythril.analysis.swc_data import INTEGER_OVERFLOW_AND_UNDERFLOW @@ -26,9 +27,7 @@ class IntegerOverflowUnderflowModule(DetectionModule): """This module searches for integer over- and underflows.""" def __init__(self): - """ - - """ + """""" super().__init__( name="Integer Overflow and Underflow", swc_id=INTEGER_OVERFLOW_AND_UNDERFLOW, @@ -41,7 +40,7 @@ class IntegerOverflowUnderflowModule(DetectionModule): ) def execute(self, statespace): - """Executes analysis module for integer underflow and integer overflow + """Executes analysis module for integer underflow and integer overflow. :param statespace: Statespace to analyse :return: Found issues @@ -137,7 +136,7 @@ class IntegerOverflowUnderflowModule(DetectionModule): def _verify_integer_overflow( self, statespace, node, expr, state, model, constraint, op0, op1 ): - """ Verifies existence of integer overflow + """Verifies existence of integer overflow. :param statespace: :param node: @@ -178,8 +177,7 @@ class IntegerOverflowUnderflowModule(DetectionModule): return None def _check_integer_underflow(self, statespace, state, node): - """ - Checks for integer underflow + """Checks for integer underflow. :param statespace: :param state: state from node to examine @@ -267,7 +265,7 @@ class IntegerOverflowUnderflowModule(DetectionModule): @staticmethod def _check_jumpi(state, taint_result): - """ Check if conditional jump is dependent on the result of expression + """Check if conditional jump is dependent on the result of expression. :param state: :param taint_result: @@ -278,7 +276,7 @@ class IntegerOverflowUnderflowModule(DetectionModule): @staticmethod def _check_sstore(state, taint_result): - """ Check if store operation is dependent on the result of expression + """Check if store operation is dependent on the result of expression. :param state: :param taint_result: @@ -298,9 +296,8 @@ class IntegerOverflowUnderflowModule(DetectionModule): depth=0, max_depth=64, ): - """ - Checks the statespace for children states, with JUMPI or SSTORE instuctions, - for dependency on expression + """Checks the statespace for children states, with JUMPI or SSTORE + instuctions, for dependency on expression. :param statespace: The statespace to explore :param node: Current node to explore from diff --git a/mythril/analysis/modules/multiple_sends.py b/mythril/analysis/modules/multiple_sends.py index a5f55abf..61ed5a51 100644 --- a/mythril/analysis/modules/multiple_sends.py +++ b/mythril/analysis/modules/multiple_sends.py @@ -1,4 +1,5 @@ -"""This module contains the detection code to find multiple sends occurring in a single transaction.""" +"""This module contains the detection code to find multiple sends occurring in +a single transaction.""" from mythril.analysis.report import Issue from mythril.analysis.swc_data import MULTIPLE_SENDS from mythril.analysis.modules.base import DetectionModule @@ -9,9 +10,7 @@ class MultipleSendsModule(DetectionModule): """This module checks for multiple sends in a single transaction.""" def __init__(self): - """ - - """ + """""" super().__init__( name="Multiple Sends", swc_id=MULTIPLE_SENDS, diff --git a/mythril/analysis/modules/suicide.py b/mythril/analysis/modules/suicide.py index 50088ccb..353be7ee 100644 --- a/mythril/analysis/modules/suicide.py +++ b/mythril/analysis/modules/suicide.py @@ -59,7 +59,8 @@ def _analyze_state(state): class SuicideModule(DetectionModule): - """This module checks if the contact can be 'accidentally' killed by anyone.""" + """This module checks if the contact can be 'accidentally' killed by + anyone.""" def __init__(self): super().__init__( diff --git a/mythril/analysis/modules/transaction_order_dependence.py b/mythril/analysis/modules/transaction_order_dependence.py index cebfc524..29f228d7 100644 --- a/mythril/analysis/modules/transaction_order_dependence.py +++ b/mythril/analysis/modules/transaction_order_dependence.py @@ -1,4 +1,5 @@ -"""This module contains the detection code to find the existence of transaction order dependence.""" +"""This module contains the detection code to find the existence of transaction +order dependence.""" import logging import re import copy @@ -31,7 +32,7 @@ class TxOrderDependenceModule(DetectionModule): ) def execute(self, statespace): - """ Executes the analysis module + """Executes the analysis module. :param statespace: :return: @@ -76,7 +77,7 @@ class TxOrderDependenceModule(DetectionModule): # TODO: move to __init__ or util module @staticmethod def _get_states_with_opcode(statespace, opcode): - """ Gets all (state, node) tuples in statespace with opcode + """Gets all (state, node) tuples in statespace with opcode. :param statespace: :param opcode: @@ -89,7 +90,8 @@ class TxOrderDependenceModule(DetectionModule): @staticmethod def _dependent_on_storage(expression): - """ Checks if expression is dependent on a storage symbol and returns the influencing storages + """Checks if expression is dependent on a storage symbol and returns + the influencing storages. :param expression: :return: @@ -99,8 +101,8 @@ class TxOrderDependenceModule(DetectionModule): @staticmethod def _get_storage_variable(storage, state): - """ - Get storage z3 object given storage name and the state + """Get storage z3 object given storage name and the state. + :param storage: storage name example: storage_0 :param state: state to retrieve the variable from :return: z3 object representing storage @@ -112,7 +114,7 @@ class TxOrderDependenceModule(DetectionModule): return None def _can_change(self, constraints, variable): - """ Checks if the variable can change given some constraints + """Checks if the variable can change given some constraints. :param constraints: :param variable: @@ -133,7 +135,8 @@ class TxOrderDependenceModule(DetectionModule): return False def _get_influencing_storages(self, call): - """ Examines a Call object and returns an iterator of all storages that influence the call value or direction + """Examines a Call object and returns an iterator of all storages that + influence the call value or direction. :param call: """ @@ -156,7 +159,7 @@ class TxOrderDependenceModule(DetectionModule): yield storage def _get_influencing_sstores(self, statespace, interesting_storages): - """ Gets sstore (state, node) tuples that write to interesting_storages + """Gets sstore (state, node) tuples that write to interesting_storages. :param statespace: :param interesting_storages: @@ -175,8 +178,8 @@ class TxOrderDependenceModule(DetectionModule): # TODO: remove @staticmethod def _try_constraints(constraints, new_constraints): - """ - Tries new constraints + """Tries new constraints. + :param constraints: :param new_constraints: :return Model if satisfiable otherwise None diff --git a/mythril/analysis/modules/unchecked_retval.py b/mythril/analysis/modules/unchecked_retval.py index 3bf60190..3d89e2fa 100644 --- a/mythril/analysis/modules/unchecked_retval.py +++ b/mythril/analysis/modules/unchecked_retval.py @@ -1,4 +1,5 @@ -"""This module contains detection code to find occurrences of calls whose return value remains unchecked.""" +"""This module contains detection code to find occurrences of calls whose +return value remains unchecked.""" from mythril.analysis.report import Issue from mythril.analysis.swc_data import UNCHECKED_RET_VAL from mythril.analysis.modules.base import DetectionModule diff --git a/mythril/analysis/ops.py b/mythril/analysis/ops.py index fe9b5d75..a4db24bc 100644 --- a/mythril/analysis/ops.py +++ b/mythril/analysis/ops.py @@ -1,4 +1,5 @@ -"""This module contains various helper methods for dealing with EVM operations.""" +"""This module contains various helper methods for dealing with EVM +operations.""" from mythril.laser.smt import simplify from enum import Enum from mythril.laser.ethereum import util diff --git a/mythril/analysis/report.py b/mythril/analysis/report.py index 6b4ef162..02656879 100644 --- a/mythril/analysis/report.py +++ b/mythril/analysis/report.py @@ -156,7 +156,7 @@ class Report: return json.dumps(result, sort_keys=True) def as_swc_standard_format(self): - """ Format defined for integration and correlation + """Format defined for integration and correlation. :return: """ diff --git a/mythril/analysis/security.py b/mythril/analysis/security.py index e8964fa1..746709de 100644 --- a/mythril/analysis/security.py +++ b/mythril/analysis/security.py @@ -1,4 +1,5 @@ -"""This module contains functionality for hooking in detection modules and executing them.""" +"""This module contains functionality for hooking in detection modules and +executing them.""" from collections import defaultdict from ethereum.opcodes import opcodes from mythril.analysis import modules diff --git a/mythril/analysis/symbolic.py b/mythril/analysis/symbolic.py index 15453ebf..64256563 100644 --- a/mythril/analysis/symbolic.py +++ b/mythril/analysis/symbolic.py @@ -1,4 +1,5 @@ -"""This module contains a wrapper around LASER for extended analysis purposes.""" +"""This module contains a wrapper around LASER for extended analysis +purposes.""" from mythril.analysis.security import get_detection_module_hooks from mythril.laser.ethereum import svm from mythril.laser.ethereum.state.account import Account @@ -16,7 +17,8 @@ from mythril.laser.ethereum.strategy.basic import ( class SymExecWrapper: """Wrapper class for the LASER Symbolic virtual machine. - Symbolically executes the code and does a bit of pre-analysis for convenience. + Symbolically executes the code and does a bit of pre-analysis for + convenience. """ def __init__( diff --git a/mythril/analysis/traceexplore.py b/mythril/analysis/traceexplore.py index 8c9d5c0b..ce06f0e9 100644 --- a/mythril/analysis/traceexplore.py +++ b/mythril/analysis/traceexplore.py @@ -1,4 +1,5 @@ -"""This module provides a function to convert a state space into a set of state nodes and transition edges.""" +"""This module provides a function to convert a state space into a set of state +nodes and transition edges.""" from z3 import Z3Exception from mythril.laser.smt import simplify from mythril.laser.ethereum.svm import NodeFlags diff --git a/mythril/disassembler/asm.py b/mythril/disassembler/asm.py index 9b8d5f44..2c9c7907 100644 --- a/mythril/disassembler/asm.py +++ b/mythril/disassembler/asm.py @@ -1,4 +1,5 @@ -"""This module contains various helper classes and functions to deal with EVM code disassembly.""" +"""This module contains various helper classes and functions to deal with EVM +code disassembly.""" import re from collections import Generator @@ -12,7 +13,7 @@ opcodes[254] = ["ASSERT_FAIL", 0, 0, 0] class EvmInstruction: - """ Model to hold the information of the disassembly.""" + """Model to hold the information of the disassembly.""" def __init__(self, address, op_code, argument=None): self.address = address @@ -60,7 +61,8 @@ def get_opcode_from_name(operation_name: str) -> int: def find_op_code_sequence(pattern: list, instruction_list: list) -> Generator: - """Returns all indices in instruction_list that point to instruction sequences following a pattern. + """Returns all indices in instruction_list that point to instruction + sequences following a pattern. :param pattern: The pattern to look for, e.g. [["PUSH1", "PUSH2"], ["EQ"]] where ["PUSH1", "EQ"] satisfies pattern :param instruction_list: List of instructions to look in diff --git a/mythril/disassembler/disassembly.py b/mythril/disassembler/disassembly.py index 1dc67ef2..e69e07b7 100644 --- a/mythril/disassembler/disassembly.py +++ b/mythril/disassembler/disassembly.py @@ -5,8 +5,7 @@ from mythril.support.signatures import SignatureDB class Disassembly(object): - """ - Disassembly class + """Disassembly class. Stores bytecode, and its disassembly. Additionally it will gather the following information on the existing functions in the disassembled code: @@ -58,10 +57,11 @@ class Disassembly(object): def get_function_info( index: int, instruction_list: list, signature_database: SignatureDB ) -> (str, int, str): - """ - Finds the function information for a call table entry - Solidity uses the first 4 bytes of the calldata to indicate which function the message call should execute - The generated code that directs execution to the correct function looks like this: + """Finds the function information for a call table entry Solidity uses the + first 4 bytes of the calldata to indicate which function the message call + should execute The generated code that directs execution to the correct + function looks like this: + - PUSH function_hash - EQ - PUSH entry_point diff --git a/mythril/ethereum/evmcontract.py b/mythril/ethereum/evmcontract.py index 48fc692b..d401f142 100644 --- a/mythril/ethereum/evmcontract.py +++ b/mythril/ethereum/evmcontract.py @@ -1,4 +1,5 @@ -"""This module contains the class representing EVM contracts, aka Smart Contracts.""" +"""This module contains the class representing EVM contracts, aka Smart +Contracts.""" from mythril.disassembler.disassembly import Disassembly from ethereum import utils import persistent @@ -6,7 +7,8 @@ import re class EVMContract(persistent.Persistent): - """This class represents an address with associated code (Smart Contract).""" + """This class represents an address with associated code (Smart + Contract).""" def __init__( self, code="", creation_code="", name="Unknown", enable_online_lookup=False diff --git a/mythril/ethereum/interface/leveldb/accountindexing.py b/mythril/ethereum/interface/leveldb/accountindexing.py index c7299119..45bcefff 100644 --- a/mythril/ethereum/interface/leveldb/accountindexing.py +++ b/mythril/ethereum/interface/leveldb/accountindexing.py @@ -1,7 +1,7 @@ """This module contains account indexing functionality. -This includes a sedes class for lists, account storage receipts for LevelDB -and a class for updating account addresses. +This includes a sedes class for lists, account storage receipts for +LevelDB and a class for updating account addresses. """ import logging from mythril import ethereum @@ -20,6 +20,7 @@ BATCH_SIZE = 8 * 4096 class CountableList(object): """A sedes for lists of arbitrary length. + :param element_sedes: when (de-)serializing a list, this sedes will be applied to all of its elements """ @@ -50,9 +51,7 @@ class CountableList(object): class ReceiptForStorage(rlp.Serializable): - """ - Receipt format stored in levelDB - """ + """Receipt format stored in levelDB.""" fields = [ ("state_root", binary), @@ -66,9 +65,7 @@ class ReceiptForStorage(rlp.Serializable): class AccountIndexer(object): - """ - Updates address index - """ + """Updates address index.""" def __init__(self, ethDB): self.db = ethDB @@ -78,9 +75,8 @@ class AccountIndexer(object): self.updateIfNeeded() def get_contract_by_hash(self, contract_hash): - """ - get mapped contract_address by its hash, if not found try indexing - """ + """get mapped contract_address by its hash, if not found try + indexing.""" contract_address = self.db.reader._get_address_by_hash(contract_hash) if contract_address is not None: return contract_address @@ -89,9 +85,7 @@ class AccountIndexer(object): raise AddressNotFoundError def _process(self, startblock): - """ - Processesing method - """ + """Processesing method.""" log.debug("Processing blocks %d to %d" % (startblock, startblock + BATCH_SIZE)) addresses = [] @@ -113,9 +107,7 @@ class AccountIndexer(object): return addresses def updateIfNeeded(self): - """ - update address index - """ + """update address index.""" headBlock = self.db.reader._get_head_block() if headBlock is not None: # avoid restarting search if head block is same & we already initialized diff --git a/mythril/ethereum/interface/leveldb/client.py b/mythril/ethereum/interface/leveldb/client.py index 9e1c71f7..3373d3f1 100644 --- a/mythril/ethereum/interface/leveldb/client.py +++ b/mythril/ethereum/interface/leveldb/client.py @@ -158,9 +158,7 @@ class LevelDBReader(object): class LevelDBWriter(object): - """ - level db writing interface - """ + """level db writing interface.""" def __init__(self, db): """ @@ -183,7 +181,7 @@ class LevelDBWriter(object): self.wb = self.db.write_batch() def _commit_batch(self): - """Commit a batch""" + """Commit a batch.""" self.wb.write() def _store_account_address(self, address): @@ -196,9 +194,7 @@ class LevelDBWriter(object): class EthLevelDB(object): - """ - Go-Ethereum LevelDB client class - """ + """Go-Ethereum LevelDB client class.""" def __init__(self, path): """ @@ -235,10 +231,12 @@ class EthLevelDB(object): try: address = _encode_hex(indexer.get_contract_by_hash(address_hash)) except AddressNotFoundError: - """ - The hash->address mapping does not exist in our index. If the index is up-to-date, this likely means - that the contract was created by an internal transaction. Skip this contract as right now we don't - have a good solution for this. + """The hash->address mapping does not exist in our index. + + If the index is up-to-date, this likely means that + the contract was created by an internal transaction. + Skip this contract as right now we don't have a good + solution for this. """ continue diff --git a/mythril/ethereum/interface/leveldb/eth_db.py b/mythril/ethereum/interface/leveldb/eth_db.py index 7ba6f5de..a296f696 100644 --- a/mythril/ethereum/interface/leveldb/eth_db.py +++ b/mythril/ethereum/interface/leveldb/eth_db.py @@ -1,4 +1,5 @@ -"""This module contains the ETH_DB class, which the base database used by pyethereum.""" +"""This module contains the ETH_DB class, which the base database used by +pyethereum.""" import plyvel from ethereum.db import BaseDB @@ -10,19 +11,13 @@ class ETH_DB(BaseDB): self.db = plyvel.DB(path) def get(self, key): - """ - gets value for key - """ + """gets value for key.""" return self.db.get(key) def put(self, key, value): - """ - puts value for key - """ + """puts value for key.""" self.db.put(key, value) def write_batch(self): - """ - start writing a batch - """ + """start writing a batch.""" return self.db.write_batch() diff --git a/mythril/ethereum/interface/leveldb/state.py b/mythril/ethereum/interface/leveldb/state.py index 7d16bfa1..4cd5c133 100644 --- a/mythril/ethereum/interface/leveldb/state.py +++ b/mythril/ethereum/interface/leveldb/state.py @@ -48,9 +48,7 @@ STATE_DEFAULTS = { class Account(rlp.Serializable): - """ - adjusted account from ethereum.state - """ + """adjusted account from ethereum.state.""" fields = [ ("nonce", big_endian_int), @@ -82,14 +80,11 @@ class Account(rlp.Serializable): @property def code(self): - """ - code rlp data - """ + """code rlp data.""" return self.db.get(self.code_hash) def get_storage_data(self, key): - """ - get storage data + """get storage data. :param key: :return: @@ -103,8 +98,8 @@ class Account(rlp.Serializable): @classmethod def blank_account(cls, db, addr, initial_nonce=0): - """ - creates a blank account + """creates a blank account. + :param db: :param addr: :param initial_nonce: @@ -116,17 +111,15 @@ class Account(rlp.Serializable): return o def is_blank(self): - """ - checks if is a blank account + """checks if is a blank account. + :return: """ return self.nonce == 0 and self.balance == 0 and self.code_hash == BLANK_HASH class State: - """ - adjusted state from ethereum.state - """ + """adjusted state from ethereum.state.""" def __init__(self, db, root): """ @@ -141,7 +134,8 @@ class State: self.cache = {} def get_and_cache_account(self, addr): - """Gets and caches an account for an addres, creates blank if not found + """Gets and caches an account for an addres, creates blank if not + found. :param addr: :return: @@ -165,9 +159,7 @@ class State: return o def get_all_accounts(self): - """ - iterates through trie to and yields non-blank leafs as accounts - """ + """iterates through trie to and yields non-blank leafs as accounts.""" for address_hash, rlpdata in self.secure_trie.trie.iter_branch(): if rlpdata != trie.BLANK_NODE: yield rlp.decode(rlpdata, Account, db=self.db, address=address_hash) diff --git a/mythril/ethereum/interface/rpc/constants.py b/mythril/ethereum/interface/rpc/constants.py index b16dd98d..183bd1d3 100644 --- a/mythril/ethereum/interface/rpc/constants.py +++ b/mythril/ethereum/interface/rpc/constants.py @@ -1,4 +1,5 @@ -"""This file contains constants used used by the Ethereum JSON RPC interface.""" +"""This file contains constants used used by the Ethereum JSON RPC +interface.""" BLOCK_TAG_EARLIEST = "earliest" BLOCK_TAG_LATEST = "latest" BLOCK_TAG_PENDING = "pending" diff --git a/mythril/ethereum/interface/rpc/exceptions.py b/mythril/ethereum/interface/rpc/exceptions.py index 8806dff0..3b5cccd5 100644 --- a/mythril/ethereum/interface/rpc/exceptions.py +++ b/mythril/ethereum/interface/rpc/exceptions.py @@ -8,24 +8,28 @@ class EthJsonRpcError(Exception): class ConnectionError(EthJsonRpcError): - """An RPC exception denoting there was an error in connecting to the RPC instance.""" + """An RPC exception denoting there was an error in connecting to the RPC + instance.""" pass class BadStatusCodeError(EthJsonRpcError): - """An RPC exception denoting a bad status code returned by the RPC instance.""" + """An RPC exception denoting a bad status code returned by the RPC + instance.""" pass class BadJsonError(EthJsonRpcError): - """An RPC exception denoting that the RPC instance returned a bad JSON object.""" + """An RPC exception denoting that the RPC instance returned a bad JSON + object.""" pass class BadResponseError(EthJsonRpcError): - """An RPC exception denoting that the RPC instance returned a bad response.""" + """An RPC exception denoting that the RPC instance returned a bad + response.""" pass diff --git a/mythril/ethereum/interface/rpc/utils.py b/mythril/ethereum/interface/rpc/utils.py index 00daed00..60033795 100644 --- a/mythril/ethereum/interface/rpc/utils.py +++ b/mythril/ethereum/interface/rpc/utils.py @@ -1,10 +1,10 @@ -"""This module contains various utility functions regarding the RPC data format and validation.""" +"""This module contains various utility functions regarding the RPC data format +and validation.""" from .constants import BLOCK_TAGS def hex_to_dec(x): - """ - Convert hex to decimal + """Convert hex to decimal. :param x: :return: @@ -13,9 +13,8 @@ def hex_to_dec(x): def clean_hex(d): - """ - Convert decimal to hex and remove the "L" suffix that is appended to large - numbers + """Convert decimal to hex and remove the "L" suffix that is appended to + large numbers. :param d: :return: @@ -38,7 +37,7 @@ def validate_block(block): def wei_to_ether(wei): - """Convert wei to ether + """Convert wei to ether. :param wei: :return: @@ -47,7 +46,7 @@ def wei_to_ether(wei): def ether_to_wei(ether): - """Convert ether to wei + """Convert ether to wei. :param ether: :return: diff --git a/mythril/ethereum/util.py b/mythril/ethereum/util.py index 8c0c8660..c672a437 100644 --- a/mythril/ethereum/util.py +++ b/mythril/ethereum/util.py @@ -1,4 +1,5 @@ -"""This module contains various utility functions regarding unit conversion and solc integration.""" +"""This module contains various utility functions regarding unit conversion and +solc integration.""" from ethereum.abi import encode_abi, encode_int from ethereum.utils import zpad from ethereum.abi import method_id diff --git a/mythril/exceptions.py b/mythril/exceptions.py index 33e69e35..7988759b 100644 --- a/mythril/exceptions.py +++ b/mythril/exceptions.py @@ -14,24 +14,28 @@ class CompilerError(MythrilBaseException): class UnsatError(MythrilBaseException): - """A Mythril exception denoting the unsatisfiability of a series of constraints.""" + """A Mythril exception denoting the unsatisfiability of a series of + constraints.""" pass class NoContractFoundError(MythrilBaseException): - """A Mythril exception denoting that a given contract file was not found.""" + """A Mythril exception denoting that a given contract file was not + found.""" pass class CriticalError(MythrilBaseException): - """A Mythril exception denoting an unknown critical error has been encountered.""" + """A Mythril exception denoting an unknown critical error has been + encountered.""" pass class AddressNotFoundError(MythrilBaseException): - """A Mythril exception denoting the given smart contract address was not found.""" + """A Mythril exception denoting the given smart contract address was not + found.""" pass diff --git a/mythril/interfaces/epic.py b/mythril/interfaces/epic.py index 9aaf21aa..c18f984d 100755 --- a/mythril/interfaces/epic.py +++ b/mythril/interfaces/epic.py @@ -21,9 +21,7 @@ PY3 = sys.version_info >= (3,) # Reset terminal colors at exit def reset(): - """ - - """ + """""" sys.stdout.write("\x1b[0m") sys.stdout.flush() @@ -53,7 +51,7 @@ COLOR_ANSI = ( class LolCat(object): - """Cats lel""" + """Cats lel.""" def __init__(self, mode=256, output=sys.stdout): self.mode = mode @@ -193,9 +191,7 @@ class LolCat(object): def detect_mode(term_hint="xterm-256color"): - """ - Poor-mans color mode detection. - """ + """Poor-mans color mode detection.""" if "ANSICON" in os.environ: return 16 elif os.environ.get("ConEmuANSI", "OFF") == "ON": diff --git a/mythril/laser/ethereum/call.py b/mythril/laser/ethereum/call.py index ec9bb026..226814ef 100644 --- a/mythril/laser/ethereum/call.py +++ b/mythril/laser/ethereum/call.py @@ -1,7 +1,6 @@ -""" -This module contains the business logic used by Instruction in instructions.py -to get the necessary elements from the stack and determine the parameters for the new global state. -""" +"""This module contains the business logic used by Instruction in +instructions.py to get the necessary elements from the stack and determine the +parameters for the new global state.""" import logging from typing import Union @@ -28,9 +27,9 @@ log = logging.getLogger(__name__) def get_call_parameters( global_state: GlobalState, dynamic_loader: DynLoader, with_value=False ): - """ - Gets call parameters from global state - Pops the values from the stack and determines output parameters + """Gets call parameters from global state Pops the values from the stack + and determines output parameters. + :param global_state: state to look in :param dynamic_loader: dynamic loader to use :param with_value: whether to pop the value argument from the stack @@ -71,8 +70,8 @@ def get_callee_address( dynamic_loader: DynLoader, symbolic_to_address: Expression, ): - """ - Gets the address of the callee + """Gets the address of the callee. + :param global_state: state to look in :param dynamic_loader: dynamic loader to use :param symbolic_to_address: The (symbolic) callee address @@ -114,8 +113,8 @@ def get_callee_address( def get_callee_account( global_state: GlobalState, callee_address: str, dynamic_loader: DynLoader ): - """ - Gets the callees account from the global_state + """Gets the callees account from the global_state. + :param global_state: state to look in :param callee_address: address of the callee :param dynamic_loader: dynamic loader to use @@ -158,8 +157,8 @@ def get_call_data( memory_start: Union[int, Expression], memory_size: Union[int, Expression], ): - """ - Gets call_data from the global_state + """Gets call_data from the global_state. + :param global_state: state to look in :param memory_start: Start index :param memory_size: Size diff --git a/mythril/laser/ethereum/cfg.py b/mythril/laser/ethereum/cfg.py index c9a71ee2..576115af 100644 --- a/mythril/laser/ethereum/cfg.py +++ b/mythril/laser/ethereum/cfg.py @@ -1,4 +1,4 @@ -"""This module """ +"""This module.""" from flags import Flags from enum import Enum from typing import Dict diff --git a/mythril/laser/ethereum/gas.py b/mythril/laser/ethereum/gas.py index 8c46fe94..43c5d48b 100644 --- a/mythril/laser/ethereum/gas.py +++ b/mythril/laser/ethereum/gas.py @@ -1,4 +1,5 @@ -"""This module contains functions for dynamic gas calculation and a gas cost table.""" +"""This module contains functions for dynamic gas calculation and a gas cost +table.""" from ethereum import opcodes from ethereum.utils import ceil32 diff --git a/mythril/laser/ethereum/instructions.py b/mythril/laser/ethereum/instructions.py index 2ed3fc64..d81a2de8 100644 --- a/mythril/laser/ethereum/instructions.py +++ b/mythril/laser/ethereum/instructions.py @@ -1,4 +1,5 @@ -"""This module contains a representation class for EVM instructions and transitions between them.""" +"""This module contains a representation class for EVM instructions and +transitions between them.""" import binascii import logging @@ -63,9 +64,10 @@ keccak_function_manager = KeccakFunctionManager() class StateTransition(object): """Decorator that handles global state copy and original return. - This decorator calls the decorated instruction mutator function on a copy of the state that - is passed to it. After the call, the resulting new states' program counter is automatically - incremented if `increment_pc=True`. + This decorator calls the decorated instruction mutator function on a + copy of the state that is passed to it. After the call, the + resulting new states' program counter is automatically incremented + if `increment_pc=True`. """ def __init__(self, increment_pc=True, enable_gas=True): @@ -153,9 +155,8 @@ class StateTransition(object): class Instruction: - """ - Instruction class is used to mutate a state according to the current instruction - """ + """Instruction class is used to mutate a state according to the current + instruction.""" def __init__(self, op_code: str, dynamic_loader: DynLoader): """ @@ -167,7 +168,7 @@ class Instruction: self.op_code = op_code.upper() def evaluate(self, global_state: GlobalState, post=False) -> List[GlobalState]: - """ Performs the mutation for this instruction + """Performs the mutation for this instruction. :param global_state: :param post: diff --git a/mythril/laser/ethereum/keccak.py b/mythril/laser/ethereum/keccak.py index abc79ec0..9d2aefdc 100644 --- a/mythril/laser/ethereum/keccak.py +++ b/mythril/laser/ethereum/keccak.py @@ -1,4 +1,5 @@ -"""This module contains a function manager to deal with symbolic Keccak values.""" +"""This module contains a function manager to deal with symbolic Keccak +values.""" from mythril.laser.smt import Expression @@ -6,9 +7,7 @@ class KeccakFunctionManager: """A keccak function manager for symbolic expressions.""" def __init__(self): - """ - - """ + """""" self.keccak_expression_mapping = {} def is_keccak(self, expression: Expression) -> bool: diff --git a/mythril/laser/ethereum/natives.py b/mythril/laser/ethereum/natives.py index bcf73054..e36d49c2 100644 --- a/mythril/laser/ethereum/natives.py +++ b/mythril/laser/ethereum/natives.py @@ -124,7 +124,7 @@ def identity(data: Union[bytes, str, List[int]]) -> bytes: def native_contracts(address: int, data: BaseCalldata): - """Takes integer address 1, 2, 3, 4 + """Takes integer address 1, 2, 3, 4. :param address: :param data: diff --git a/mythril/laser/ethereum/state/account.py b/mythril/laser/ethereum/state/account.py index 7cff77d9..a25b8dee 100644 --- a/mythril/laser/ethereum/state/account.py +++ b/mythril/laser/ethereum/state/account.py @@ -12,13 +12,11 @@ from mythril.disassembler.disassembly import Disassembly class Storage: - """ - Storage class represents the storage of an Account - """ + """Storage class represents the storage of an Account.""" def __init__(self, concrete=False, address=None, dynamic_loader=None): - """ - Constructor for Storage + """Constructor for Storage. + :param concrete: bool indicating whether to interpret uninitialized storage as concrete versus symbolic """ self._storage = {} @@ -62,9 +60,7 @@ class Storage: class Account: - """ - Account class representing ethereum accounts - """ + """Account class representing ethereum accounts.""" def __init__( self, @@ -75,8 +71,8 @@ class Account: concrete_storage=False, dynamic_loader=None, ): - """ - Constructor for account + """Constructor for account. + :param address: Address of the account :param code: The contract code of the account :param contract_name: The name associated with the account diff --git a/mythril/laser/ethereum/state/annotation.py b/mythril/laser/ethereum/state/annotation.py index fe031d97..6a321776 100644 --- a/mythril/laser/ethereum/state/annotation.py +++ b/mythril/laser/ethereum/state/annotation.py @@ -1,20 +1,21 @@ """This module includes classes used for annotating trace information. -This includes the base StateAnnotation class, as well as an adaption, which will not be -copied on every new state. +This includes the base StateAnnotation class, as well as an adaption, +which will not be copied on every new state. """ class StateAnnotation: - """ - The StateAnnotation class is used to persist information over traces. This allows modules to reason about traces - without the need to traverse the state space themselves. + """The StateAnnotation class is used to persist information over traces. + + This allows modules to reason about traces without the need to + traverse the state space themselves. """ @property def persist_to_world_state(self) -> bool: - """ - If this function returns true then laser will also annotate the world state. + """If this function returns true then laser will also annotate the + world state. If you want annotations to persist through different user initiated message call transactions then this should be enabled. @@ -25,10 +26,11 @@ class StateAnnotation: class NoCopyAnnotation(StateAnnotation): - """ - This class provides a base annotation class for annotations that shouldn't be copied on every new state. - Rather the same object should be propagated. - This is very useful if you are looking to analyze a property over multiple substates + """This class provides a base annotation class for annotations that + shouldn't be copied on every new state. + + Rather the same object should be propagated. This is very useful if + you are looking to analyze a property over multiple substates """ def __copy__(self): diff --git a/mythril/laser/ethereum/state/calldata.py b/mythril/laser/ethereum/state/calldata.py index 688e28cd..4440cb22 100644 --- a/mythril/laser/ethereum/state/calldata.py +++ b/mythril/laser/ethereum/state/calldata.py @@ -18,10 +18,8 @@ class CalldataType(Enum): class BaseCalldata: - """ - Base calldata class - This represents the calldata provided when sending a transaction to a contract - """ + """Base calldata class This represents the calldata provided when sending a + transaction to a contract.""" def __init__(self, tx_id): """ @@ -42,7 +40,7 @@ class BaseCalldata: return result def get_word_at(self, offset: int) -> Expression: - """ Gets word at offset + """Gets word at offset. :param offset: :return: @@ -94,14 +92,14 @@ class BaseCalldata: @property def size(self) -> Union[Expression, int]: - """ Returns the exact size of this calldata, this is not normalized + """Returns the exact size of this calldata, this is not normalized. :return: unnormalized call data size """ raise NotImplementedError() def concrete(self, model: Model) -> list: - """ Returns a concrete version of the calldata using the provided model + """Returns a concrete version of the calldata using the provided model. :param model: """ @@ -112,8 +110,7 @@ class ConcreteCalldata(BaseCalldata): """A concrete call data representation.""" def __init__(self, tx_id: int, calldata: list): - """ - Initializes the ConcreteCalldata object. + """Initializes the ConcreteCalldata object. :param tx_id: Id of the transaction that the calldata is for. :param calldata: The concrete calldata content @@ -257,8 +254,8 @@ class BasicSymbolicCalldata(BaseCalldata): """A basic class representing symbolic call data.""" def __init__(self, tx_id: int): - """ - Initializes the SymbolicCalldata object + """Initializes the SymbolicCalldata object. + :param tx_id: Id of the transaction that the calldata is for. """ self._reads = [] diff --git a/mythril/laser/ethereum/state/constraints.py b/mythril/laser/ethereum/state/constraints.py index 01133081..e6c469a7 100644 --- a/mythril/laser/ethereum/state/constraints.py +++ b/mythril/laser/ethereum/state/constraints.py @@ -1,10 +1,12 @@ -"""This module contains the class used to represent state-change constraints in the call graph.""" +"""This module contains the class used to represent state-change constraints in +the call graph.""" class Constraints(list): - """ - This class should maintain a solver and it's constraints, This class tries to make the Constraints() object - as a simple list of constraints with some background processing. + """This class should maintain a solver and it's constraints, This class + tries to make the Constraints() object as a simple list of constraints with + some background processing. + TODO: add the solver to this class after callback refactor """ diff --git a/mythril/laser/ethereum/state/environment.py b/mythril/laser/ethereum/state/environment.py index e77b2732..7c904fbc 100644 --- a/mythril/laser/ethereum/state/environment.py +++ b/mythril/laser/ethereum/state/environment.py @@ -1,4 +1,5 @@ -"""This module contains the representation for an execution state's environment.""" +"""This module contains the representation for an execution state's +environment.""" from typing import Dict from z3 import ExprRef, BitVecVal @@ -9,7 +10,8 @@ from mythril.laser.ethereum.state.calldata import CalldataType, BaseCalldata class Environment: - """The environment class represents the current execution environment for the symbolic executor.""" + """The environment class represents the current execution environment for + the symbolic executor.""" def __init__( self, diff --git a/mythril/laser/ethereum/state/global_state.py b/mythril/laser/ethereum/state/global_state.py index 3d41e148..8facc663 100644 --- a/mythril/laser/ethereum/state/global_state.py +++ b/mythril/laser/ethereum/state/global_state.py @@ -12,9 +12,7 @@ from mythril.laser.ethereum.state.annotation import StateAnnotation class GlobalState: - """ - GlobalState represents the current globalstate - """ + """GlobalState represents the current globalstate.""" def __init__( self, @@ -26,7 +24,7 @@ class GlobalState: last_return_data=None, annotations=None, ): - """ Constructor for GlobalState + """Constructor for GlobalState. :param world_state: :param environment: @@ -76,7 +74,7 @@ class GlobalState: # TODO: remove this, as two instructions are confusing def get_current_instruction(self) -> Dict: - """ Gets the current instruction for this GlobalState + """Gets the current instruction for this GlobalState. :return: """ @@ -135,9 +133,9 @@ class GlobalState: return self._annotations def get_annotations(self, annotation_type: type) -> Iterable[StateAnnotation]: - """ - Filters annotations for the queried annotation type. Designed particularly for - modules with annotations: globalstate.get_annotations(MySpecificModuleAnnotation) + """Filters annotations for the queried annotation type. Designed + particularly for modules with annotations: + globalstate.get_annotations(MySpecificModuleAnnotation) :param annotation_type: The type to filter annotations for :return: filter of matching annotations diff --git a/mythril/laser/ethereum/state/machine_state.py b/mythril/laser/ethereum/state/machine_state.py index 4cb5ed1a..b4279c90 100644 --- a/mythril/laser/ethereum/state/machine_state.py +++ b/mythril/laser/ethereum/state/machine_state.py @@ -1,4 +1,5 @@ -"""This module contains a representation of the EVM's machine state and its stack.""" +"""This module contains a representation of the EVM's machine state and its +stack.""" from copy import copy from typing import Union, Any, List, Dict @@ -15,9 +16,7 @@ from mythril.laser.ethereum.state.memory import Memory class MachineStack(list): - """ - Defines EVM stack, overrides the default list to handle overflows - """ + """Defines EVM stack, overrides the default list to handle overflows.""" STACK_LIMIT = 1024 @@ -68,24 +67,23 @@ class MachineStack(list): ) def __add__(self, other): - """Implement list concatenation if needed + """Implement list concatenation if needed. :param other: """ raise NotImplementedError("Implement this if needed") def __iadd__(self, other): - """ - Implement list concatenation if needed + """Implement list concatenation if needed. + :param other: """ raise NotImplementedError("Implement this if needed") class MachineState: - """ - MachineState represents current machine state also referenced to as \mu - """ + """MachineState represents current machine state also referenced to as + \mu.""" def __init__( self, @@ -98,7 +96,7 @@ class MachineState: max_gas_used=0, min_gas_used=0, ): - """ Constructor for machineState + """Constructor for machineState. :param gas_limit: :param pc: @@ -153,7 +151,7 @@ class MachineState: raise OutOfGasException() def mem_extend(self, start: int, size: int) -> None: - """Extends the memory of this machine state + """Extends the memory of this machine state. :param start: Start of memory extension :param size: Size of memory extension @@ -167,7 +165,7 @@ class MachineState: self.memory.extend(m_extend) def memory_write(self, offset: int, data: List[int]) -> None: - """ Writes data to memory starting at offset + """Writes data to memory starting at offset. :param offset: :param data: @@ -176,7 +174,7 @@ class MachineState: self.memory[offset : offset + len(data)] = data def pop(self, amount=1) -> Union[BitVec, List[BitVec]]: - """ Pops amount elements from the stack + """Pops amount elements from the stack. :param amount: :return: diff --git a/mythril/laser/ethereum/state/memory.py b/mythril/laser/ethereum/state/memory.py index 4511364e..74d5c547 100644 --- a/mythril/laser/ethereum/state/memory.py +++ b/mythril/laser/ethereum/state/memory.py @@ -17,9 +17,7 @@ class Memory: """A class representing contract memory with random access.""" def __init__(self): - """ - - """ + """""" self._memory = [] def __len__(self): @@ -37,7 +35,7 @@ class Memory: self._memory.extend(bytearray(size)) def get_word_at(self, index: int) -> Union[int, BitVec]: - """Access a word from a specified memory index + """Access a word from a specified memory index. :param index: integer representing the index to access :return: 32 byte word at the specified index diff --git a/mythril/laser/ethereum/state/world_state.py b/mythril/laser/ethereum/state/world_state.py index ed7d57e1..7bcd06b4 100644 --- a/mythril/laser/ethereum/state/world_state.py +++ b/mythril/laser/ethereum/state/world_state.py @@ -8,15 +8,13 @@ from mythril.laser.ethereum.state.annotation import StateAnnotation class WorldState: - """ - The WorldState class represents the world state as described in the yellow paper - """ + """The WorldState class represents the world state as described in the + yellow paper.""" def __init__( self, transaction_sequence=None, annotations: List[StateAnnotation] = None ) -> None: - """ - Constructor for the world state. Initializes the accounts record + """Constructor for the world state. Initializes the accounts record. :param transaction_sequence: :param annotations: @@ -27,8 +25,7 @@ class WorldState: self._annotations = annotations or [] def __getitem__(self, item: str) -> Account: - """ - Gets an account from the worldstate using item as key + """Gets an account from the worldstate using item as key. :param item: Address of the account to get :return: Account associated with the address @@ -52,8 +49,7 @@ class WorldState: def create_account( self, balance=0, address=None, concrete_storage=False, dynamic_loader=None ) -> Account: - """ - Create non-contract account + """Create non-contract account. :param address: The account's address :param balance: Initial balance for the account @@ -72,9 +68,9 @@ class WorldState: return new_account def create_initialized_contract_account(self, contract_code, storage) -> None: - """ - Creates a new contract account, based on the contract code and storage provided - The contract code only includes the runtime contract bytecode + """Creates a new contract account, based on the contract code and + storage provided The contract code only includes the runtime contract + bytecode. :param contract_code: Runtime bytecode for the contract :param storage: Initial storage for the contract @@ -103,9 +99,9 @@ class WorldState: return self._annotations def get_annotations(self, annotation_type: type) -> Iterator[StateAnnotation]: - """ - Filters annotations for the queried annotation type. Designed particularly for - modules with annotations: worldstate.get_annotations(MySpecificModuleAnnotation) + """Filters annotations for the queried annotation type. Designed + particularly for modules with annotations: + worldstate.get_annotations(MySpecificModuleAnnotation) :param annotation_type: The type to filter annotations for :return: filter of matching annotations @@ -113,7 +109,7 @@ class WorldState: return filter(lambda x: isinstance(x, annotation_type), self.annotations) def _generate_new_address(self) -> str: - """ Generates a new address for the global state + """Generates a new address for the global state. :return: """ diff --git a/mythril/laser/ethereum/strategy/__init__.py b/mythril/laser/ethereum/strategy/__init__.py index 10120dd3..58672339 100644 --- a/mythril/laser/ethereum/strategy/__init__.py +++ b/mythril/laser/ethereum/strategy/__init__.py @@ -2,9 +2,7 @@ from abc import ABC, abstractmethod class BasicSearchStrategy(ABC): - """ - - """ + """""" __slots__ = "work_list", "max_depth" @@ -17,9 +15,7 @@ class BasicSearchStrategy(ABC): @abstractmethod def get_strategic_global_state(self): - """ - - """ + """""" raise NotImplementedError("Must be implemented by a subclass") def __next__(self): diff --git a/mythril/laser/ethereum/strategy/basic.py b/mythril/laser/ethereum/strategy/basic.py index 4e05b270..d46c2c33 100644 --- a/mythril/laser/ethereum/strategy/basic.py +++ b/mythril/laser/ethereum/strategy/basic.py @@ -1,6 +1,4 @@ -""" -This module implements basic symbolic execution search strategies -""" +"""This module implements basic symbolic execution search strategies.""" from mythril.laser.ethereum.state.global_state import GlobalState from typing import List from random import randrange @@ -16,8 +14,8 @@ except ImportError: from bisect import bisect def choices(population, weights=None): - """ - Returns a random element out of the population based on weight. + """Returns a random element out of the population based on weight. + If the relative weights or cumulative weights are not specified, the selections are made with equal probability. """ @@ -32,9 +30,9 @@ except ImportError: class DepthFirstSearchStrategy(BasicSearchStrategy): - """ - Implements a depth first search strategy - I.E. Follow one path to a leaf, and then continue to the next one + """Implements a depth first search strategy I.E. + + Follow one path to a leaf, and then continue to the next one """ def get_strategic_global_state(self) -> GlobalState: @@ -46,9 +44,9 @@ class DepthFirstSearchStrategy(BasicSearchStrategy): class BreadthFirstSearchStrategy(BasicSearchStrategy): - """ - Implements a breadth first search strategy - I.E. Execute all states of a "level" before continuing + """Implements a breadth first search strategy I.E. + + Execute all states of a "level" before continuing """ def get_strategic_global_state(self) -> GlobalState: @@ -60,9 +58,7 @@ class BreadthFirstSearchStrategy(BasicSearchStrategy): class ReturnRandomNaivelyStrategy(BasicSearchStrategy): - """ - chooses a random state from the worklist with equal likelihood - """ + """chooses a random state from the worklist with equal likelihood.""" def get_strategic_global_state(self) -> GlobalState: """ @@ -76,9 +72,8 @@ class ReturnRandomNaivelyStrategy(BasicSearchStrategy): class ReturnWeightedRandomStrategy(BasicSearchStrategy): - """ - chooses a random state from the worklist with likelihood based on inverse proportion to depth - """ + """chooses a random state from the worklist with likelihood based on + inverse proportion to depth.""" def get_strategic_global_state(self) -> GlobalState: """ diff --git a/mythril/laser/ethereum/svm.py b/mythril/laser/ethereum/svm.py index aa3eff05..30e29039 100644 --- a/mythril/laser/ethereum/svm.py +++ b/mythril/laser/ethereum/svm.py @@ -36,10 +36,12 @@ class SVMError(Exception): class LaserEVM: """The LASER EVM. - Just as Mithril had to be mined at great efforts to provide the Dwarves with their exceptional armour, - LASER stands at the heart of Mythril, digging deep in the depths of call graphs, unearthing the most - precious symbolic call data, that is then hand-forged into beautiful and strong security issues by - the experienced smiths we call detection modules. It is truly a magnificent symbiosis. + Just as Mithril had to be mined at great efforts to provide the + Dwarves with their exceptional armour, LASER stands at the heart of + Mythril, digging deep in the depths of call graphs, unearthing the + most precious symbolic call data, that is then hand-forged into + beautiful and strong security issues by the experienced smiths we + call detection modules. It is truly a magnificent symbiosis. """ def __init__( @@ -166,8 +168,9 @@ class LaserEVM: log.info("Achieved {:.2f}% coverage for code: {}".format(cov, code)) def _execute_transactions(self, address): - """ - This function executes multiple transactions on the address based on the coverage + """This function executes multiple transactions on the address based on + the coverage. + :param address: Address of the contract :return: """ @@ -188,7 +191,8 @@ class LaserEVM: ) def _get_covered_instructions(self) -> int: - """ Gets the total number of covered instructions for all accounts in the svm + """Gets the total number of covered instructions for all accounts in + the svm. :return: """ diff --git a/mythril/laser/ethereum/taint_analysis.py b/mythril/laser/ethereum/taint_analysis.py index d66f98ec..9645178b 100644 --- a/mythril/laser/ethereum/taint_analysis.py +++ b/mythril/laser/ethereum/taint_analysis.py @@ -13,20 +13,19 @@ log = logging.getLogger(__name__) class TaintRecord: - """ - TaintRecord contains tainting information for a specific (state, node) - the information specifies the taint status before executing the operation belonging to the state - """ + """TaintRecord contains tainting information for a specific (state, node) + the information specifies the taint status before executing the operation + belonging to the state.""" def __init__(self): - """ Builds a taint record """ + """Builds a taint record.""" self.stack = [] self.memory = {} self.storage = {} self.states = [] def stack_tainted(self, index: int) -> Union[bool, None]: - """ Returns taint value of stack element at index + """Returns taint value of stack element at index. :param index: :return: @@ -36,7 +35,7 @@ class TaintRecord: return None def memory_tainted(self, index: int) -> bool: - """ Returns taint value of memory element at index + """Returns taint value of memory element at index. :param index: :return: @@ -46,7 +45,7 @@ class TaintRecord: return False def storage_tainted(self, index: int) -> bool: - """ Returns taint value of storage element at index + """Returns taint value of storage element at index. :param index: :return: @@ -56,14 +55,14 @@ class TaintRecord: return False def add_state(self, state: GlobalState) -> None: - """ Adds state with this taint record + """Adds state with this taint record. :param state: """ self.states.append(state) def clone(self) -> "TaintRecord": - """ Clones this record + """Clones this record. :return: """ @@ -75,14 +74,15 @@ class TaintRecord: class TaintResult: - """ Taint analysis result obtained after having ran the taint runner""" + """Taint analysis result obtained after having ran the taint runner.""" def __init__(self): """Create a new tains result.""" self.records = [] def check(self, state: GlobalState, stack_index: int) -> Union[bool, None]: - """Checks if stack variable is tainted, before executing the instruction + """Checks if stack variable is tainted, before executing the + instruction. :param state: state to check variable in :param stack_index: index of stack variable @@ -94,14 +94,14 @@ class TaintResult: return record.stack_tainted(stack_index) def add_records(self, records: List[TaintRecord]) -> None: - """ Adds records to this taint result + """Adds records to this taint result. :param records: """ self.records += records def _try_get_record(self, state: GlobalState) -> Union[TaintRecord, None]: - """ Finds record belonging to the state + """Finds record belonging to the state. :param state: :return: @@ -113,16 +113,15 @@ class TaintResult: class TaintRunner: - """ - Taint runner, is able to run taint analysis on symbolic execution result - """ + """Taint runner, is able to run taint analysis on symbolic execution + result.""" @staticmethod def execute( statespace: SymExecWrapper, node: Node, state: GlobalState, initial_stack=None ) -> TaintResult: - """ - Runs taint analysis on the statespace + """Runs taint analysis on the statespace. + :param initial_stack: :param statespace: symbolic statespace to run taint analysis on :param node: taint introduction node @@ -196,8 +195,8 @@ class TaintRunner: def execute_node( node: Node, last_record: TaintRecord, state_index=0 ) -> List[TaintRecord]: - """ - Runs taint analysis on a given node + """Runs taint analysis on a given node. + :param node: node to analyse :param last_record: last taint record to work from :param state_index: state index to start from diff --git a/mythril/laser/ethereum/transaction/concolic.py b/mythril/laser/ethereum/transaction/concolic.py index 91b07edc..173f59df 100644 --- a/mythril/laser/ethereum/transaction/concolic.py +++ b/mythril/laser/ethereum/transaction/concolic.py @@ -1,4 +1,5 @@ -"""This module contains functions to set up and execute concolic message calls.""" +"""This module contains functions to set up and execute concolic message +calls.""" from typing import List, Union from mythril.disassembler.disassembly import Disassembly @@ -23,7 +24,7 @@ def execute_message_call( value, track_gas=False, ) -> Union[None, List[GlobalState]]: - """ Execute a message call transaction from all open states. + """Execute a message call transaction from all open states. :param laser_evm: :param callee_address: @@ -63,7 +64,7 @@ def execute_message_call( def _setup_global_state_for_execution(laser_evm, transaction) -> None: - """ Set up global state and cfg for a transactions execution. + """Set up global state and cfg for a transactions execution. :param laser_evm: :param transaction: diff --git a/mythril/laser/ethereum/transaction/symbolic.py b/mythril/laser/ethereum/transaction/symbolic.py index 7c59976d..07a19b09 100644 --- a/mythril/laser/ethereum/transaction/symbolic.py +++ b/mythril/laser/ethereum/transaction/symbolic.py @@ -1,4 +1,5 @@ -"""This module contains functions setting up and executing transactions with symbolic values.""" +"""This module contains functions setting up and executing transactions with +symbolic values.""" import logging @@ -24,7 +25,7 @@ ATTACKER_ADDRESS = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF def execute_message_call(laser_evm, callee_address: str) -> None: - """ Executes a message call transaction from all open states + """Executes a message call transaction from all open states. :param laser_evm: :param callee_address: @@ -65,7 +66,7 @@ def execute_message_call(laser_evm, callee_address: str) -> None: def execute_contract_creation( laser_evm, contract_initialization_code, contract_name=None ) -> Account: - """ Executes a contract creation transaction from all open states + """Executes a contract creation transaction from all open states. :param laser_evm: :param contract_initialization_code: @@ -110,7 +111,7 @@ def execute_contract_creation( def _setup_global_state_for_execution(laser_evm, transaction) -> None: - """ Sets up global state and cfg for a transactions execution + """Sets up global state and cfg for a transactions execution. :param laser_evm: :param transaction: diff --git a/mythril/laser/ethereum/transaction/transaction_models.py b/mythril/laser/ethereum/transaction/transaction_models.py index 86762616..9ae72f97 100644 --- a/mythril/laser/ethereum/transaction/transaction_models.py +++ b/mythril/laser/ethereum/transaction/transaction_models.py @@ -1,4 +1,5 @@ -"""This module contians the transaction models used throughout LASER's symbolic execution.""" +"""This module contians the transaction models used throughout LASER's symbolic +execution.""" from typing import Union from mythril.disassembler.disassembly import Disassembly @@ -30,7 +31,7 @@ def get_next_transaction_id() -> int: class TransactionEndSignal(Exception): - """ Exception raised when a transaction is finalized""" + """Exception raised when a transaction is finalized.""" def __init__(self, global_state: GlobalState, revert=False): self.global_state = global_state @@ -38,7 +39,7 @@ class TransactionEndSignal(Exception): class TransactionStartSignal(Exception): - """ Exception raised when a new transaction is started""" + """Exception raised when a new transaction is started.""" def __init__( self, @@ -119,13 +120,13 @@ class BaseTransaction: class MessageCallTransaction(BaseTransaction): - """ Transaction object models an transaction""" + """Transaction object models an transaction.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def initial_global_state(self) -> GlobalState: - """Initialize the execution environment""" + """Initialize the execution environment.""" environment = Environment( self.callee_account, self.caller, @@ -152,7 +153,7 @@ class MessageCallTransaction(BaseTransaction): class ContractCreationTransaction(BaseTransaction): - """ Transaction object models an transaction""" + """Transaction object models an transaction.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs, init_call_data=False) @@ -162,7 +163,7 @@ class ContractCreationTransaction(BaseTransaction): ) def initial_global_state(self) -> GlobalState: - """Initialize the execution environment""" + """Initialize the execution environment.""" environment = Environment( self.callee_account, self.caller, diff --git a/mythril/laser/ethereum/util.py b/mythril/laser/ethereum/util.py index fa2a890d..3830b219 100644 --- a/mythril/laser/ethereum/util.py +++ b/mythril/laser/ethereum/util.py @@ -1,4 +1,5 @@ -"""This module contains various utility conversion functions and constants for LASER.""" +"""This module contains various utility conversion functions and constants for +LASER.""" import re from mythril.laser.smt import is_false, is_true, simplify, If, BitVec, Bool, Expression diff --git a/mythril/laser/smt/__init__.py b/mythril/laser/smt/__init__.py index bda97684..8c669001 100644 --- a/mythril/laser/smt/__init__.py +++ b/mythril/laser/smt/__init__.py @@ -23,14 +23,13 @@ import z3 class SymbolFactory: - """ - A symbol factory provides a default interface for all the components of mythril to create symbols - """ + """A symbol factory provides a default interface for all the components of + mythril to create symbols.""" @staticmethod def BitVecVal(value: int, size: int, annotations=None): - """ - Creates a new bit vector with a concrete value + """Creates a new bit vector with a concrete value. + :param value: The concrete value to set the bit vector to :param size: The size of the bit vector :param annotations: The annotations to initialize the bit vector with @@ -40,8 +39,8 @@ class SymbolFactory: @staticmethod def BitVecSym(name: str, size: int, annotations=None): - """ - Creates a new bit vector with a symbolic value + """Creates a new bit vector with a symbolic value. + :param name: The name of the symbolic bit vector :param size: The size of the bit vector :param annotations: The annotations to initialize the bit vector with @@ -51,38 +50,34 @@ class SymbolFactory: class _SmtSymbolFactory(SymbolFactory): - """ - An implementation of a SymbolFactory that creates symbols using - the classes in: mythril.laser.smt - """ + """An implementation of a SymbolFactory that creates symbols using the + classes in: mythril.laser.smt.""" @staticmethod def BitVecVal(value: int, size: int, annotations=None): - """ Creates a new bit vector with a concrete value """ + """Creates a new bit vector with a concrete value.""" raw = z3.BitVecVal(value, size) return BitVec(raw, annotations) @staticmethod def BitVecSym(name: str, size: int, annotations=None): - """ Creates a new bit vector with a symbolic value """ + """Creates a new bit vector with a symbolic value.""" raw = z3.BitVec(name, size) return BitVec(raw, annotations) class _Z3SymbolFactory(SymbolFactory): - """ - An implementation of a SymbolFactory that directly returns - z3 symbols - """ + """An implementation of a SymbolFactory that directly returns z3 + symbols.""" @staticmethod def BitVecVal(value: int, size: int, annotations=None): - """ Creates a new bit vector with a concrete value """ + """Creates a new bit vector with a concrete value.""" return z3.BitVecVal(value, size) @staticmethod def BitVecSym(name: str, size: int, annotations=None): - """ Creates a new bit vector with a symbolic value """ + """Creates a new bit vector with a symbolic value.""" return z3.BitVec(name, size) diff --git a/mythril/laser/smt/array.py b/mythril/laser/smt/array.py index 3f1f6720..1396f5fa 100644 --- a/mythril/laser/smt/array.py +++ b/mythril/laser/smt/array.py @@ -1,7 +1,8 @@ """This module contains an SMT abstraction of arrays. -This includes an Array class to implement basic store and set operations, as well as -as a K-array, which can be initialized with default values over a certain range. +This includes an Array class to implement basic store and set +operations, as well as as a K-array, which can be initialized with +default values over a certain range. """ from mythril.laser.smt.bitvec import BitVec @@ -12,7 +13,7 @@ class BaseArray: """Base array type, which implements basic store and set operations.""" def __getitem__(self, item: BitVec): - """ Gets item from the array, item can be symbolic""" + """Gets item from the array, item can be symbolic.""" if isinstance(item, slice): raise ValueError( "Instance of BaseArray, does not support getitem with slices" @@ -20,7 +21,7 @@ class BaseArray: return BitVec(z3.Select(self.raw, item.raw)) def __setitem__(self, key: BitVec, value: BitVec): - """ Sets an item in the array, key can be symbolic""" + """Sets an item in the array, key can be symbolic.""" self.raw = z3.Store(self.raw, key.raw, value.raw) @@ -28,8 +29,8 @@ class Array(BaseArray): """A basic symbolic array.""" def __init__(self, name: str, domain: int, value_range: int): - """ - Initializes a symbolic array + """Initializes a symbolic array. + :param name: Name of the array :param domain: The domain for the array (10 -> all the values that a bv of size 10 could take) :param value_range: The range for the values in the array (10 -> all the values that a bv of size 10 could take) @@ -40,11 +41,12 @@ class Array(BaseArray): class K(BaseArray): - """A basic symbolic array, which can be initialized with a default value.""" + """A basic symbolic array, which can be initialized with a default + value.""" def __init__(self, domain: int, value_range: int, value: int): - """ - Initializes an array with a default value + """Initializes an array with a default value. + :param domain: The domain for the array (10 -> all the values that a bv of size 10 could take) :param value_range: The range for the values in the array (10 -> all the values that a bv of size 10 could take) :param value: The default value to use for this array diff --git a/mythril/laser/smt/bitvec.py b/mythril/laser/smt/bitvec.py index 2720af89..bce44c88 100644 --- a/mythril/laser/smt/bitvec.py +++ b/mythril/laser/smt/bitvec.py @@ -304,7 +304,8 @@ def BVAddNoOverflow(a: Union[BitVec, int], b: Union[BitVec, int], signed: bool) def BVMulNoOverflow(a: Union[BitVec, int], b: Union[BitVec, int], signed: bool) -> Bool: - """Creates predicate that verifies that the multiplication doesn't overflow. + """Creates predicate that verifies that the multiplication doesn't + overflow. :param a: :param b: diff --git a/mythril/laser/smt/bool.py b/mythril/laser/smt/bool.py index 376be512..aadacda2 100644 --- a/mythril/laser/smt/bool.py +++ b/mythril/laser/smt/bool.py @@ -1,4 +1,5 @@ -"""This module provides classes for an SMT abstraction of boolean expressions.""" +"""This module provides classes for an SMT abstraction of boolean +expressions.""" import z3 from typing import Union diff --git a/mythril/laser/smt/expression.py b/mythril/laser/smt/expression.py index 30cbe602..fa8ca579 100644 --- a/mythril/laser/smt/expression.py +++ b/mythril/laser/smt/expression.py @@ -4,7 +4,8 @@ import z3 class Expression: - """This is the base symbol class and maintains functionality for simplification and annotations.""" + """This is the base symbol class and maintains functionality for + simplification and annotations.""" def __init__(self, raw, annotations=None): """ @@ -17,16 +18,16 @@ class Expression: @property def annotations(self): - """Gets the annotations for this expression - - :return: + """Gets the annotations for this expression. + + :return: """ return self._annotations def annotate(self, annotation): - """Annotates this expression with the given annotation - - :param annotation: + """Annotates this expression with the given annotation. + + :param annotation: """ if isinstance(annotation, list): self._annotations += annotation @@ -43,9 +44,9 @@ class Expression: def simplify(expression: Expression): """Simplify the expression . - - :param expression: - :return: + + :param expression: + :return: """ expression.simplify() return expression diff --git a/mythril/laser/smt/solver.py b/mythril/laser/smt/solver.py index 1806eae6..8a1d495f 100644 --- a/mythril/laser/smt/solver.py +++ b/mythril/laser/smt/solver.py @@ -8,20 +8,19 @@ class Solver: """An SMT solver object.""" def __init__(self): - """ - - """ + """""" self.raw = z3.Solver() def set_timeout(self, timeout: int) -> None: - """ Sets the timeout that will be used by this solver, timeout is in milliseconds + """Sets the timeout that will be used by this solver, timeout is in + milliseconds. :param timeout: """ self.raw.set(timeout=timeout) def add(self, constraints: list) -> None: - """ Adds the constraints to this solver + """Adds the constraints to this solver. :param constraints: :return: @@ -33,7 +32,7 @@ class Solver: self.raw.add(constraints) def append(self, constraints: list) -> None: - """ Adds the constraints to this solver + """Adds the constraints to this solver. :param constraints: :return: @@ -45,14 +44,15 @@ class Solver: self.raw.add(constraints) def check(self): - """ Returns z3 smt check result + """Returns z3 smt check result. :return: """ return self.raw.check() def model(self): - """ Returns z3 model for a solution + """Returns z3 model for a solution. + :return: """ return self.raw.model() @@ -62,7 +62,7 @@ class Solver: self.raw.reset() def pop(self, num) -> None: - """ Pop num constraints from this solver + """Pop num constraints from this solver. :param num: """ @@ -70,9 +70,7 @@ class Solver: class Optimize(Solver): - """ - An optimizing smt solver - """ + """An optimizing smt solver.""" def __init__(self): """Create a new optimizing solver instance.""" @@ -80,14 +78,14 @@ class Optimize(Solver): self.raw = z3.Optimize() def minimize(self, element: Expression): - """ In solving this solver will try to minimize the passed expression + """In solving this solver will try to minimize the passed expression. :param element: """ self.raw.minimize(element.raw) def maximize(self, element: Expression): - """ In solving this solver will try to maximize the passed expression + """In solving this solver will try to maximize the passed expression. :param element: """ diff --git a/mythril/mythril.py b/mythril/mythril.py index a97f8571..d962f7e3 100644 --- a/mythril/mythril.py +++ b/mythril/mythril.py @@ -77,7 +77,6 @@ class Mythril(object): mythril.dump_statespaces(args) mythril.disassemble(contract) mythril.get_state_variable_from_storage(args) - """ def __init__( @@ -133,8 +132,8 @@ class Mythril(object): return mythril_dir def _init_config(self): - """ - If no config file exists, create it and add default options. + """If no config file exists, create it and add default options. + Default LevelDB path is specified based on OS dynamic loading is set to infura by default in the file Returns: leveldb directory diff --git a/mythril/solidity/soliditycontract.py b/mythril/solidity/soliditycontract.py index 931b9403..6ec018f8 100644 --- a/mythril/solidity/soliditycontract.py +++ b/mythril/solidity/soliditycontract.py @@ -1,4 +1,5 @@ -"""This module contains representation classes for Solidity files, contracts and source mappings.""" +"""This module contains representation classes for Solidity files, contracts +and source mappings.""" import mythril.laser.ethereum.util as helper from mythril.ethereum.evmcontract import EVMContract from mythril.ethereum.util import get_solc_json diff --git a/mythril/support/loader.py b/mythril/support/loader.py index 47bbc37a..f77649c2 100644 --- a/mythril/support/loader.py +++ b/mythril/support/loader.py @@ -1,4 +1,5 @@ -"""This module contains the dynamic loader logic to get on-chain storage data and dependencies.""" +"""This module contains the dynamic loader logic to get on-chain storage data +and dependencies.""" from mythril.disassembler.disassembly import Disassembly import logging import re diff --git a/mythril/support/signatures.py b/mythril/support/signatures.py index 41c20e96..7460e0ca 100644 --- a/mythril/support/signatures.py +++ b/mythril/support/signatures.py @@ -75,8 +75,9 @@ except ImportError: class SQLiteDB(object): - """ - Simple context manager for sqlite3 databases. Commits everything at exit. + """Simple context manager for sqlite3 databases. + + Commits everything at exit. """ def __init__(self, path): @@ -112,9 +113,7 @@ class SQLiteDB(object): class SignatureDB(object, metaclass=Singleton): - """ - - """ + """""" def __init__(self, enable_online_lookup: bool = False, path: str = None) -> None: """ @@ -146,8 +145,8 @@ class SignatureDB(object, metaclass=Singleton): ) def __getitem__(self, item: str) -> List[str]: - """ - Provide dict interface db[sighash] + """Provide dict interface db[sighash] + :param item: 4-byte signature string :return: list of matching text signature strings """ @@ -155,8 +154,8 @@ class SignatureDB(object, metaclass=Singleton): @staticmethod def _normalize_byte_sig(byte_sig: str) -> str: - """ - Adds a leading 0x to the byte signature if it's not already there. + """Adds a leading 0x to the byte signature if it's not already there. + :param byte_sig: 4-byte signature string :return: normalized byte signature string """ @@ -184,10 +183,9 @@ class SignatureDB(object, metaclass=Singleton): ) def get(self, byte_sig: str, online_timeout: int = 2) -> List[str]: - """ - Get a function text signature for a byte signature - 1) try local cache - 2) try online lookup (if enabled; if not flagged as unavailable) + """Get a function text signature for a byte signature 1) try local + cache 2) try online lookup (if enabled; if not flagged as unavailable) + :param byte_sig: function signature hash as hexstr :param online_timeout: online lookup timeout :return: list of matching function text signatures @@ -235,8 +233,8 @@ class SignatureDB(object, metaclass=Singleton): def import_solidity_file( self, file_path: str, solc_binary: str = "solc", solc_args: str = None ): - """ - Import Function Signatures from solidity source files + """Import Function Signatures from solidity source files. + :param solc_binary: :param solc_args: :param file_path: solidity source code file path @@ -283,8 +281,7 @@ class SignatureDB(object, metaclass=Singleton): @staticmethod def lookup_online(byte_sig: str, timeout: int, proxies=None) -> List[str]: - """ - Lookup function signatures from 4byte.directory. + """Lookup function signatures from 4byte.directory. :param byte_sig: function signature hash as hexstr :param timeout: optional timeout for online lookup diff --git a/mythril/support/truffle.py b/mythril/support/truffle.py index 29bc678c..1841c340 100644 --- a/mythril/support/truffle.py +++ b/mythril/support/truffle.py @@ -1,4 +1,5 @@ -"""This module contains functionality used to easily analyse Truffle projects.""" +"""This module contains functionality used to easily analyse Truffle +projects.""" import os from pathlib import PurePath import re diff --git a/mythril/version.py b/mythril/version.py index 8b78ac30..ce650a08 100644 --- a/mythril/version.py +++ b/mythril/version.py @@ -1,6 +1,7 @@ """This file contains the current Mythril version. -This file is suitable for sourcing inside POSIX shell, e.g. bash as well as for importing into Python. +This file is suitable for sourcing inside POSIX shell, e.g. bash as well +as for importing into Python. """ VERSION = "v0.19.11" # NOQA diff --git a/setup.py b/setup.py index 7d970f74..98a4935b 100755 --- a/setup.py +++ b/setup.py @@ -1,13 +1,11 @@ # -*- coding: utf-8 -*- -""" -install mythril and deploy source-dist and wheel to pypi.python.org +"""install mythril and deploy source-dist and wheel to pypi.python.org. deps (requires up2date version): *) pip install --upgrade pip wheel setuptools twine publish to pypi w/o having to convert Readme.md to RST: 1) #> python setup.py sdist bdist_wheel 2) #> twine upload dist/* #; #optional --repository or --repository-url - """ from setuptools import setup, find_packages from setuptools.command.install import install @@ -27,14 +25,12 @@ exec(open(str(version_path), "r").read()) class VerifyVersionCommand(install): - """Custom command to verify that the git tag matches our version""" + """Custom command to verify that the git tag matches our version.""" description = "verify that the git tag matches our version" def run(self): - """ - - """ + """""" tag = os.getenv("CIRCLE_TAG") if tag != VERSION: @@ -45,8 +41,8 @@ class VerifyVersionCommand(install): def read_file(fname): - """ - return file contents + """return file contents. + :param fname: path relative to setup.py :return: file contents """ diff --git a/tests/__init__.py b/tests/__init__.py index 361d7ac8..493c755f 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -17,9 +17,7 @@ MYTHRIL_DIR = TESTS_DIR / "mythril_dir" class BaseTestCase(TestCase): def setUp(self): - """ - - """ + """""" self.changed_files = [] def compare_files_error_message(self): @@ -46,9 +44,7 @@ class BaseTestCase(TestCase): self.changed_files.append((input_file, output_expected, output_current)) def assert_and_show_changed_files(self): - """ - - """ + """""" self.assertEqual( 0, len(self.changed_files), msg=self.compare_files_error_message() ) diff --git a/tests/evmcontract_test.py b/tests/evmcontract_test.py index bfc70637..d0936426 100644 --- a/tests/evmcontract_test.py +++ b/tests/evmcontract_test.py @@ -4,9 +4,7 @@ from tests import BaseTestCase class EVMContractTestCase(BaseTestCase): def setUp(self): - """ - - """ + """""" super().setUp() self.code = "0x60606040525b603c5b60006010603e565b9050593681016040523660008237602060003683856040603f5a0204f41560545760206000f35bfe5b50565b005b73c3b2ae46792547a96b9f84405e36d0e07edcd05c5b905600a165627a7a7230582062a884f947232ada573f95940cce9c8bfb7e4e14e21df5af4e884941afb55e590029" self.creation_code = "0x60606040525b603c5b60006010603e565b9050593681016040523660008237602060003683856040603f5a0204f41560545760206000f35bfe5b50565b005b73c3b2ae46792547a96b9f84405e36d0e07edcd05c5b905600a165627a7a7230582062a884f947232ada573f95940cce9c8bfb7e4e14e21df5af4e884941afb55e590029" @@ -14,9 +12,7 @@ class EVMContractTestCase(BaseTestCase): class Getinstruction_listTestCase(EVMContractTestCase): def runTest(self): - """ - - """ + """""" contract = EVMContract(self.code, self.creation_code) disassembly = contract.disassembly @@ -30,9 +26,7 @@ class Getinstruction_listTestCase(EVMContractTestCase): class GetEASMTestCase(EVMContractTestCase): def runTest(self): - """ - - """ + """""" contract = EVMContract(self.code) instruction_list = contract.get_easm() @@ -45,9 +39,7 @@ class GetEASMTestCase(EVMContractTestCase): class MatchesExpressionTestCase(EVMContractTestCase): def runTest(self): - """ - - """ + """""" contract = EVMContract(self.code) self.assertTrue( diff --git a/tests/native_test.py b/tests/native_test.py index bf7e3b8a..1f25741f 100644 --- a/tests/native_test.py +++ b/tests/native_test.py @@ -87,9 +87,7 @@ def _test_natives(laser_info, test_list, test_name): class NativeTests(BaseTestCase): @staticmethod def runTest(): - """ - - """ + """""" disassembly = SolidityContract( "./tests/native_tests.sol", solc_binary=Mythril._init_solc_binary("0.5.0") ).disassembly diff --git a/tests/report_test.py b/tests/report_test.py index 842c38d4..f5414534 100644 --- a/tests/report_test.py +++ b/tests/report_test.py @@ -41,7 +41,7 @@ def _generate_report(input_file): @pytest.fixture(scope="module") def reports(): - """ Fixture that analyses all reports""" + """Fixture that analyses all reports.""" reset_callback_modules() pool = Pool(cpu_count()) input_files = sorted( @@ -53,7 +53,8 @@ def reports(): def _assert_empty(changed_files, postfix): - """ Asserts there are no changed files and otherwise builds error message""" + """Asserts there are no changed files and otherwise builds error + message.""" message = "" for input_file in changed_files: output_expected = ( @@ -76,7 +77,8 @@ def _assert_empty(changed_files, postfix): def _assert_empty_json(changed_files): - """ Asserts there are no changed files and otherwise builds error message""" + """Asserts there are no changed files and otherwise builds error + message.""" postfix = ".json" expected = [] actual = [] @@ -111,8 +113,8 @@ def _assert_empty_json(changed_files): def _get_changed_files(postfix, report_builder, reports): - """ - Returns a generator for all unexpected changes in generated reports + """Returns a generator for all unexpected changes in generated reports. + :param postfix: The applicable postfix :param report_builder: serialization function :param reports: The reports to serialize diff --git a/tests/rpc_test.py b/tests/rpc_test.py index efb2ca4b..45fd762a 100644 --- a/tests/rpc_test.py +++ b/tests/rpc_test.py @@ -8,15 +8,11 @@ class RpcTest(BaseTestCase): client = None def setUp(self): - """ - - """ + """""" self.client = EthJsonRpc() def tearDown(self): - """ - - """ + """""" self.client.close() def test_eth_coinbase(self):