Merge branch 'master' into issue/576-add-new-cli-option-to-pass-contract-creation-bytecode

pull/596/head
Maxime Biais 6 years ago
commit fac974080b
No known key found for this signature in database
GPG Key ID: F3EA910F71E3C894
  1. 20
      README.md
  2. 4
      mythril/analysis/modules/dependence_on_predictable_vars.py
  3. 4
      mythril/analysis/modules/ether_send.py
  4. 2
      mythril/analysis/modules/multiple_sends.py
  5. 1
      mythril/analysis/symbolic.py
  6. 8
      mythril/analysis/traceexplore.py
  7. 2
      mythril/disassembler/disassembly.py
  8. 2
      mythril/ether/ethcontract.py
  9. 115
      mythril/ether/evm.py
  10. 17
      mythril/ethereum/interface/leveldb/accountindexing.py
  11. 61
      mythril/ethereum/interface/leveldb/client.py
  12. 32
      mythril/ethereum/interface/leveldb/state.py
  13. 14
      mythril/interfaces/cli.py
  14. 2
      mythril/laser/ethereum/call.py
  15. 10
      mythril/laser/ethereum/instructions.py
  16. 2
      mythril/laser/ethereum/state.py
  17. 2
      mythril/laser/ethereum/svm.py
  18. 24
      mythril/mythril.py
  19. 3
      mythril/support/signatures.py
  20. 1
      requirements.txt
  21. 3
      setup.py
  22. BIN
      static/mythril.png
  23. BIN
      static/mythril_new.png
  24. 2
      tests/analysis/test_delegatecall.py
  25. 2
      tests/laser/state/mstack_test.py
  26. 2
      tests/laser/transaction/symbolic_test.py
  27. 2
      tests/report_test.py
  28. 3
      tests/taint_runner_test.py

