diff --git a/README.md b/README.md index 41566bac..c5fbd20f 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,16 @@ [![Discord](https://img.shields.io/discord/481002907366588416.svg)](https://discord.gg/E3YrVtG) [![PyPI](https://badge.fury.io/py/mythril.svg)](https://pypi.python.org/pypi/mythril) ![Master Build Status](https://img.shields.io/circleci/project/github/ConsenSys/mythril/master.svg) -[![Waffle.io - Columns and their card count](https://badge.waffle.io/ConsenSys/mythril.svg?columns=all)](https://waffle.io/ConsenSys/mythril) +[![Waffle.io - Columns and their card count](https://badge.waffle.io/ConsenSys/mythril.svg?columns=In%20Progress)](https://waffle.io/ConsenSys/mythril) [![Sonarcloud - Maintainability](https://sonarcloud.io/api/project_badges/measure?project=mythril&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=mythril) - +[![PyPI Statistics](https://pypistats.com/badge/mythril.svg)](https://pypistats.com/package/mythril) mythril Mythril OSS is the classic security analysis tool for Ethereum smart contracts. It uses concolic analysis, taint analysis and control flow checking to detect a variety of security vulnerabilities. Whether you want to contribute, need support, or want to learn what we have cooking for the future, our [Discord server](https://discord.gg/E3YrVtG) will serve your needs! -Oh and by the way, we're now building a whole security tools ecosystem with [Mythril Platform](https://mythril.ai). You should definitely check that out as well. +Oh and by the way, we're building an easy-to-use SaaS solution and tools ecosystem for Ethereum developers called [Mythril Platform](https://mythril.ai). You should definitely check that out as well. ## Installation and setup diff --git a/mythril/analysis/symbolic.py b/mythril/analysis/symbolic.py index bc2373a7..75c5f122 100644 --- a/mythril/analysis/symbolic.py +++ b/mythril/analysis/symbolic.py @@ -9,9 +9,9 @@ from mythril.laser.ethereum.strategy.basic import DepthFirstSearchStrategy, Brea class SymExecWrapper: - ''' + """ Wrapper class for the LASER Symbolic virtual machine. Symbolically executes the code and does a bit of pre-analysis for convenience. - ''' + """ def __init__(self, contract, address, strategy, dynloader=None, max_depth=22, execution_timeout=None, create_timeout=None): @@ -66,7 +66,7 @@ class SymExecWrapper: # ignore prebuilts continue - if (meminstart.type == VarType.CONCRETE and meminsz.type == VarType.CONCRETE): + if meminstart.type == VarType.CONCRETE and meminsz.type == VarType.CONCRETE: self.calls.append(Call(self.nodes[key], state, state_index, op, to, gas, value, state.mstate.memory[meminstart.val:meminsz.val * 4])) else: self.calls.append(Call(self.nodes[key], state, state_index, op, to, gas, value)) @@ -104,7 +104,7 @@ class SymExecWrapper: taint = True for constraint in s.node.constraints: - if ("caller" in str(constraint)): + if "caller" in str(constraint): taint = False break diff --git a/mythril/ether/asm.py b/mythril/ether/asm.py index 5cc2b4b5..5e2267ea 100644 --- a/mythril/ether/asm.py +++ b/mythril/ether/asm.py @@ -80,7 +80,7 @@ def find_opcode_sequence(pattern, instruction_list): matched = False break - if (matched): + if matched: match_indexes.append(i) return match_indexes @@ -102,7 +102,7 @@ def disassemble(bytecode): instruction = {'address': addr} try: - if (sys.version_info > (3, 0)): + if sys.version_info > (3, 0): opcode = opcodes[bytecode[addr]] else: opcode = opcodes[ord(bytecode[addr])] diff --git a/mythril/ether/ethcontract.py b/mythril/ether/ethcontract.py index b43b1919..fbd87b69 100644 --- a/mythril/ether/ethcontract.py +++ b/mythril/ether/ethcontract.py @@ -7,15 +7,16 @@ import re class ETHContract(persistent.Persistent): def __init__(self, code, creation_code="", name="Unknown", enable_online_lookup=True): - - self.creation_code = creation_code - self.name = name - + # Workaround: We currently do not support compile-time linking. # Dynamic contract addresses of the format __[contract-name]_____________ are replaced with a generic address + # Apply this for creation_code & code + creation_code = re.sub(r'(_+.*_+)', 'aa' * 20, creation_code) code = re.sub(r'(_+.*_+)', 'aa' * 20, code) + self.creation_code = creation_code + self.name = name self.code = code self.disassembly = Disassembly(code, enable_online_lookup=enable_online_lookup) self.creation_disassembly = Disassembly(creation_code, enable_online_lookup=enable_online_lookup) @@ -49,7 +50,7 @@ class ETHContract(persistent.Persistent): m = re.match(r'^code#([a-zA-Z0-9\s,\[\]]+)#', token) - if (m): + if m: if easm_code is None: easm_code = self.get_easm() @@ -59,7 +60,7 @@ class ETHContract(persistent.Persistent): m = re.match(r'^func#([a-zA-Z0-9\s_,(\\)\[\]]+)#$', token) - if (m): + if m: sign_hash = "0x" + utils.sha3(m.group(1))[:4].hex() diff --git a/mythril/ether/evm.py b/mythril/ether/evm.py index 545e30ff..f1cf2fa5 100644 --- a/mythril/ether/evm.py +++ b/mythril/ether/evm.py @@ -37,7 +37,7 @@ def trace(code, calldata=""): if m: stackitems = re.findall(r'b\'(\d+)\'', m.group(1)) - stack = "["; + stack = "[" if len(stackitems): for i in range(0, len(stackitems) - 1): diff --git a/mythril/ether/util.py b/mythril/ether/util.py index 0e4bae40..6b351665 100644 --- a/mythril/ether/util.py +++ b/mythril/ether/util.py @@ -10,7 +10,7 @@ import json def safe_decode(hex_encoded_string): - if (hex_encoded_string.startswith("0x")): + if hex_encoded_string.startswith("0x"): return bytes.fromhex(hex_encoded_string[2:]) else: return bytes.fromhex(hex_encoded_string) diff --git a/mythril/interfaces/cli.py b/mythril/interfaces/cli.py index 061044fd..124b0977 100644 --- a/mythril/interfaces/cli.py +++ b/mythril/interfaces/cli.py @@ -5,7 +5,7 @@ http://www.github.com/ConsenSys/mythril """ -import logging +import logging, coloredlogs import json import sys import argparse @@ -103,7 +103,10 @@ def main(): if args.v: if 0 <= args.v < 3: - logging.basicConfig(level=[logging.NOTSET, logging.INFO, logging.DEBUG][args.v]) + coloredlogs.install( + fmt='%(name)s[%(process)d] %(levelname)s %(message)s', + level=[logging.NOTSET, logging.INFO, logging.DEBUG][args.v] + ) else: exit_with_error(args.outform, "Invalid -v value, you can find valid values in usage") diff --git a/mythril/laser/ethereum/instructions.py b/mythril/laser/ethereum/instructions.py index a1dbbe60..bf60db4f 100644 --- a/mythril/laser/ethereum/instructions.py +++ b/mythril/laser/ethereum/instructions.py @@ -773,7 +773,8 @@ class Instruction: return self._sload_helper(global_state, str(index)) - def _sload_helper(self, global_state, index, constraints=None): + @staticmethod + def _sload_helper(global_state, index, constraints=None): try: data = global_state.environment.active_account.storage[index] except KeyError: @@ -786,8 +787,8 @@ class Instruction: global_state.mstate.stack.append(data) return [global_state] - - def _get_constraints(self, keccak_keys, this_key, argument): + @staticmethod + def _get_constraints(keccak_keys, this_key, argument): global keccak_function_manager for keccak_key in keccak_keys: if keccak_key == this_key: @@ -837,7 +838,8 @@ class Instruction: return self._sstore_helper(global_state, str(index), value) - def _sstore_helper(self, global_state, index, value, constraint=None): + @staticmethod + def _sstore_helper(global_state, index, value, constraint=None): try: global_state.environment.active_account = deepcopy(global_state.environment.active_account) global_state.accounts[ diff --git a/mythril/laser/ethereum/taint_analysis.py b/mythril/laser/ethereum/taint_analysis.py index 4f605008..2144d864 100644 --- a/mythril/laser/ethereum/taint_analysis.py +++ b/mythril/laser/ethereum/taint_analysis.py @@ -109,7 +109,8 @@ class TaintRunner: records = TaintRunner.execute_node(node, record, index) result.add_records(records) - + if len(records) == 0: # continue if there is no record to work on + continue children = TaintRunner.children(node, statespace, environment, transaction_stack_length) for child in children: current_nodes.append((child, records[-1], 0)) diff --git a/mythril/laser/ethereum/util.py b/mythril/laser/ethereum/util.py index c6c8e5ce..8d680534 100644 --- a/mythril/laser/ethereum/util.py +++ b/mythril/laser/ethereum/util.py @@ -16,7 +16,7 @@ def sha3(seed): def safe_decode(hex_encoded_string): - if (hex_encoded_string.startswith("0x")): + if hex_encoded_string.startswith("0x"): return bytes.fromhex(hex_encoded_string[2:]) else: return bytes.fromhex(hex_encoded_string) @@ -99,7 +99,7 @@ def concrete_int_to_bytes(val): # logging.debug("concrete_int_to_bytes " + str(val)) - if (type(val) == int): + if type(val) == int: return val.to_bytes(32, byteorder='big') return (simplify(val).as_long()).to_bytes(32, byteorder='big') diff --git a/mythril/leveldb/accountindexing.py b/mythril/leveldb/accountindexing.py index f61ebe80..9d94c31e 100644 --- a/mythril/leveldb/accountindexing.py +++ b/mythril/leveldb/accountindexing.py @@ -34,9 +34,9 @@ class CountableList(object): class ReceiptForStorage(rlp.Serializable): - ''' + """ Receipt format stored in levelDB - ''' + """ fields = [ ('state_root', binary), @@ -50,9 +50,9 @@ class ReceiptForStorage(rlp.Serializable): class AccountIndexer(object): - ''' + """ Updates address index - ''' + """ def __init__(self, ethDB): self.db = ethDB @@ -62,19 +62,20 @@ 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 - ''' + """ contract_address = self.db.reader._get_address_by_hash(contract_hash) if contract_address is not None: return contract_address + else: raise AddressNotFoundError def _process(self, startblock): - ''' + """ Processesing method - ''' + """ logging.debug("Processing blocks %d to %d" % (startblock, startblock + BATCH_SIZE)) addresses = [] @@ -94,9 +95,9 @@ class AccountIndexer(object): return addresses def updateIfNeeded(self): - ''' + """ 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 @@ -126,7 +127,7 @@ class AccountIndexer(object): count = 0 processed = 0 - while (blockNum <= self.lastBlock): + while blockNum <= self.lastBlock: # leveldb cannot be accessed on multiple processes (not even readonly) # multithread version performs significantly worse than serial try: diff --git a/mythril/leveldb/client.py b/mythril/leveldb/client.py index 7d0bb0df..43317117 100644 --- a/mythril/leveldb/client.py +++ b/mythril/leveldb/client.py @@ -26,23 +26,23 @@ address_mapping_head_key = b'accountMapping' # head (latest) number of indexed def _format_block_number(number): - ''' + """ formats block number to uint64 big endian - ''' + """ return utils.zpad(utils.int_to_big_endian(number), 8) def _encode_hex(v): - ''' + """ encodes hash as hex - ''' + """ return '0x' + utils.encode_hex(v) class LevelDBReader(object): - ''' + """ level db reading interface, can be used with snapshot - ''' + """ def __init__(self, db): self.db = db @@ -50,34 +50,34 @@ class LevelDBReader(object): self.head_state = None def _get_head_state(self): - ''' + """ gets head state - ''' + """ if not self.head_state: root = self._get_head_block().state_root self.head_state = State(self.db, root) return self.head_state def _get_account(self, address): - ''' + """ gets account by address - ''' + """ state = self._get_head_state() account_address = binascii.a2b_hex(utils.remove_0x_head(address)) return state.get_and_cache_account(account_address) def _get_block_hash(self, number): - ''' + """ gets block hash by block number - ''' + """ num = _format_block_number(number) hash_key = header_prefix + num + num_suffix return self.db.get(hash_key) def _get_head_block(self): - ''' + """ gets head block header - ''' + """ if not self.head_block_header: block_hash = self.db.get(head_header_key) num = self._get_block_number(block_hash) @@ -91,38 +91,29 @@ class LevelDBReader(object): return self.head_block_header def _get_block_number(self, block_hash): - ''' - gets block number by its hash - ''' + """Get block number by its hash""" number_key = block_hash_prefix + block_hash return self.db.get(number_key) def _get_block_header(self, block_hash, num): - ''' - get block header by block header hash & number - ''' + """Get block header by block header hash & number""" header_key = header_prefix + num + block_hash + block_header_data = self.db.get(header_key) header = rlp.decode(block_header_data, sedes=BlockHeader) return header def _get_address_by_hash(self, block_hash): - ''' - get mapped address by its hash - ''' + """Get mapped address by its hash""" address_key = address_prefix + block_hash return self.db.get(address_key) def _get_last_indexed_number(self): - ''' - latest indexed block number - ''' + """Get latest indexed block number""" return self.db.get(address_mapping_head_key) def _get_block_receipts(self, block_hash, num): - ''' - get block transaction receipts by block header hash & number - ''' + """Get block transaction receipts by block header hash & number""" number = _format_block_number(num) receipts_key = block_receipts_prefix + number + block_hash receipts_data = self.db.get(receipts_key) @@ -131,44 +122,44 @@ class LevelDBReader(object): class LevelDBWriter(object): - ''' + """ level db writing interface - ''' + """ def __init__(self, db): self.db = db self.wb = None def _set_last_indexed_number(self, number): - ''' + """ sets latest indexed block number - ''' + """ return self.db.put(address_mapping_head_key, _format_block_number(number)) def _start_writing(self): - ''' + """ start writing a batch - ''' + """ self.wb = self.db.write_batch() def _commit_batch(self): - ''' + """ commit batch - ''' + """ self.wb.write() def _store_account_address(self, address): - ''' + """ get block transaction receipts by block header hash & number - ''' + """ address_key = address_prefix + utils.sha3(address) self.wb.put(address_key, address) class EthLevelDB(object): - ''' + """ Go-Ethereum LevelDB client class - ''' + """ def __init__(self, path): self.path = path @@ -177,9 +168,9 @@ class EthLevelDB(object): self.writer = LevelDBWriter(self.db) def get_contracts(self): - ''' + """ iterate through all contracts - ''' + """ for account in self.reader._get_head_state().get_all_accounts(): if account.code is not None: code = _encode_hex(account.code) @@ -188,9 +179,9 @@ class EthLevelDB(object): yield contract, account.address, account.balance def search(self, expression, callback_func): - ''' + """ searches through all contract accounts - ''' + """ cnt = 0 indexer = AccountIndexer(self) @@ -217,9 +208,7 @@ class EthLevelDB(object): logging.info("Searched %d contracts" % cnt) def contract_hash_to_address(self, contract_hash): - ''' - tries to find corresponding account address - ''' + """Tries to find corresponding account address""" address_hash = binascii.a2b_hex(utils.remove_0x_head(contract_hash)) indexer = AccountIndexer(self) @@ -227,17 +216,17 @@ class EthLevelDB(object): return _encode_hex(indexer.get_contract_by_hash(address_hash)) def eth_getBlockHeaderByNumber(self, number): - ''' + """ gets block header by block number - ''' + """ block_hash = self.reader._get_block_hash(number) block_number = _format_block_number(number) return self.reader._get_block_header(block_hash, block_number) def eth_getBlockByNumber(self, number): - ''' + """ gets block body by block number - ''' + """ block_hash = self.reader._get_block_hash(number) block_number = _format_block_number(number) body_key = body_prefix + block_number + block_hash @@ -246,22 +235,22 @@ class EthLevelDB(object): return body def eth_getCode(self, address): - ''' + """ gets account code - ''' + """ account = self.reader._get_account(address) return _encode_hex(account.code) def eth_getBalance(self, address): - ''' + """ gets account balance - ''' + """ account = self.reader._get_account(address) return account.balance def eth_getStorageAt(self, address, position): - ''' + """ gets account storage data at position - ''' + """ account = self.reader._get_account(address) return _encode_hex(utils.zpad(utils.encode_int(account.get_storage_data(position)), 32)) diff --git a/mythril/leveldb/eth_db.py b/mythril/leveldb/eth_db.py index a46d9e93..ab9107fa 100644 --- a/mythril/leveldb/eth_db.py +++ b/mythril/leveldb/eth_db.py @@ -3,27 +3,27 @@ from ethereum.db import BaseDB class ETH_DB(BaseDB): - ''' + """ adopts pythereum BaseDB using plyvel - ''' + """ def __init__(self, path): self.db = plyvel.DB(path) def get(self, key): - ''' + """ gets value for key - ''' + """ return self.db.get(key) def put(self, key, value): - ''' + """ puts value for key - ''' + """ self.db.put(key, value) def write_batch(self): - ''' + """ start writing a batch - ''' - return self.db.write_batch() \ No newline at end of file + """ + return self.db.write_batch() diff --git a/mythril/leveldb/state.py b/mythril/leveldb/state.py index c6a24119..83507b69 100644 --- a/mythril/leveldb/state.py +++ b/mythril/leveldb/state.py @@ -32,9 +32,9 @@ STATE_DEFAULTS = { class Account(rlp.Serializable): - ''' + """ adjusted account from ethereum.state - ''' + """ fields = [ ('nonce', big_endian_int), @@ -57,15 +57,15 @@ class Account(rlp.Serializable): @property def code(self): - ''' + """ code rlp data - ''' + """ return self.db.get(self.code_hash) def get_storage_data(self, key): - ''' + """ get storage data - ''' + """ if key not in self.storage_cache: v = self.storage_trie.get(utils.encode_int32(key)) self.storage_cache[key] = utils.big_endian_to_int( @@ -74,24 +74,24 @@ class Account(rlp.Serializable): @classmethod def blank_account(cls, db, addr, initial_nonce=0): - ''' + """ creates a blank account - ''' + """ db.put(BLANK_HASH, b'') o = cls(initial_nonce, 0, trie.BLANK_ROOT, BLANK_HASH, db, addr) o.existent_at_start = False return o def is_blank(self): - ''' + """ checks if is a blank account - ''' + """ return self.nonce == 0 and self.balance == 0 and self.code_hash == BLANK_HASH -class State(): - ''' +class State: + """ adjusted state from ethereum.state - ''' + """ def __init__(self, db, root): self.db = db @@ -101,14 +101,14 @@ 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""" + if addr in self.cache: return self.cache[addr] rlpdata = self.secure_trie.get(addr) if rlpdata == trie.BLANK_NODE and len(addr) == 32: # support for hashed addresses rlpdata = self.trie.get(addr) + if rlpdata != trie.BLANK_NODE: o = rlp.decode(rlpdata, Account, db=self.db, address=addr) else: @@ -120,9 +120,9 @@ class State(): return o def get_all_accounts(self): - ''' + """ 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/mythril.py b/mythril/mythril.py index 221d136d..d96b9b27 100644 --- a/mythril/mythril.py +++ b/mythril/mythril.py @@ -103,7 +103,8 @@ class Mythril(object): self.contracts = [] # loaded contracts - def _init_mythril_dir(self): + @staticmethod + def _init_mythril_dir(): try: mythril_dir = os.environ['MYTHRIL_DIR'] except KeyError: @@ -179,7 +180,8 @@ class Mythril(object): def analyze_truffle_project(self, *args, **kwargs): return analyze_truffle_project(self.sigs, *args, **kwargs) # just passthru by passing signatures for now - def _init_solc_binary(self, version): + @staticmethod + def _init_solc_binary(version): # Figure out solc binary and version # Only proper versions are supported. No nightlies, commits etc (such as available in remix) @@ -434,7 +436,8 @@ class Mythril(object): raise CriticalError("Could not connect to RPC server. Make sure that your node is running and that RPC parameters are set correctly.") return '\n'.join(outtxt) - def disassemble(self, contract): + @staticmethod + def disassemble(contract): return contract.get_easm() @staticmethod diff --git a/mythril/rpc/base_client.py b/mythril/rpc/base_client.py index bc8b1994..9234ecf9 100644 --- a/mythril/rpc/base_client.py +++ b/mythril/rpc/base_client.py @@ -20,64 +20,64 @@ class BaseClient(object): pass def eth_coinbase(self): - ''' + """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_coinbase TESTED - ''' + """ return self._call('eth_coinbase') def eth_blockNumber(self): - ''' + """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_blocknumber TESTED - ''' + """ return hex_to_dec(self._call('eth_blockNumber')) def eth_getBalance(self, address=None, block=BLOCK_TAG_LATEST): - ''' + """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getbalance TESTED - ''' + """ address = address or self.eth_coinbase() block = validate_block(block) return hex_to_dec(self._call('eth_getBalance', [address, block])) def eth_getStorageAt(self, address=None, position=0, block=BLOCK_TAG_LATEST): - ''' + """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat TESTED - ''' + """ block = validate_block(block) return self._call('eth_getStorageAt', [address, hex(position), block]) def eth_getCode(self, address, default_block=BLOCK_TAG_LATEST): - ''' + """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcode NEEDS TESTING - ''' + """ if isinstance(default_block, str): if default_block not in BLOCK_TAGS: raise ValueError return self._call('eth_getCode', [address, default_block]) def eth_getBlockByNumber(self, block=BLOCK_TAG_LATEST, tx_objects=True): - ''' + """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbynumber TESTED - ''' + """ block = validate_block(block) return self._call('eth_getBlockByNumber', [block, tx_objects]) def eth_getTransactionReceipt(self, tx_hash): - ''' + """ https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt TESTED - ''' + """ return self._call('eth_getTransactionReceipt', [tx_hash]) diff --git a/mythril/rpc/client.py b/mythril/rpc/client.py index 6a7f0b96..1545092f 100644 --- a/mythril/rpc/client.py +++ b/mythril/rpc/client.py @@ -17,9 +17,9 @@ JSON_MEDIA_TYPE = 'application/json' This code is adapted from: https://github.com/ConsenSys/ethjsonrpc ''' class EthJsonRpc(BaseClient): - ''' + """ Ethereum JSON-RPC client class - ''' + """ def __init__(self, host='localhost', port=GETH_DEFAULT_RPC_PORT, tls=False): self.host = host diff --git a/mythril/rpc/utils.py b/mythril/rpc/utils.py index e87b7dc6..5f98fcea 100644 --- a/mythril/rpc/utils.py +++ b/mythril/rpc/utils.py @@ -2,17 +2,17 @@ from .constants import BLOCK_TAGS def hex_to_dec(x): - ''' + """ Convert hex to decimal - ''' + """ return int(x, 16) def clean_hex(d): - ''' + """ Convert decimal to hex and remove the "L" suffix that is appended to large numbers - ''' + """ return hex(d).rstrip('L') def validate_block(block): @@ -25,14 +25,14 @@ def validate_block(block): def wei_to_ether(wei): - ''' + """ Convert wei to ether - ''' + """ return 1.0 * wei / 10**18 def ether_to_wei(ether): - ''' + """ Convert ether to wei - ''' + """ return ether * 10**18 diff --git a/mythril/support/loader.py b/mythril/support/loader.py index 7c0855ec..d219d17c 100644 --- a/mythril/support/loader.py +++ b/mythril/support/loader.py @@ -37,7 +37,7 @@ class DynLoader: m = re.match(r'^(0x[0-9a-fA-F]{40})$', dependency_address) - if (m): + if m: dependency_address = m.group(1) else: @@ -47,7 +47,7 @@ class DynLoader: code = self.eth.eth_getCode(dependency_address) - if (code == "0x"): + if code == "0x": return None else: return Disassembly(code) diff --git a/requirements.txt b/requirements.txt index 53a4a086..30162f8d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +coloredlogs>=10.0 configparser>=3.5.0 coverage eth_abi>=1.0.0 diff --git a/setup.py b/setup.py index cfb6cb7b..2c92ce4a 100755 --- a/setup.py +++ b/setup.py @@ -82,6 +82,7 @@ setup( packages=find_packages(exclude=['contrib', 'docs', 'tests']), install_requires=[ + 'coloredlogs>=10.0', 'ethereum>=2.3.2', 'z3-solver>=4.5', 'requests', diff --git a/tests/native_test.py b/tests/native_test.py index a0942d42..bcb0eab9 100644 --- a/tests/native_test.py +++ b/tests/native_test.py @@ -6,13 +6,13 @@ from mythril.laser.ethereum import svm from tests import * -SHA256_TEST = [ (0,False) for i in range(6)] +SHA256_TEST = [(0, False) for _ in range(6)] -RIPEMD160_TEST = [ (0,False) for i in range(6)] +RIPEMD160_TEST = [(0, False) for _ in range(6)] -ECRECOVER_TEST = [ (0,False) for i in range(9)] +ECRECOVER_TEST = [(0, False) for _ in range(9)] -IDENTITY_TEST = [ (0, False) for i in range(4)] +IDENTITY_TEST = [(0, False) for _ in range(4)] SHA256_TEST[0] = (5555555555555555, True) #These are Random numbers to check whether the 'if condition' is entered or not(True means entered) SHA256_TEST[1] = (323232325445454546, True) @@ -98,9 +98,9 @@ def _test_natives(laser_info, test_list, test_name): assert(success == len(test_list)) - class NativeTests(BaseTestCase): - def runTest(self): + @staticmethod + def runTest(): disassembly = SolidityContract('./tests/native_tests.sol').disassembly account = Account("0x0000000000000000000000000000000000000000", disassembly) accounts = {account.address: account}