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") code_info = contract.get_source_info(70, constructor=True) self.assertEqual(code_info.filename, str(input_file)) self.assertEqual(code_info.lineno, 6) self.assertEqual(code_info.code, "assert(var1 > 0)")
def test_get_source_info_with_contract_name_specified(self): input_file = TEST_FILES / "multi_contracts.sol" contract = SolidityContract(str(input_file), name="Transfer1") code_info = contract.get_source_info(142) self.assertEqual(code_info.filename, str(input_file)) self.assertEqual(code_info.lineno, 6) self.assertEqual(code_info.code, "msg.sender.transfer(1 ether)")
def test_get_source_info_without_name_gets_latest_contract_info(self): input_file = TEST_FILES / "multi_contracts.sol" contract = SolidityContract(str(input_file)) code_info = contract.get_source_info(142) self.assertEqual(code_info.filename, str(input_file)) self.assertEqual(code_info.lineno, 14) self.assertEqual(code_info.code, "msg.sender.transfer(2 ether)")
def test_laser_result(self): for input_file in TESTDATA_INPUTS_CONTRACTS.iterdir(): if input_file.name in ["weak_random.sol", "environments.sol"]: continue output_expected = TESTDATA_OUTPUTS_EXPECTED_LASER_RESULT / ( input_file.name + ".json") output_current = TESTDATA_OUTPUTS_CURRENT_LASER_RESULT / ( input_file.name + ".json") disassembly = SolidityContract( str(input_file), solc_binary=Mythril._init_solc_binary("0.5.0")).disassembly account = Account("0x0000000000000000000000000000000000000000", disassembly) accounts = {account.address: account} laser = svm.LaserEVM(accounts, max_depth=22, transaction_count=1) laser.register_hooks(hook_type="post", hook_dict=get_detection_module_hooks()) laser.sym_exec(account.address) laser_info = _all_info(laser) output_current.write_text( json.dumps(laser_info, cls=LaserEncoder, indent=4)) if not (output_expected.read_text() == output_expected.read_text()): self.found_changed_files(input_file, output_expected, output_current) self.assert_and_show_changed_files()
def test_sym_exec(): contract = SolidityContract( str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol"), solc_binary=Mythril._init_solc_binary("0.5.0"), ) sym = SymExecWrapper(contract, address=(util.get_indexed_address(0)), strategy="dfs") issues = fire_lasers(sym) assert len(issues) != 0
def test_sym_exec(): contract = SolidityContract( str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol")) sym = SymExecWrapper( contract, address=(util.get_indexed_address(0)), strategy="dfs", execution_timeout=25, ) issues = fire_lasers(sym) assert len(issues) != 0
def load_from_solidity(self, solidity_files): """ :param solidity_files: :return: """ address = util.get_indexed_address(0) contracts = [] for file in solidity_files: if ":" in file: file, contract_name = file.split(":") else: contract_name = None file = os.path.expanduser(file) try: # import signatures from solidity source self.sigs.import_solidity_file(file, solc_binary=self.solc_binary, solc_args=self.solc_args) if contract_name is not None: contract = SolidityContract( 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( input_file=file, solc_args=self.solc_args, solc_binary=self.solc_binary, ): self.contracts.append(contract) contracts.append(contract) except FileNotFoundError: raise CriticalError("Input file not found: " + file) except CompilerError as e: raise CriticalError(e) except NoContractFoundError: log.error("The file " + file + " does not contain a compilable contract.") return address, contracts
def runTest(): """""" disassembly = SolidityContract( "./tests/native_tests.sol", solc_binary=Mythril._init_solc_binary("0.5.0") ).disassembly account = Account("0x0000000000000000000000000000000000000000", disassembly) accounts = {account.address: account} laser = svm.LaserEVM(accounts, max_depth=100, transaction_count=1) laser.sym_exec(account.address) laser_info = str(_all_info(laser)) _test_natives(laser_info, SHA256_TEST, "SHA256") _test_natives(laser_info, RIPEMD160_TEST, "RIPEMD160") _test_natives(laser_info, ECRECOVER_TEST, "ECRECOVER") _test_natives(laser_info, IDENTITY_TEST, "IDENTITY")
def AnalyseSherlockSolidity(nameContract, addressContract, locationContract): startTime = time.time() # pour calculer temps exécution accounts = {} contractAddress = addressContract contractName = nameContract contract = SolidityContract(locationContract) account = svm.Account(contractAddress, contract.disassembly) accounts = {contractAddress: account} laser = svm.LaserEVM(accounts, max_depth=maxDept, execution_timeout=executionTimeOut, create_timeout=createTimeOut, transaction_count=transactionCount) ExecutionSymbolique(laser, contractAddress, contractName, startTime)
def runTest(): """""" disassembly = SolidityContract( "./tests/native_tests.sol", solc_binary=MythrilDisassembler._init_solc_binary("0.5.3"), ).disassembly account = Account("0x0000000000000000000000000000000000000000", disassembly) world_state = WorldState() world_state.put_account(account) laser = svm.LaserEVM(max_depth=100, transaction_count=1) laser.sym_exec(world_state=world_state, target_address=account.address.value) laser_info = str(_all_info(laser)) _test_natives(laser_info, SHA256_TEST, "SHA256") _test_natives(laser_info, RIPEMD160_TEST, "RIPEMD160") _test_natives(laser_info, ECRECOVER_TEST, "ECRECOVER") _test_natives(laser_info, IDENTITY_TEST, "IDENTITY")
def test_create(): contract = SolidityContract( str(tests.TESTDATA_INPUTS_CONTRACTS / "calls.sol")) laser_evm = svm.LaserEVM({}) laser_evm.time = datetime.now() execute_contract_creation(laser_evm, contract.creation_code) resulting_final_state = laser_evm.open_states[0] for address, created_account in resulting_final_state.accounts.items(): created_account_code = created_account.code actual_code = Disassembly(contract.code) for i in range(len(created_account_code.instruction_list)): found_instruction = created_account_code.instruction_list[i] actual_instruction = actual_code.instruction_list[i] assert found_instruction["opcode"] == actual_instruction["opcode"]
def load_from_solidity( self, solidity_files: List[str]) -> Tuple[str, List[SolidityContract]]: """ :param solidity_files: List of solidity_files :return: tuple of address, contract class list """ address = util.get_indexed_address(0) contracts = [] for file in solidity_files: if ":" in file: file, contract_name = file.split(":") else: contract_name = None file = os.path.expanduser(file) try: # import signatures from solidity source self.sigs.import_solidity_file( file, solc_binary=self.solc_binary, solc_settings_json=self.solc_settings_json, ) if contract_name is not None: contract = SolidityContract( input_file=file, name=contract_name, solc_settings_json=self.solc_settings_json, solc_binary=self.solc_binary, ) self.contracts.append(contract) contracts.append(contract) else: for contract in get_contracts_from_file( input_file=file, solc_settings_json=self.solc_settings_json, solc_binary=self.solc_binary, ): self.contracts.append(contract) contracts.append(contract) except FileNotFoundError: raise CriticalError("Input file not found: " + file) except CompilerError as e: error_msg = str(e) # Check if error is related to solidity version mismatch if ("Error: Source file requires different compiler version" in error_msg): # Grab relevant line "pragma solidity <solv>...", excluding any comments solv_pragma_line = error_msg.split("\n")[-3].split("//")[0] # Grab solidity version from relevant line solv_match = re.findall(r"[0-9]+\.[0-9]+\.[0-9]+", solv_pragma_line) error_suggestion = ("<version_number>" if len(solv_match) != 1 else solv_match[0]) error_msg = ( error_msg + '\nSolidityVersionMismatch: Try adding the option "--solv ' + error_suggestion + '"\n') raise CriticalError(error_msg) except NoContractFoundError: log.error("The file " + file + " does not contain a compilable contract.") return address, contracts
def contract(self) -> EVMContract: return SolidityContract(self._file_path, solc_binary=self._solc)
# compile test contracts from pathlib import Path from mythril.solidity.soliditycontract import SolidityContract # Recompiles all the to be tested contracts root = Path(__file__).parent input = root / "input_contracts" output = root / "inputs" for contract in input.iterdir(): sol = SolidityContract(str(contract)) code = sol.code output_file = output / "{}.o".format(contract.name) output_file.write_text(code)