diff --git a/mev_inspect/block.py b/mev_inspect/block.py index 74c4f1e..44e1ee3 100644 --- a/mev_inspect/block.py +++ b/mev_inspect/block.py @@ -11,6 +11,7 @@ from mev_inspect.schemas.blocks import Block from mev_inspect.schemas.receipts import Receipt from mev_inspect.schemas.traces import Trace, TraceType from mev_inspect.schemas.swaps import Swap +from mev_inspect.schemas.liquidations import Liquidation from mev_inspect.utils import hex_to_int @@ -47,18 +48,25 @@ def _logs_by_tx(logs): logs_by_tx[transaction_hash] = [log] return logs_by_tx -def get_amounts(data): +def get_swap(data): data = data[2:] # print(data) return int(data[0:64], base=16), int(data[64:128], base=16), int(data[128:192], base=16), int(data[192:256], base=16) +def get_liquidation(data): + data = data[2:] + # print(data) + return int(data[0:64], base=16), int(data[64:128], base=16), "0x"+data[128+24:168+24] + univ2abi = ''' [{"inputs":[],"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":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1Out","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint112","name":"reserve0","type":"uint112"},{"indexed":false,"internalType":"uint112","name":"reserve1","type":"uint112"}],"name":"Sync","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":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINIMUM_LIQUIDITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"burn","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint112","name":"_reserve0","type":"uint112"},{"internalType":"uint112","name":"_reserve1","type":"uint112"},{"internalType":"uint32","name":"_blockTimestampLast","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"kLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"price0CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price1CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"skim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0Out","type":"uint256"},{"internalType":"uint256","name":"amount1Out","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}] ''' async def classify_logs(logs, reserves, w3): cswaps = [] + cliquidations = [] topic_swap = "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822" + topic_liquidation = "0xe413a321e8681d831f4dbccbca790d2952b56f977908e45be37335533e005286" for log in logs: if log['topics'][0] == topic_swap: # print(log) @@ -69,13 +77,15 @@ async def classify_logs(logs, reserves, w3): token0, token1 = reserves[pool_address] else: addr = Web3.toChecksumAddress(pool_address) - token0 = await w3.eth.call({'to': addr, 'data': '0x0dfe1681'}) - token1 = await w3.eth.call({'to': addr, 'data': '0xd21220a7'}) + token0, token1 = await asyncio.gather( + w3.eth.call({'to': addr, 'data': '0x0dfe1681'}), + w3.eth.call({'to': addr, 'data': '0xd21220a7'}) + ) token0 = w3.toHex(token0) token1 = w3.toHex(token1) reserves[pool_address] = (token0, token1) - am0in, am1in, am0out, am1out = get_amounts(log['data']) + am0in, am1in, am0out, am1out = get_swap(log['data']) swap = Swap( abi_name="uniswap_v2", transaction_hash=transaction_hash, @@ -92,21 +102,39 @@ async def classify_logs(logs, reserves, w3): error=None ) cswaps.append(swap) + elif log['topics'][0] == topic_liquidation: + block = str(int(log['blockNumber'], 16)) + am_debt, am_recv, addr_usr = get_liquidation(log['data']) + liquidation = Liquidation( + liquidated_user = "0x"+log['topics'][3][26:], + liquidator_user = addr_usr, + debt_token_address = "0x"+log['topics'][2][26:], + debt_purchase_amount = am_debt, + received_amount = am_recv, + received_token_address = "0x"+log['topics'][1][26:], + protocol = None, + transaction_hash = log['transactionHash'], + trace_address = [int(log['logIndex'], 16)], + block_number = block, + error = None + ) + cliquidations.append(liquidation) - return cswaps + return cswaps, cliquidations + +reserves: Dict[str, Tuple[str, str]] = dict() async def get_classified_traces_from_events(w3: Web3, after_block: int, before_block: int): base_provider = w3.provider start = after_block stride = 300 - reserves: Dict[str, Tuple[str, str]] = dict() while start < before_block: begin = start end = start + stride if (start + stride) < before_block else before_block-1 start += stride print("fetching from node...", begin, end, flush=True) - swaplogs = await _get_logs_for_topics(base_provider, begin, end, ["0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822"]) - logs_by_tx = _logs_by_tx(swaplogs) + all_logs = await _get_logs_for_topics(base_provider, begin, end, [["0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822","0xe413a321e8681d831f4dbccbca790d2952b56f977908e45be37335533e005286"]]) + logs_by_tx = _logs_by_tx(all_logs) for tx in logs_by_tx.keys(): yield await classify_logs(logs_by_tx[tx], reserves, w3) diff --git a/mev_inspect/inspect_block.py b/mev_inspect/inspect_block.py index 59aea5c..a4b2895 100644 --- a/mev_inspect/inspect_block.py +++ b/mev_inspect/inspect_block.py @@ -88,7 +88,7 @@ async def inspect_many_blocks( count = 0 arbitrages_payload = [] - async for swaps in get_classified_traces_from_events(w3, after_block_number, before_block_number): + async for swaps, liquidations in get_classified_traces_from_events(w3, after_block_number, before_block_number): arbitrages = get_arbitrages(swaps) @@ -112,6 +112,9 @@ async def inspect_many_blocks( arbitrages_payload = [] count = 0 + if len(liquidations) > 0: + print(liquidations) + # all_blocks: List[Block] = [] # all_classified_traces: List[ClassifiedTrace] = [] # all_transfers: List[Transfer] = [] diff --git a/mev_inspect/inspector.py b/mev_inspect/inspector.py index 7878527..e3bb9c0 100644 --- a/mev_inspect/inspector.py +++ b/mev_inspect/inspector.py @@ -67,7 +67,7 @@ class MEVInspector: trace_db_session: Optional[orm.Session], after_block: int, before_block: int, - block_batch_size: int = 10, + block_batch_size: int = 300, ): tasks = [] for block_number in range(after_block, before_block, block_batch_size): diff --git a/mev_inspect/schemas/liquidations.py b/mev_inspect/schemas/liquidations.py index 8ef4faa..10b667d 100644 --- a/mev_inspect/schemas/liquidations.py +++ b/mev_inspect/schemas/liquidations.py @@ -12,7 +12,7 @@ class Liquidation(BaseModel): debt_purchase_amount: int received_amount: int received_token_address: Optional[str] - protocol: Protocol + protocol: Optional[Protocol] transaction_hash: str trace_address: List[int] block_number: str