From 7a105e5decb73bf3b16c2edbebd8f8ac7a604554 Mon Sep 17 00:00:00 2001 From: Nikhil Parasaram Date: Wed, 16 Oct 2019 16:02:04 +0100 Subject: [PATCH] Py35 support (#1233) * Add py35 into tox * Use solcx for python3.6+ * Fix tests --- mythril/ethereum/util.py | 8 +++-- mythril/mythril/mythril_disassembler.py | 36 ++++++++++++------- .../transaction/create_transaction_test.py | 10 ++---- tests/native_test.py | 5 +-- tests/solidity_contract_test.py | 16 ++------- tox.ini | 2 +- 6 files changed, 35 insertions(+), 42 deletions(-) diff --git a/mythril/ethereum/util.py b/mythril/ethereum/util.py index a6e1d874..0ec4e645 100644 --- a/mythril/ethereum/util.py +++ b/mythril/ethereum/util.py @@ -2,8 +2,8 @@ solc integration.""" import binascii import json +import sys import os -import solcx from pathlib import Path from subprocess import PIPE, Popen @@ -12,6 +12,9 @@ from ethereum.utils import zpad from mythril.exceptions import CompilerError +if sys.version_info[1] >= 6: + import solcx + def safe_decode(hex_encoded_string): """ @@ -128,10 +131,9 @@ def solc_exists(version): "bin/solc", ) # py-solc setup ] - else: + elif sys.version_info[1] >= 6: # we are using solc-x for the the 0.5 and higher solc_binaries = [os.path.join(solcx.__path__[0], "bin", "solc-v" + version)] - for solc_path in solc_binaries: if os.path.exists(solc_path): return solc_path diff --git a/mythril/mythril/mythril_disassembler.py b/mythril/mythril/mythril_disassembler.py index ad6b04b7..ad28f1f5 100644 --- a/mythril/mythril/mythril_disassembler.py +++ b/mythril/mythril/mythril_disassembler.py @@ -1,7 +1,7 @@ import logging import re import solc -import solcx +import sys import os from ethereum import utils @@ -14,6 +14,9 @@ from mythril.ethereum.evmcontract import EVMContract from mythril.ethereum.interface.rpc.exceptions import ConnectionError from mythril.solidity.soliditycontract import SolidityContract, get_contracts_from_file +if sys.version_info[1] >= 6: + import solcx + log = logging.getLogger(__name__) @@ -67,23 +70,30 @@ class MythrilDisassembler: ): log.info("Given version is already installed") else: - try: - if version.startswith("0.4"): + if version.startswith("0.4"): + try: solc.install_solc("v" + version) - else: + except solc.exceptions.SolcError: + raise CriticalError( + "There was an error when trying to install the specified solc version" + ) + elif sys.version_info[1] >= 6: + # solcx supports python 3.6+ + try: solcx.install_solc("v" + version) - solc_binary = util.solc_exists(version) - if not solc_binary: - raise solc.exceptions.SolcError() - except solc.exceptions.SolcError: - raise CriticalError( - "There was an error when trying to install the specified solc version" - ) - except solcx.exceptions.SolcError: + except solcx.exceptions.SolcError: + raise CriticalError( + "There was an error when trying to install the specified solc version" + ) + else: raise CriticalError( - "There was an error when trying to install the specified solc version" + "Py-Solc doesn't support 0.5.*. You can switch to python 3.6 which uses solcx." ) + solc_binary = util.solc_exists(version) + if not solc_binary: + raise solc.exceptions.SolcError() + log.info("Setting the compiler to %s", solc_binary) return solc_binary diff --git a/tests/laser/transaction/create_transaction_test.py b/tests/laser/transaction/create_transaction_test.py index 574dcc06..ad39fb77 100644 --- a/tests/laser/transaction/create_transaction_test.py +++ b/tests/laser/transaction/create_transaction_test.py @@ -11,10 +11,7 @@ from mythril.analysis.symbolic import SymExecWrapper def test_create(): - contract = SolidityContract( - str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"), - solc_binary=MythrilDisassembler._init_solc_binary("0.5.0"), - ) + contract = SolidityContract(str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol")) laser_evm = svm.LaserEVM({}) @@ -35,10 +32,7 @@ def test_create(): def test_sym_exec(): - contract = SolidityContract( - str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"), - solc_binary=MythrilDisassembler._init_solc_binary("0.5.0"), - ) + contract = SolidityContract(str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol")) sym = SymExecWrapper( contract, diff --git a/tests/native_test.py b/tests/native_test.py index 82bb36b4..3105028d 100644 --- a/tests/native_test.py +++ b/tests/native_test.py @@ -78,10 +78,7 @@ class NativeTests(BaseTestCase): """""" # The solidity version (0.5.3 at the moment) should be kept in sync with # pragma in ./tests/native_tests.sol - disassembly = SolidityContract( - "./tests/native_tests.sol", - solc_binary=MythrilDisassembler._init_solc_binary("0.5.3"), - ).disassembly + disassembly = SolidityContract("./tests/native_tests.sol").disassembly account = Account("0x0000000000000000000000000000000000000000", disassembly) world_state = WorldState() world_state.put_account(account) diff --git a/tests/solidity_contract_test.py b/tests/solidity_contract_test.py index 4edb8e6e..87023116 100644 --- a/tests/solidity_contract_test.py +++ b/tests/solidity_contract_test.py @@ -10,9 +10,7 @@ TEST_FILES = Path(__file__).parent / "testdata/input_contracts" class SolidityContractTest(BaseTestCase): def test_get_source_info_without_name_gets_latest_contract_info(self): input_file = TEST_FILES / "multi_contracts.sol" - contract = SolidityContract( - str(input_file), solc_binary=MythrilDisassembler._init_solc_binary("0.5.0") - ) + contract = SolidityContract(str(input_file)) code_info = contract.get_source_info(142) @@ -22,11 +20,7 @@ class SolidityContractTest(BaseTestCase): def test_get_source_info_with_contract_name_specified(self): input_file = TEST_FILES / "multi_contracts.sol" - contract = SolidityContract( - str(input_file), - name="Transfer1", - solc_binary=MythrilDisassembler._init_solc_binary("0.5.0"), - ) + contract = SolidityContract(str(input_file), name="Transfer1") code_info = contract.get_source_info(142) @@ -36,11 +30,7 @@ class SolidityContractTest(BaseTestCase): def test_get_source_info_with_contract_name_specified_constructor(self): input_file = TEST_FILES / "constructor_assert.sol" - contract = SolidityContract( - str(input_file), - name="AssertFail", - solc_binary=MythrilDisassembler._init_solc_binary("0.5.0"), - ) + contract = SolidityContract(str(input_file), name="AssertFail") code_info = contract.get_source_info(70, constructor=True) diff --git a/tox.ini b/tox.ini index 804b6791..ec2ec40d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py36 +envlist = py35, py36 [testenv] deps =