From 476e5dc4e890281fab040e8d3f586c2113ec5135 Mon Sep 17 00:00:00 2001 From: Maxime Biais Date: Thu, 18 Oct 2018 14:19:45 +0200 Subject: [PATCH 01/17] Add a new CLI option to load contract creation bytecode from the command line --- mythril/analysis/symbolic.py | 4 +++- mythril/ether/ethcontract.py | 5 ++--- mythril/interfaces/cli.py | 7 ++++--- mythril/laser/ethereum/svm.py | 2 +- mythril/mythril.py | 8 ++++++-- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/mythril/analysis/symbolic.py b/mythril/analysis/symbolic.py index c9431257..71037a6b 100644 --- a/mythril/analysis/symbolic.py +++ b/mythril/analysis/symbolic.py @@ -1,6 +1,6 @@ from mythril.laser.ethereum import svm from mythril.laser.ethereum.state import Account -from mythril.ether.soliditycontract import SolidityContract +from mythril.ether.soliditycontract import SolidityContract, ETHContract import copy import logging from .ops import get_variable, SStore, Call, VarType @@ -35,6 +35,8 @@ class SymExecWrapper: if isinstance(contract, SolidityContract): self.laser.sym_exec(creation_code=contract.creation_code, contract_name=contract.name) + elif isinstance(contract, ETHContract) and contract.creation_code: + self.laser.sym_exec(creation_code=contract.creation_code, contract_name=contract.name) else: self.laser.sym_exec(address) diff --git a/mythril/ether/ethcontract.py b/mythril/ether/ethcontract.py index 801e063b..b27f2011 100644 --- a/mythril/ether/ethcontract.py +++ b/mythril/ether/ethcontract.py @@ -6,8 +6,8 @@ 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=True): + # 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 @@ -24,7 +24,6 @@ class ETHContract(persistent.Persistent): def as_dict(self): return { - 'address': self.address, 'name': self.name, 'code': self.code, 'creation_code': self.creation_code, diff --git a/mythril/interfaces/cli.py b/mythril/interfaces/cli.py index 1784add4..0d1d9ba5 100644 --- a/mythril/interfaces/cli.py +++ b/mythril/interfaces/cli.py @@ -43,10 +43,11 @@ def main(): inputs = parser.add_argument_group('input arguments') inputs.add_argument('-c', '--code', help='hex-encoded bytecode string ("6060604052...")', metavar='BYTECODE') - inputs.add_argument('-f', '--codefile', help='file containing hex-encoded bytecode string', + inputs.add_argument('-f', '--codefile', help='file containing hex-encoded bytecode string', metavar='BYTECODEFILE', type=argparse.FileType('r')) inputs.add_argument('-a', '--address', help='pull contract from the blockchain', metavar='CONTRACT_ADDRESS') inputs.add_argument('-l', '--dynld', action='store_true', help='auto-load dependencies from the blockchain') + inputs.add_argument('--contract-creation', dest="is_contract_creation", action='store_true', help='Only when -c or -f is used. Consider the input bytecode as contract creation code.') outputs = parser.add_argument_group('output formats') outputs.add_argument('-o', '--outform', choices=['text', 'markdown', 'json'], default='text', @@ -166,10 +167,10 @@ def main(): if args.code: # Load from bytecode - address, _ = mythril.load_from_bytecode(args.code) + address, _ = mythril.load_from_bytecode(args.code, args.is_contract_creation) elif args.codefile: bytecode = ''.join([l.strip() for l in args.codefile if len(l.strip()) > 0]) - address, _ = mythril.load_from_bytecode(bytecode) + address, _ = mythril.load_from_bytecode(bytecode, args.is_contract_creation) elif args.address: # Get bytecode from a contract address address, _ = mythril.load_from_address(args.address) diff --git a/mythril/laser/ethereum/svm.py b/mythril/laser/ethereum/svm.py index f1bd80b5..e29e4e76 100644 --- a/mythril/laser/ethereum/svm.py +++ b/mythril/laser/ethereum/svm.py @@ -93,7 +93,7 @@ class LaserEVM: logging.info("%d nodes, %d edges, %d total states", len(self.nodes), len(self.edges), self.total_states) for code, coverage in self.coverage.items(): cov = reduce(lambda sum_, val: sum_ + 1 if val else sum_, coverage[1]) / float(coverage[0]) * 100 - logging.info("Achieved {} coverage for code: {}".format(cov, code)) + logging.info("Achieved {:.2f}% coverage for code: {}".format(cov, code)) def _get_covered_instructions(self) -> int: """ Gets the total number of covered instructions for all accounts in the svm""" diff --git a/mythril/mythril.py b/mythril/mythril.py index 123ab904..185c823d 100644 --- a/mythril/mythril.py +++ b/mythril/mythril.py @@ -277,9 +277,13 @@ class Mythril(object): print(self.eth_db.contract_hash_to_address(hash)) - def load_from_bytecode(self, code): + def load_from_bytecode(self, code, is_contract_creation=False): address = util.get_indexed_address(0) - self.contracts.append(ETHContract(code, name="MAIN")) + if (is_contract_creation): + self.contracts.append(ETHContract(creation_code=code, name="MAIN")) + else: + self.contracts.append(ETHContract(code=code, name="MAIN")) + print(self.contracts) return address, self.contracts[-1] # return address and contract object def load_from_address(self, address): From 957575087ba99540a70727f7f93ffe805225df27 Mon Sep 17 00:00:00 2001 From: Maxime Biais Date: Fri, 26 Oct 2018 10:05:57 +0200 Subject: [PATCH 02/17] Replace --contract-creation option by --bin-runtime Default bytecode expected is now the contract creation bytecode. --- mythril/interfaces/cli.py | 6 +++--- mythril/mythril.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mythril/interfaces/cli.py b/mythril/interfaces/cli.py index feb7777d..7358ce9d 100644 --- a/mythril/interfaces/cli.py +++ b/mythril/interfaces/cli.py @@ -48,7 +48,7 @@ def main(): metavar='BYTECODEFILE', type=argparse.FileType('r')) inputs.add_argument('-a', '--address', help='pull contract from the blockchain', metavar='CONTRACT_ADDRESS') inputs.add_argument('-l', '--dynld', action='store_true', help='auto-load dependencies from the blockchain') - inputs.add_argument('--contract-creation', dest="is_contract_creation", action='store_true', help='Only when -c or -f is used. Consider the input bytecode as contract creation code.') + inputs.add_argument('--bin-runtime', action='store_true', help='Only when -c or -f is used. Consider the input bytecode as binary runtime code, default being the contract creation bytecode.') outputs = parser.add_argument_group('output formats') outputs.add_argument('-o', '--outform', choices=['text', 'markdown', 'json'], default='text', @@ -175,10 +175,10 @@ def main(): if args.code: # Load from bytecode - address, _ = mythril.load_from_bytecode(args.code, args.is_contract_creation) + address, _ = mythril.load_from_bytecode(args.code, args.bin_runtime) elif args.codefile: bytecode = ''.join([l.strip() for l in args.codefile if len(l.strip()) > 0]) - address, _ = mythril.load_from_bytecode(bytecode, args.is_contract_creation) + address, _ = mythril.load_from_bytecode(bytecode, args.bin_runtime) elif args.address: # Get bytecode from a contract address address, _ = mythril.load_from_address(args.address) diff --git a/mythril/mythril.py b/mythril/mythril.py index 8097aa18..64243d75 100644 --- a/mythril/mythril.py +++ b/mythril/mythril.py @@ -278,12 +278,12 @@ class Mythril(object): print(self.eth_db.contract_hash_to_address(hash)) - def load_from_bytecode(self, code, is_contract_creation=False): + def load_from_bytecode(self, code, bin_runtime=False): address = util.get_indexed_address(0) - if (is_contract_creation): - self.contracts.append(ETHContract(creation_code=code, name="MAIN", enable_online_lookup=self.enable_online_lookup)) - else: + if (bin_runtime): self.contracts.append(ETHContract(code=code, name="MAIN", enable_online_lookup=self.enable_online_lookup)) + else: + self.contracts.append(ETHContract(creation_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): From 0f8e9144a64d22dac51757d20b7282df5cfb8a17 Mon Sep 17 00:00:00 2001 From: Haozhong Zhang Date: Tue, 16 Oct 2018 16:55:58 +0800 Subject: [PATCH 03/17] analysis/transaction_order_dependence: import missing `copy` module in transaction_order_dependence.py copy.deepcopy() is used in transaction_order_dependence.py, but the `copy` module is not imported. --- mythril/analysis/modules/transaction_order_dependence.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mythril/analysis/modules/transaction_order_dependence.py b/mythril/analysis/modules/transaction_order_dependence.py index 4528459c..9db7c104 100644 --- a/mythril/analysis/modules/transaction_order_dependence.py +++ b/mythril/analysis/modules/transaction_order_dependence.py @@ -1,5 +1,6 @@ import logging import re +import copy from mythril.analysis import solver from mythril.analysis.ops import * From ce4075b8df3e8d6bcfdd309b91b3a3fad2177f3d Mon Sep 17 00:00:00 2001 From: Haozhong Zhang Date: Tue, 9 Oct 2018 13:52:12 +0800 Subject: [PATCH 04/17] laser/instruction: remove unused solver in sstore_() --- mythril/laser/ethereum/instructions.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/mythril/laser/ethereum/instructions.py b/mythril/laser/ethereum/instructions.py index c31d5f46..cabdaba1 100644 --- a/mythril/laser/ethereum/instructions.py +++ b/mythril/laser/ethereum/instructions.py @@ -18,7 +18,6 @@ from z3 import ( URem, SRem, BitVec, - Solver, is_true, BitVecVal, If, @@ -43,7 +42,6 @@ from mythril.laser.ethereum.transaction import ( TransactionStartSignal, ContractCreationTransaction, ) -from mythril.analysis.solver import get_model TT256 = 2 ** 256 TT256M1 = 2 ** 256 - 1 @@ -924,9 +922,6 @@ class Instruction: storage_keys = global_state.environment.active_account.storage.keys() keccak_keys = filter(keccak_function_manager.is_keccak, storage_keys) - solver = Solver() - solver.set(timeout=1000) - results = [] new = False From 725bfec464594070d568f6a24880abd16afb05a4 Mon Sep 17 00:00:00 2001 From: Haozhong Zhang Date: Tue, 30 Oct 2018 20:53:30 +0800 Subject: [PATCH 05/17] laser/instruction: simplify before checking by Z3 is_true() Z3 is_true() does not automatically consider `expr == expr` to be true, so `is_true(key_argument == index_argument)` in `sstore_()` will miss lots of positive conditions and then generate lots of unnecessary subsequent paths. Take the following contract for example ``` contract Foo { mapping(address => uint) public balances; function bar(address _to, uint256 _value) public { require(balances[_to] + _value >= balances[_to]); balances[_to] += _value; balances[_to] += _value; } ``` Before this commit, - 772 nodes/771 edges/8288 states are generated. After this commit, - only 237 nodes/236 edges/3204 states are generated. --- mythril/laser/ethereum/instructions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mythril/laser/ethereum/instructions.py b/mythril/laser/ethereum/instructions.py index cabdaba1..edefece9 100644 --- a/mythril/laser/ethereum/instructions.py +++ b/mythril/laser/ethereum/instructions.py @@ -929,7 +929,7 @@ class Instruction: key_argument = keccak_function_manager.get_argument(keccak_key) index_argument = keccak_function_manager.get_argument(index) - if is_true(key_argument == index_argument): + if is_true(simplify(key_argument == index_argument)): return self._sstore_helper( copy(global_state), keccak_key, From 91015e63baae514393e0cb6a7ea64e80a3b93d67 Mon Sep 17 00:00:00 2001 From: Haozhong Zhang Date: Tue, 30 Oct 2018 21:17:06 +0800 Subject: [PATCH 06/17] analysis/integer: remove unnecessary deepcopy of constraints `solver.get_model()` has no way to mutate constraints passed to it, so the expensive deepcopy of constraints before calling `solver.get_model()`is unnecessary. --- mythril/analysis/modules/integer.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mythril/analysis/modules/integer.py b/mythril/analysis/modules/integer.py index b5c952f8..4e6f9b25 100644 --- a/mythril/analysis/modules/integer.py +++ b/mythril/analysis/modules/integer.py @@ -127,11 +127,8 @@ def _try_constraints(constraints, new_constraints): Tries new constraints :return Model if satisfiable otherwise None """ - _constraints = copy.deepcopy(constraints) - for constraint in new_constraints: - _constraints.append(copy.deepcopy(constraint)) try: - model = solver.get_model(_constraints) + model = solver.get_model(constraints + new_constraints) return model except UnsatError: return None From 3dd205d6488881988d537b40e1376b500d1895b6 Mon Sep 17 00:00:00 2001 From: "Dr. Sergey Pogodin" Date: Wed, 31 Oct 2018 10:03:16 +0100 Subject: [PATCH 07/17] Version bumped to 0.19.0 --- mythril/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mythril/version.py b/mythril/version.py index 209f9662..624f5a07 100644 --- a/mythril/version.py +++ b/mythril/version.py @@ -1,3 +1,3 @@ # This file is suitable for sourcing inside POSIX shell, e.g. bash as # well as for importing into Python -VERSION = "v0.18.13" # NOQA +VERSION = "v0.19.0" # NOQA From 0d0d8e5ac3cdaaaf8a16f585dd278587c25263e5 Mon Sep 17 00:00:00 2001 From: Haozhong Zhang Date: Wed, 31 Oct 2018 19:55:49 +0800 Subject: [PATCH 08/17] dependencies: bump the minimal Z3 version to 4.8 Following commits will use overflow checking APIs that are only available in newer versions of Z3. --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index d829a885..3691a704 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,5 +24,5 @@ pytest_mock requests rlp>=1.0.1 transaction>=2.2.1 -z3-solver>=4.5 +z3-solver>=4.8 pysha3 diff --git a/setup.py b/setup.py index 6aa0dfb7..c52d2153 100755 --- a/setup.py +++ b/setup.py @@ -75,7 +75,7 @@ setup( install_requires=[ "coloredlogs>=10.0", "ethereum>=2.3.2", - "z3-solver>=4.5", + "z3-solver>=4.8", "requests", "py-solc", "plyvel", From ee674ff803d7f309fd5b296ce51f4d0c47a0d7a2 Mon Sep 17 00:00:00 2001 From: Haozhong Zhang Date: Wed, 31 Oct 2018 11:30:30 +0800 Subject: [PATCH 09/17] analysis/integer: fix the overflow check of bit vector multiplication Differently than the bit vector addition, an overflowed bit vector multiplication does not necessarily result in a value less than any of its operands (e.g., the multiplication of two 8-bit vectors 0x7 and 4 produces 0xC). Fix this issue by using Z3 BVMulNoOverflow in the overflow check of bit vector multiplication. --- mythril/analysis/modules/integer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mythril/analysis/modules/integer.py b/mythril/analysis/modules/integer.py index df0d8988..709d2c2e 100644 --- a/mythril/analysis/modules/integer.py +++ b/mythril/analysis/modules/integer.py @@ -72,11 +72,12 @@ def _check_integer_overflow(statespace, state, node): # Formulate expression if instruction["opcode"] == "ADD": expr = op0 + op1 + constraint = Or(And(ULT(expr, op0), op1 != 0), And(ULT(expr, op1), op0 != 0)) else: expr = op1 * op0 + constraint = Not(BVMulNoOverflow(op0, op1, signed=False)) # Check satisfiable - constraint = Or(And(ULT(expr, op0), op1 != 0), And(ULT(expr, op1), op0 != 0)) model = _try_constraints(node.constraints, [constraint]) if model is None: From a982a7d7fd461c2b670a43e9544164de3ae84b5e Mon Sep 17 00:00:00 2001 From: Haozhong Zhang Date: Wed, 31 Oct 2018 19:58:46 +0800 Subject: [PATCH 10/17] analysis/integer: switch addition overflow check to dedicated Z3 API Use Z3 API BVAddNoOverflow() in the constraint to check the bit vector addition overflow. --- mythril/analysis/modules/integer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mythril/analysis/modules/integer.py b/mythril/analysis/modules/integer.py index 709d2c2e..bb75c550 100644 --- a/mythril/analysis/modules/integer.py +++ b/mythril/analysis/modules/integer.py @@ -72,7 +72,7 @@ def _check_integer_overflow(statespace, state, node): # Formulate expression if instruction["opcode"] == "ADD": expr = op0 + op1 - constraint = Or(And(ULT(expr, op0), op1 != 0), And(ULT(expr, op1), op0 != 0)) + constraint = Not(BVAddNoOverflow(op0, op1, signed=False)) else: expr = op1 * op0 constraint = Not(BVMulNoOverflow(op0, op1, signed=False)) From 9ee0014a1bd4f1db1364ec8a5a3eba94f49784f9 Mon Sep 17 00:00:00 2001 From: Nikhil Parasaram Date: Wed, 31 Oct 2018 22:40:13 +0530 Subject: [PATCH 11/17] Pass solc binary to other functions --- mythril/ether/soliditycontract.py | 10 +++++----- mythril/mythril.py | 9 +++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/mythril/ether/soliditycontract.py b/mythril/ether/soliditycontract.py index 14995b8b..da142c71 100644 --- a/mythril/ether/soliditycontract.py +++ b/mythril/ether/soliditycontract.py @@ -25,18 +25,18 @@ class SourceCodeInfo: self.code = code -def get_contracts_from_file(input_file, solc_args=None): - data = get_solc_json(input_file, solc_args=solc_args) +def get_contracts_from_file(input_file, solc_args=None, solc_binary="solc"): + data = get_solc_json(input_file, solc_args=solc_args, solc_binary=solc_binary) for key, contract in data["contracts"].items(): filename, name = key.split(":") if filename == input_file and len(contract["bin-runtime"]): - yield SolidityContract(input_file, name, solc_args) + yield SolidityContract(input_file=input_file, name=name, solc_args=solc_args, solc_binary=solc_binary) class SolidityContract(ETHContract): - def __init__(self, input_file, name=None, solc_args=None): + def __init__(self, input_file, name=None, solc_args=None, solc_binary="solc"): - data = get_solc_json(input_file, solc_args=solc_args) + data = get_solc_json(input_file, solc_args=solc_args, solc_binary=solc_binary) self.solidity_files = [] diff --git a/mythril/mythril.py b/mythril/mythril.py index d5dbd76f..728f47c6 100644 --- a/mythril/mythril.py +++ b/mythril/mythril.py @@ -375,13 +375,18 @@ class Mythril(object): if contract_name is not None: contract = SolidityContract( - file, contract_name, solc_args=self.solc_args + input_file=file, + name=contract_name, + solc_args=self.solc_args, + solc_binary=self.solc_binary ) self.contracts.append(contract) contracts.append(contract) else: for contract in get_contracts_from_file( - file, solc_args=self.solc_args + input_file=file, + solc_args=self.solc_args, + solc_binary=self.solc_binary ): self.contracts.append(contract) contracts.append(contract) From 973148db669331c8826b5692546e2511e52a079c Mon Sep 17 00:00:00 2001 From: Nikhil Parasaram Date: Wed, 31 Oct 2018 22:47:49 +0530 Subject: [PATCH 12/17] Reformat code with black --- mythril/ether/soliditycontract.py | 7 ++++++- mythril/mythril.py | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mythril/ether/soliditycontract.py b/mythril/ether/soliditycontract.py index da142c71..fdf10fc0 100644 --- a/mythril/ether/soliditycontract.py +++ b/mythril/ether/soliditycontract.py @@ -30,7 +30,12 @@ def get_contracts_from_file(input_file, solc_args=None, solc_binary="solc"): for key, contract in data["contracts"].items(): filename, name = key.split(":") if filename == input_file and len(contract["bin-runtime"]): - yield SolidityContract(input_file=input_file, name=name, solc_args=solc_args, solc_binary=solc_binary) + yield SolidityContract( + input_file=input_file, + name=name, + solc_args=solc_args, + solc_binary=solc_binary, + ) class SolidityContract(ETHContract): diff --git a/mythril/mythril.py b/mythril/mythril.py index 728f47c6..6477d3b2 100644 --- a/mythril/mythril.py +++ b/mythril/mythril.py @@ -378,7 +378,7 @@ class Mythril(object): input_file=file, name=contract_name, solc_args=self.solc_args, - solc_binary=self.solc_binary + solc_binary=self.solc_binary, ) self.contracts.append(contract) contracts.append(contract) @@ -386,7 +386,7 @@ class Mythril(object): for contract in get_contracts_from_file( input_file=file, solc_args=self.solc_args, - solc_binary=self.solc_binary + solc_binary=self.solc_binary, ): self.contracts.append(contract) contracts.append(contract) From 9c92f1b24c36ec01da6085974d86f2a24847845a Mon Sep 17 00:00:00 2001 From: Bernhard Mueller Date: Wed, 31 Oct 2018 20:28:58 +0100 Subject: [PATCH 13/17] Fix z3 version --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index d829a885..252538c5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,5 +24,5 @@ pytest_mock requests rlp>=1.0.1 transaction>=2.2.1 -z3-solver>=4.5 +z3-solver==4.5.1.0.post2 pysha3 diff --git a/setup.py b/setup.py index 6aa0dfb7..4a33a0dc 100755 --- a/setup.py +++ b/setup.py @@ -75,7 +75,7 @@ setup( install_requires=[ "coloredlogs>=10.0", "ethereum>=2.3.2", - "z3-solver>=4.5", + "z3-solver==4.5.1.0.post2", "requests", "py-solc", "plyvel", From 9cbf1d55e5781fdae8ec64f18b9edb5f15b732f8 Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Wed, 31 Oct 2018 20:57:37 +0100 Subject: [PATCH 14/17] revert changes to support z3 4.5 --- mythril/analysis/modules/integer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mythril/analysis/modules/integer.py b/mythril/analysis/modules/integer.py index 8916ed13..aea9ff06 100644 --- a/mythril/analysis/modules/integer.py +++ b/mythril/analysis/modules/integer.py @@ -72,11 +72,12 @@ def _check_integer_overflow(statespace, state, node): # Formulate expression if instruction["opcode"] == "ADD": expr = op0 + op1 - constraint = Not(BVAddNoOverflow(op0, op1, signed=False)) + # constraint = Not(BVAddNoOverflow(op0, op1, signed=False)) else: expr = op1 * op0 - constraint = Not(BVMulNoOverflow(op0, op1, signed=False)) + # constraint = Not(BVMulNoOverflow(op0, op1, signed=False)) + constraint = Or(And(ULT(expr, op0), op1 != 0), And(ULT(expr, op1), op0 != 0)) # Check satisfiable model = _try_constraints(node.constraints, [constraint]) From 036278502a43a4b8d03e8a1cfcf666878f034e04 Mon Sep 17 00:00:00 2001 From: Bernhard Mueller Date: Wed, 31 Oct 2018 22:13:55 +0100 Subject: [PATCH 15/17] Update version.py --- mythril/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mythril/version.py b/mythril/version.py index edb5e509..93f43515 100644 --- a/mythril/version.py +++ b/mythril/version.py @@ -1,3 +1,3 @@ # This file is suitable for sourcing inside POSIX shell, e.g. bash as # well as for importing into Python -VERSION = "v0.19.1" # NOQA +VERSION = "v0.19.3" # NOQA From fe728cc98d223ba16402e2240c35a8adc83ffd9b Mon Sep 17 00:00:00 2001 From: Maxime Biais Date: Mon, 5 Nov 2018 09:59:13 +0100 Subject: [PATCH 16/17] Reformat files using _black_ --- mythril/interfaces/cli.py | 2 +- mythril/mythril.py | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/mythril/interfaces/cli.py b/mythril/interfaces/cli.py index 01c059f0..51bae2a2 100644 --- a/mythril/interfaces/cli.py +++ b/mythril/interfaces/cli.py @@ -93,7 +93,7 @@ def main(): inputs.add_argument( "--bin-runtime", action="store_true", - help="Only when -c or -f is used. Consider the input bytecode as binary runtime code, default being the contract creation bytecode." + help="Only when -c or -f is used. Consider the input bytecode as binary runtime code, default being the contract creation bytecode.", ) outputs = parser.add_argument_group("output formats") diff --git a/mythril/mythril.py b/mythril/mythril.py index 2580166f..67d917f2 100644 --- a/mythril/mythril.py +++ b/mythril/mythril.py @@ -313,16 +313,20 @@ class Mythril(object): def load_from_bytecode(self, code, bin_runtime=False): address = util.get_indexed_address(0) - if (bin_runtime): + if bin_runtime: self.contracts.append( ETHContract( - code=code, name="MAIN", enable_online_lookup=self.enable_online_lookup + code=code, + name="MAIN", + enable_online_lookup=self.enable_online_lookup, ) ) else: self.contracts.append( ETHContract( - creation_code=code, name="MAIN", enable_online_lookup=self.enable_online_lookup + creation_code=code, + name="MAIN", + enable_online_lookup=self.enable_online_lookup, ) ) return address, self.contracts[-1] # return address and contract object From 754eaf4fe1db7b89eb6afb05a3922dbcb9a51aea Mon Sep 17 00:00:00 2001 From: Bernhard Mueller Date: Tue, 6 Nov 2018 23:26:09 +0700 Subject: [PATCH 17/17] Add the much cooler "total downloads" badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b975def..2b3c0fda 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ![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) +[![Downloads](https://pepy.tech/badge/mythril)](https://pepy.tech/project/mythril) 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.