from mythril.ether import evm from mythril.ether.contractstorage import get_persistent_storage from mythril.disassembler.disassembly import Disassembly from mythril.rpc.client import EthJsonRpc from mythril.disassembler.callgraph import generate_callgraph import os contract_storage = get_persistent_storage() contract_keys = list(contract_storage.contracts) homestead = EthJsonRpc() # Iterate over all contracts in the database for k in contract_keys: contract = contract_storage.contracts[k] # Run each contract in the PyEthereum EVM trace to check whether DELEGATECALL is reached # To execute the fallback function, we don't provide any input data ret = evm.trace(contract.code) if 'DELEGATECALL' in ret: print("DELEGATECALL in fallback function: Contract 0x" + k.hex() + " deployed at: ") instance_list = contract_storage.instance_lists[k] for i in range(1, len(instance_list.addresses)): print("Address: " + instance_list.addresses[i] + ", balance: " + str(instance_list.balances[i])) # contract.get_xrefs() should contain the delegateCall() target (library contract) print("Referenced contracts:") xrefs = contract.get_xrefs() print ("\n".join(xrefs)) ''' from here on are many different options! In this example, we'll only check one of the refernced contracts contains the initWallet() function If it does, we save the disassembly and callgraph for further analysis ''' for xref in xrefs: code = homestead.eth_getCode(xref) disassembly = Disassembly(code) if contract.matches_expression("func#initWallet(address[],uint256,uint256)#"): print ("initWallet() in referenced library contract: " + xref) # Save list of contracts that forward calls to this library contract cwd = os.getcwd() with open("contracts_calling_" + xref + ".txt", "w") as f: addresses = contract_storage.instance_lists[k].addresses f.write("\n".join(addresses)) easm = disassembly.get_easm() with open("library_" + xref + ".easm", "w") as f: f.write(easm) generate_callgraph(disassembly, os.path.join(cwd, "library_" + xref))