@ -1,17 +1,23 @@
# Mythril OSS [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Mythril%20-%20Security%20Analyzer%20for%20Ethereum%20Smart%20Contracts&url=https://www.github.com/ConsenSys/mythril)
# Mythril Classic
<p align="center">
<img src="/static/mythril_new.png" height="320px"/>
</p>
[![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=In%20Progress)](https://waffle.io/ConsenSys/mythril)
![Master Build Status](https://img.shields.io/circleci/project/github/ConsenSys/mythril-classic/master.svg)
[![Waffle.io - Columns and their card count](https://badge.waffle.io/ConsenSys/mythril-classic.svg?columns=In%20Progress)](https://waffle.io/ConsenSys/mythril-classic/)
[![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)
<img height="120px" align="right" src="https://github.com/ConsenSys/mythril/raw/master/static/mythril.png" alt="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.
Mythril Classic is an open-source 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 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.
Oh and by the way, we're also building an easy-to-use security analysis platform (a.k.a. "the INFURA for smart contract security") that anybody can use to create purpose-built security tools. It's called [Mythril Platform](https://mythril.ai) and you should definitely [check it out](https://media.consensys.net/mythril-platform-api-is-upping-the-smart-contract-security-game-eee1d2642488).
## Installation and setup
@ -31,7 +37,7 @@ See the [Wiki](https://github.com/ConsenSys/mythril/wiki/Installation-and-Setup)
## Usage
Instructions for using the 'myth' tool are found on the [Wiki](https://github.com/ConsenSys/mythril/wiki).
Instructions for using the 'myth' tool are found on the [Wiki](https://github.com/ConsenSys/mythril-classic/wiki).
For support or general discussions please join the Mythril community on [Discord](https://discord.gg/E3YrVtG).

@ -120,8 +120,8 @@ def solve(call):
model = solver.get_model(call.node.constraints)
logging.debug("[DEPENDENCE_ON_PREDICTABLE_VARS] MODEL: " + str(model))
for d in model.decls():
logging.debug("[DEPENDENCE_ON_PREDICTABLE_VARS] main model: %s = 0x%x" % (d.name(), model[d].as_long()))
for decl in model.decls():
logging.debug("[DEPENDENCE_ON_PREDICTABLE_VARS] main model: %s = 0x%x" % (decl.name(), model[decl].as_long()))
return True
except UnsatError:

@ -111,8 +111,8 @@ def execute(statespace):
try:
model = solver.get_model(node.constraints)
for d in model.decls():
logging.debug("[ETHER_SEND] main model: %s = 0x%x" % (d.name(), model[d].as_long()))
for decl in model.decls():
logging.debug("[ETHER_SEND] main model: %s = 0x%x" % (decl.name(), model[decl].as_long()))
debug = "SOLVER OUTPUT:\n" + solver.pretty_print_model(model)

@ -38,7 +38,7 @@ def execute(statespace):
def _explore_nodes(call, statespace):
children = _child_nodes(statespace, call.node)
sending_children = list(filter(lambda call: call.node in children, statespace.calls))
sending_children = list(filter(lambda c: c.node in children, statespace.calls))
return sending_children

@ -16,7 +16,6 @@ class SymExecWrapper:
def __init__(self, contract, address, strategy, dynloader=None, max_depth=22,
execution_timeout=None, create_timeout=None, max_transaction_count=3):
s_strategy = None
if strategy == 'dfs':
s_strategy = DepthFirstSearchStrategy
elif strategy == 'bfs':

@ -13,8 +13,8 @@ colors = [
{'border': '#4753bf', 'background': '#3b46a1', 'highlight': {'border': '#fff', 'background': '#424db3'}},
]
def get_serializable_statespace(statespace):
nodes = []
edges = []
@ -40,10 +40,10 @@ def get_serializable_statespace(statespace):
color = color_map[node.get_cfg_dict()['contract_name']]
def get_state_accounts(state):
def get_state_accounts(node_state):
state_accounts = []
for key in state.accounts:
account = state.accounts[key].as_dict
for key in node_state.accounts:
account = node_state.accounts[key].as_dict
account.pop('code', None)
account['balance'] = str(account['balance'])

@ -5,7 +5,7 @@ import logging
class Disassembly(object):
def __init__(self, code, enable_online_lookup=True):
def __init__(self, code, enable_online_lookup=False):
self.instruction_list = asm.disassemble(util.safe_decode(code))
self.func_hashes = []
self.func_to_addr = {}

@ -6,7 +6,7 @@ import re
class ETHContract(persistent.Persistent):
def __init__(self, code="", creation_code="", name="Unknown", enable_online_lookup=True):
def __init__(self, code="", creation_code="", name="Unknown", enable_online_lookup=False):
# Workaround: We currently do not support compile-time linking.
# Dynamic contract addresses of the format __[contract-name]_____________ are replaced with a generic address

@ -7,69 +7,52 @@ from io import StringIO
import re
def trace(code, calldata = ""):
log_handlers = ['eth.vm.op', 'eth.vm.op.stack', 'eth.vm.op.memory', 'eth.vm.op.storage']
output = StringIO()
stream_handler = StreamHandler(output)
for handler in log_handlers:
log_vm_op = get_logger(handler)
log_vm_op.setLevel("TRACE")
log_vm_op.addHandler(stream_handler)
addr = bytes.fromhex('0123456789ABCDEF0123456789ABCDEF01234567')
state = State()
ext = messages.VMExt(state, transactions.Transaction(0, 0, 21000, addr, 0, addr))
message = vm.Message(addr, addr, 0, 21000, calldata)
res, gas, dat = vm.vm_execute(ext, message, util.safe_decode(code))
stream_handler.flush()
ret = output.getvalue()
lines = ret.split("\n")
trace = []
for line in lines:
m = re.search(r'pc=b\'(\d+)\'.*op=([A-Z0-9]+)', line)
if m:
pc = m.group(1)
op = m.group(2)
m = re.match(r'.*stack=(\[.*?\])', line)
if m:
stackitems = re.findall(r'b\'(\d+)\'', m.group(1))
stack = "["
if len(stackitems):
for i in range(0, len(stackitems) - 1):
stack += hex(int(stackitems[i])) + ", "
stack += hex(int(stackitems[-1]))
stack += "]"
else:
stack = "[]"
if re.match(r'^PUSH.*', op):
val = re.search(r'pushvalue=(\d+)', line).group(1)
pushvalue = hex(int(val))
trace.append({'pc': pc, 'op': op, 'stack': stack, 'pushvalue': pushvalue})
else:
trace.append({'pc': pc, 'op': op, 'stack': stack})
return trace
def trace(code, calldata=""):
log_handlers = ['eth.vm.op', 'eth.vm.op.stack', 'eth.vm.op.memory', 'eth.vm.op.storage']
output = StringIO()
stream_handler = StreamHandler(output)
for handler in log_handlers:
log_vm_op = get_logger(handler)
log_vm_op.setLevel("TRACE")
log_vm_op.addHandler(stream_handler)
addr = bytes.fromhex('0123456789ABCDEF0123456789ABCDEF01234567')
state = State()
ext = messages.VMExt(state, transactions.Transaction(0, 0, 21000, addr, 0, addr))
message = vm.Message(addr, addr, 0, 21000, calldata)
vm.vm_execute(ext, message, util.safe_decode(code))
stream_handler.flush()
ret = output.getvalue()
lines = ret.split("\n")
state_trace = []
for line in lines:
m = re.search(r'pc=b\'(\d+)\'.*op=([A-Z0-9]+)', line)
if m:
pc = m.group(1)
op = m.group(2)
m = re.match(r'.*stack=(\[.*?\])', line)
if m:
stackitems = re.findall(r'b\'(\d+)\'', m.group(1))
stack = "["
if len(stackitems):
for i in range(0, len(stackitems) - 1):
stack += hex(int(stackitems[i])) + ", "
stack += hex(int(stackitems[-1]))
stack += "]"
else:
stack = "[]"
if re.match(r'^PUSH.*', op):
val = re.search(r'pushvalue=(\d+)', line).group(1)
pushvalue = hex(int(val))
state_trace.append({'pc': pc, 'op': op, 'stack': stack, 'pushvalue': pushvalue})
else:
state_trace.append({'pc': pc, 'op': op, 'stack': stack})
return state_trace

@ -63,16 +63,15 @@ class AccountIndexer(object):
def get_contract_by_hash(self, contract_hash):
"""
get mapped address by its hash, if not found try indexing
get mapped contract_address by its hash, if not found try indexing
"""
address = self.db.reader._get_address_by_hash(contract_hash)
if address is not None:
return address
contract_address = self.db.reader._get_address_by_hash(contract_hash)
if contract_address is not None:
return contract_address
else:
raise AddressNotFoundError
return self.db.reader._get_address_by_hash(contract_hash)
def _process(self, startblock):
"""
Processesing method
@ -82,9 +81,9 @@ class AccountIndexer(object):
addresses = []
for blockNum in range(startblock, startblock + BATCH_SIZE):
hash = self.db.reader._get_block_hash(blockNum)
if hash is not None:
receipts = self.db.reader._get_block_receipts(hash, blockNum)
block_hash = self.db.reader._get_block_hash(blockNum)
if block_hash is not None:
receipts = self.db.reader._get_block_receipts(block_hash, blockNum)
for receipt in receipts:
if receipt.contractAddress is not None and not all(b == 0 for b in receipt.contractAddress):

@ -79,52 +79,43 @@ class LevelDBReader(object):
gets head block header
"""
if not self.head_block_header:
hash = self.db.get(head_header_key)
num = self._get_block_number(hash)
self.head_block_header = self._get_block_header(hash, num)
block_hash = self.db.get(head_header_key)
num = self._get_block_number(block_hash)
self.head_block_header = self._get_block_header(block_hash, num)
# find header with valid state
while not self.db.get(self.head_block_header.state_root) and self.head_block_header.prevhash is not None:
hash = self.head_block_header.prevhash
num = self._get_block_number(hash)
self.head_block_header = self._get_block_header(hash, num)
block_hash = self.head_block_header.prevhash
num = self._get_block_number(block_hash)
self.head_block_header = self._get_block_header(block_hash, num)
return self.head_block_header
def _get_block_number(self, hash):
"""
gets block number by hash
"""
number_key = block_hash_prefix + hash
def _get_block_number(self, block_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, hash, num):
"""
get block header by block header hash & number
"""
header_key = header_prefix + num + hash
def _get_block_header(self, block_hash, num):
"""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, hash):
"""
get mapped address by its hash
"""
address_key = address_prefix + hash
def _get_address_by_hash(self, block_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, hash, num):
"""
get block transaction receipts by block header hash & number
"""
def _get_block_receipts(self, block_hash, num):
"""Get block transaction receipts by block header hash & number"""
number = _format_block_number(num)
receipts_key = block_receipts_prefix + number + hash
receipts_key = block_receipts_prefix + number + block_hash
receipts_data = self.db.get(receipts_key)
receipts = rlp.decode(receipts_data, sedes=CountableList(ReceiptForStorage))
return receipts
@ -216,12 +207,10 @@ class EthLevelDB(object):
if not cnt % 1000:
logging.info("Searched %d contracts" % cnt)
def contract_hash_to_address(self, hash):
"""
tries to find corresponding account address
"""
def contract_hash_to_address(self, contract_hash):
"""Tries to find corresponding account address"""
address_hash = binascii.a2b_hex(utils.remove_0x_head(hash))
address_hash = binascii.a2b_hex(utils.remove_0x_head(contract_hash))
indexer = AccountIndexer(self)
return _encode_hex(indexer.get_contract_by_hash(address_hash))
@ -230,9 +219,9 @@ class EthLevelDB(object):
"""
gets block header by block number
"""
hash = self.reader._get_block_hash(number)
block_hash = self.reader._get_block_hash(number)
block_number = _format_block_number(number)
return self.reader._get_block_header(hash, block_number)
return self.reader._get_block_header(block_hash, block_number)
def eth_getBlockByNumber(self, number):
"""

@ -43,9 +43,9 @@ class Account(rlp.Serializable):
('code_hash', hash32)
]
def __init__(self, nonce, balance, storage, code_hash, db, address):
def __init__(self, nonce, balance, storage, code_hash, db, addr):
self.db = db
self.address = address
self.address = addr
super(Account, self).__init__(nonce, balance, storage, code_hash)
self.storage_cache = {}
self.storage_trie = SecureTrie(Trie(self.db))
@ -73,12 +73,12 @@ class Account(rlp.Serializable):
return self.storage_cache[key]
@classmethod
def blank_account(cls, db, address, initial_nonce=0):
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, address)
o = cls(initial_nonce, 0, trie.BLANK_ROOT, BLANK_HASH, db, addr)
o.existent_at_start = False
return o
@ -100,21 +100,21 @@ class State:
self.journal = []
self.cache = {}
def get_and_cache_account(self, address):
"""
gets and caches an account for an addres, creates blank if not found
"""
if address in self.cache:
return self.cache[address]
rlpdata = self.secure_trie.get(address)
if rlpdata == trie.BLANK_NODE and len(address) == 32: # support for hashed addresses
rlpdata = self.trie.get(address)
def get_and_cache_account(self, addr):
"""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=address)
o = rlp.decode(rlpdata, Account, db=self.db, address=addr)
else:
o = Account.blank_account(
self.db, address, 0)
self.cache[address] = o
self.db, addr, 0)
self.cache[addr] = o
o._mutable = True
o._cached_rlp = None
return o

@ -15,10 +15,11 @@ import argparse
from mythril.exceptions import CriticalError, AddressNotFoundError
from mythril.mythril import Mythril
from mythril.version import VERSION
import mythril.support.signatures as sigs
def exit_with_error(format, message):
if format == 'text' or format == 'markdown':
def exit_with_error(format_, message):
if format_ == 'text' or format_ == 'markdown':
print(message)
else:
result = {'success': False, 'error': str(message), 'issues': []}
@ -79,6 +80,7 @@ def main():
options.add_argument('--phrack', action='store_true', help='Phrack-style call graph')
options.add_argument('--enable-physics', action='store_true', help='enable graph physics simulation')
options.add_argument('-v', type=int, help='log level (0-2)', metavar='LOG_LEVEL')
options.add_argument('-q', '--query-signature', action='store_true', help='Lookup function signatures through www.4byte.directory')
rpc = parser.add_argument_group('RPC options')
rpc.add_argument('-i', action='store_true', help='Preset: Infura Node service (Mainnet)')
@ -103,6 +105,7 @@ def main():
parser.print_help()
sys.exit()
if args.v:
if 0 <= args.v < 3:
coloredlogs.install(
@ -112,6 +115,10 @@ def main():
else:
exit_with_error(args.outform, "Invalid -v value, you can find valid values in usage")
if args.query_signature:
if sigs.ethereum_input_decoder == None:
exit_with_error(args.outform, "The --query-signature function requires the python package ethereum-input-decoder")
# -- commands --
if args.hash:
print(Mythril.hash_for_function_signature(args.hash))
@ -123,7 +130,8 @@ def main():
# solc_args = None, dynld = None, max_recursion_depth = 12):
mythril = Mythril(solv=args.solv, dynld=args.dynld,
solc_args=args.solc_args)
solc_args=args.solc_args,
enable_online_lookup=args.query_signature)
if args.dynld and not (args.rpc or args.i):
mythril.set_api_from_config_path()

@ -99,7 +99,7 @@ def get_callee_account(global_state, callee_address, dynamic_loader):
try:
code = dynamic_loader.dynld(environment.active_account.address, callee_address)
except Exception as e:
except Exception:
logging.debug("Unable to execute dynamic loader.")
raise ValueError()
if code is None:

@ -497,7 +497,6 @@ class Instruction:
global keccak_function_manager
state = global_state.mstate
environment = global_state.environment
op0, op1 = state.stack.pop(), state.stack.pop()
try:
@ -701,12 +700,9 @@ class Instruction:
try:
# Attempt to concretize value
_bytes = util.concrete_int_to_bytes(value)
state.memory[mstart:mstart+len(_bytes)] = _bytes
except (AttributeError, TypeError):
state.memory[mstart: mstart + len(_bytes)] = _bytes
except:
try:
state.memory[mstart] = value
except TypeError:
@ -948,7 +944,7 @@ class Instruction:
state = global_state.mstate
dpth = int(self.op_code[3:])
state.stack.pop(), state.stack.pop()
[state.stack.pop() for x in range(dpth)]
[state.stack.pop() for _ in range(dpth)]
# Not supported
return [global_state]

@ -278,10 +278,10 @@ class GlobalState:
def new_bitvec(self, name, size=256):
transaction_id = self.current_transaction.id
node_id = self.node.uid
return BitVec("{}_{}".format(transaction_id, name), size)
class WorldState:
"""
The WorldState class represents the world state as described in the yellow paper

@ -74,7 +74,7 @@ class LaserEVM:
logging.info("Finished contract creation, found {} open states".format(len(self.open_states)))
if len(self.open_states) == 0:
logging.warning("No contract was created during the execution of contract creation "
"Increase the resources for creation execution (--max-depth or --create_timeout)")
"Increase the resources for creation execution (--max-depth or --create-timeout)")
# Reset code coverage
self.coverage = {}

@ -76,18 +76,20 @@ class Mythril(object):
"""
def __init__(self, solv=None,
solc_args=None, dynld=False):
solc_args=None, dynld=False,
enable_online_lookup=False):
self.solv = solv
self.solc_args = solc_args
self.dynld = dynld
self.enable_online_lookup = enable_online_lookup
self.mythril_dir = self._init_mythril_dir()
self.sigs = signatures.SignatureDb()
self.sigs = signatures.SignatureDb(enable_online_lookup=self.enable_online_lookup)
try:
self.sigs.open() # tries mythril_dir/signatures.json by default (provide path= arg to make this configurable)
except FileNotFoundError as fnfe:
except FileNotFoundError:
logging.info(
"No signature database found. Creating database if sigs are loaded in: " + self.sigs.signatures_file + "\n" +
"Consider replacing it with the pre-initialized database at https://raw.githubusercontent.com/ConsenSys/mythril/master/signatures.json")
@ -261,8 +263,7 @@ class Mythril(object):
def search_db(self, search):
def search_callback(contract, address, balance):
def search_callback(_, address, balance):
print("Address: " + address + ", balance: " + str(balance))
try:
@ -280,10 +281,9 @@ class Mythril(object):
def load_from_bytecode(self, code, is_contract_creation=False):
address = util.get_indexed_address(0)
if (is_contract_creation):
self.contracts.append(ETHContract(creation_code=code, name="MAIN"))
self.contracts.append(ETHContract(creation_code=code, name="MAIN", enable_online_lookup=self.enable_online_lookup))
else:
self.contracts.append(ETHContract(code=code, name="MAIN"))
print(self.contracts)
self.contracts.append(ETHContract(code=code, name="MAIN", enable_online_lookup=self.enable_online_lookup))
return address, self.contracts[-1] # return address and contract object
def load_from_address(self, address):
@ -294,15 +294,15 @@ class Mythril(object):
code = self.eth.eth_getCode(address)
except FileNotFoundError as e:
raise CriticalError("IPC error: " + str(e))
except ConnectionError as e:
except ConnectionError:
raise CriticalError("Could not connect to RPC server. Make sure that your node is running and that RPC parameters are set correctly.")
except Exception as e:
raise CriticalError("IPC / RPC error: " + str(e))
raise CriticalError("IPC / RPC error: " + str(e))
else:
if code == "0x" or code == "0x0":
raise CriticalError("Received an empty response from eth_getCode. Check the contract address and verify that you are on the correct chain.")
else:
self.contracts.append(ETHContract(code, name=address))
self.contracts.append(ETHContract(code, name=address, enable_online_lookup=self.enable_online_lookup))
return address, self.contracts[-1] # return address and contract object
def load_from_solidity(self, solidity_files):
@ -439,7 +439,7 @@ class Mythril(object):
outtxt.append("{}: {}".format(hex(i), self.eth.eth_getStorageAt(address, i)))
except FileNotFoundError as e:
raise CriticalError("IPC error: " + str(e))
except ConnectionError as e:
except ConnectionError:
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)

@ -11,7 +11,6 @@ from subprocess import Popen, PIPE
from mythril.exceptions import CompilerError
# todo: tintinweb - make this a normal requirement? (deps: eth-abi and requests, both already required by mythril)
try:
# load if available but do not fail
import ethereum_input_decoder
@ -54,7 +53,7 @@ except ImportError:
class SignatureDb(object):
def __init__(self, enable_online_lookup=True):
def __init__(self, enable_online_lookup=False):
"""
Constr
:param enable_online_lookup: enable onlien signature hash lookup

@ -4,6 +4,7 @@ coverage
eth_abi>=1.0.0
eth-account>=0.1.0a2
ethereum>=2.3.2
ethereum-input-decoder>=0.2.2
eth-hash>=0.1.0
eth-keyfile>=0.5.1
eth-keys>=0.2.0b3

@ -104,7 +104,8 @@ setup(
'py-flags',
'mock',
'configparser>=3.5.0',
'persistent>=4.2.0'
'persistent>=4.2.0',
'ethereum-input-decoder>=0.2.2'
],
tests_require=[

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

@ -189,7 +189,7 @@ def test_delegate_call(sym_mock, concrete_mock, curr_instruction):
statespace.calls = [call]
# act
issues = execute(statespace)
execute(statespace)
# assert
assert concrete_mock.call_count == 1

@ -45,7 +45,7 @@ class MachineStackTest(BaseTestCase):
mstack = MachineStack([0, 1])
with pytest.raises(NotImplementedError):
mstack = mstack + [2]
mstack + [2]
@staticmethod
def test_mstack_no_support_iadd():

@ -49,7 +49,7 @@ def test_execute_contract_creation(mocked_setup: MagicMock):
mocked_setup.side_effect = _is_contract_creation
# Act
new_account = execute_contract_creation(laser_evm, "606000")
execute_contract_creation(laser_evm, "606000")
# Assert
# mocked_setup.assert_called()

@ -23,7 +23,7 @@ def _fix_debug_data(json_str):
def _generate_report(input_file):
contract = ETHContract(input_file.read_text())
contract = ETHContract(input_file.read_text(), enable_online_lookup=False)
sym = SymExecWrapper(contract, address=(util.get_indexed_address(0)), strategy="dfs", execution_timeout=30)
issues = fire_lasers(sym)

@ -6,6 +6,7 @@ from mythril.laser.ethereum.cfg import Node, Edge
from mythril.laser.ethereum.state import MachineState, Account, Environment, GlobalState
from mythril.laser.ethereum.svm import LaserEVM
def test_execute_state(mocker):
record = TaintRecord()
record.stack = [True, False, True]
@ -54,8 +55,6 @@ def test_execute_node(mocker):
assert state_1 in record.states
def test_execute(mocker):
active_account = Account('0x00')
environment = Environment(active_account, None, None, None, None, None)

Loading…
Cancel
Save