diff --git a/mev_inspect/abis/ERC20.json b/mev_inspect/abis/ERC20.json new file mode 100644 index 0000000..1295df2 --- /dev/null +++ b/mev_inspect/abis/ERC20.json @@ -0,0 +1,2 @@ + +[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}] diff --git a/mev_inspect/processor.py b/mev_inspect/processor.py index b9fa72f..74e1aeb 100644 --- a/mev_inspect/processor.py +++ b/mev_inspect/processor.py @@ -58,15 +58,20 @@ class Processor: call_data = decoder.decode(trace.action["input"]) if call_data is not None: + signature = call_data.function_signature + classification = spec.classifications.get( + signature, Classification.unknown + ) + return ClassifiedTrace( transaction_hash=trace.transaction_hash, block_number=trace.block_number, trace_type=trace.type, trace_address=trace.trace_address, - classification=Classification.unknown, + classification=classification, protocol=spec.protocol, function_name=call_data.function_name, - function_signature=call_data.function_signature, + function_signature=signature, intputs=call_data.inputs, ) diff --git a/mev_inspect/schemas/classifications.py b/mev_inspect/schemas/classifications.py index 6b5d4d4..cd94c69 100644 --- a/mev_inspect/schemas/classifications.py +++ b/mev_inspect/schemas/classifications.py @@ -9,6 +9,8 @@ from .blocks import TraceType class Classification(Enum): unknown = "unknown" swap = "swap" + burn = "burn" + transfer = "transfer" class Protocol(Enum): @@ -32,3 +34,4 @@ class DecodeSpec(BaseModel): abi_name: str protocol: Optional[Protocol] = None valid_contract_addresses: Optional[List[str]] = None + classifications: Dict[str, Classification] = {} diff --git a/testing_file.py b/testing_file.py index c3f773f..b5f73b1 100644 --- a/testing_file.py +++ b/testing_file.py @@ -5,7 +5,7 @@ from web3 import Web3 from mev_inspect import block from mev_inspect.processor import Processor -from mev_inspect.schemas.classifications import DecodeSpec, Protocol +from mev_inspect.schemas.classifications import Classification, DecodeSpec, Protocol SUSHISWAP_ROUTER_ADDRESS = "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F" @@ -23,7 +23,20 @@ DECODE_SPECS = [ protocol=Protocol.sushiswap, valid_contract_addresses=[SUSHISWAP_ROUTER_ADDRESS], ), - DecodeSpec(abi_name="UniswapV2Pair"), + DecodeSpec( + abi_name="ERC20", + classifications={ + "transferFrom(address,address,uint256)": Classification.transfer, + "transfer(address,uint256)": Classification.transfer, + "burn(address)": Classification.burn, + }, + ), + DecodeSpec( + abi_name="UniswapV2Pair", + classifications={ + "swap(uint256,uint256,address,bytes)": Classification.swap, + }, + ), ] @@ -41,19 +54,22 @@ def inspect_block(base_provider, block_number): print(f"Total transactions: {total_transactions}") processor = Processor(DECODE_SPECS) - classifications = processor.process(block_data) + classified_traces = processor.process(block_data) - print(f"Returned {len(classifications)} classifications") + print(f"Returned {len(classified_traces)} classified traces") stats = {} - for classification in classifications: - protocol = classification.protocol - signature = classification.function_signature + for trace in classified_traces: + protocol = trace.protocol + classification = trace.classification.value + signature = trace.function_signature protocol_stats = stats.get(protocol, {}) + class_stats = protocol_stats.get(classification, {}) signature_count = protocol_stats.get(signature, 0) - protocol_stats[signature] = signature_count + 1 + class_stats[signature] = signature_count + 1 + protocol_stats[classification] = class_stats stats[protocol] = protocol_stats print(json.dumps(dict(stats.items()), indent=4))