mirror of https://github.com/ConsenSys/mythril
parent
a7be75d260
commit
53abd900fd
@ -0,0 +1,81 @@ |
|||||||
|
from rpc.client import EthJsonRpc |
||||||
|
from ethcontract import ETHContract |
||||||
|
from tinydb import TinyDB, Query |
||||||
|
import codecs |
||||||
|
import hashlib |
||||||
|
|
||||||
|
|
||||||
|
class ContractStorage: |
||||||
|
|
||||||
|
def __init__(self): |
||||||
|
self.db = TinyDB('./contracts.json') |
||||||
|
|
||||||
|
|
||||||
|
def initialize(self, rpchost, rpcport): |
||||||
|
|
||||||
|
eth = EthJsonRpc(rpchost, rpcport) |
||||||
|
|
||||||
|
blockNum = eth.eth_blockNumber() |
||||||
|
|
||||||
|
while(blockNum > 0): |
||||||
|
|
||||||
|
if not blockNum % 1000: |
||||||
|
print("Processing block: " + str(blockNum)) |
||||||
|
|
||||||
|
block = eth.eth_getBlockByNumber(blockNum) |
||||||
|
|
||||||
|
for tx in block['transactions']: |
||||||
|
|
||||||
|
if not tx['to']: |
||||||
|
|
||||||
|
receipt = eth.eth_getTransactionReceipt(tx['hash']) |
||||||
|
|
||||||
|
contract_address = receipt['contractAddress'] |
||||||
|
|
||||||
|
contract_code = eth.eth_getCode(contract_address) |
||||||
|
|
||||||
|
m = hashlib.md5() |
||||||
|
|
||||||
|
m.update(contract_code.encode('UTF-8')) |
||||||
|
|
||||||
|
contract_hash = codecs.encode(m.digest(), 'hex_codec') |
||||||
|
contract_id = contract_hash.decode("utf-8") |
||||||
|
|
||||||
|
contract_balance = eth.eth_getBalance(contract_address) |
||||||
|
|
||||||
|
Contract = Query() |
||||||
|
|
||||||
|
new_instance = {'address': contract_address, 'balance': contract_balance} |
||||||
|
|
||||||
|
s = self.db.search(Contract.id == contract_id) |
||||||
|
|
||||||
|
if not len(s): |
||||||
|
|
||||||
|
self.db.insert({'id': contract_id, 'code': contract_code, 'instances': [new_instance]}) |
||||||
|
|
||||||
|
else: |
||||||
|
|
||||||
|
instances = s[0]['instances'] |
||||||
|
|
||||||
|
instances.append(new_instance) |
||||||
|
|
||||||
|
self.db.update({'instances': instances}, Contract.id == contract_id) |
||||||
|
|
||||||
|
blockNum -= 1 |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def search(self, expression): |
||||||
|
|
||||||
|
all_contracts = self.db.all() |
||||||
|
|
||||||
|
for c in all_contracts: |
||||||
|
|
||||||
|
for instance in c['instances']: |
||||||
|
|
||||||
|
if ('balance' in instance): |
||||||
|
contract = ETHContract(c['code'], instance['balance']) |
||||||
|
|
||||||
|
if (contract.matches_expression(expression)): |
||||||
|
print("Found contract:" + instance['address']) |
||||||
|
|
@ -0,0 +1,38 @@ |
|||||||
|
from ether import asm, util |
||||||
|
import re |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ETHContract: |
||||||
|
|
||||||
|
def __init__(self, code = "", balance = 0): |
||||||
|
|
||||||
|
self.easm_code = asm.disassembly_to_easm(asm.disassemble(util.safe_decode(code))) |
||||||
|
self.balance = balance |
||||||
|
|
||||||
|
def matches_expression(self, expression): |
||||||
|
|
||||||
|
str_eval = "" |
||||||
|
|
||||||
|
tokens = re.split("( and | or )", expression, re.IGNORECASE) |
||||||
|
|
||||||
|
for token in tokens: |
||||||
|
|
||||||
|
if token == " and " or token == " or ": |
||||||
|
str_eval += token |
||||||
|
continue |
||||||
|
|
||||||
|
m = re.match(r'^code\(([a-zA-Z0-9\s,]+)\)$', token) |
||||||
|
|
||||||
|
if (m): |
||||||
|
code = m.group(1).replace(",", "\\n") |
||||||
|
str_eval += "\"" + code + "\" in self.easm_code" |
||||||
|
continue |
||||||
|
|
||||||
|
m = re.match(r'^balance\s*[=><]+\s*\d+$', token) |
||||||
|
if (m): |
||||||
|
str_eval += "self." + m.group(0) |
||||||
|
continue |
||||||
|
|
||||||
|
return eval(str_eval) |
||||||
|
|
Loading…
Reference in new issue