|
| 1 | +#!/usr/bin/env python3 |
| 2 | + |
| 3 | +# Usage: |
| 4 | +# |
| 5 | +# ``` |
| 6 | +# pip3 install -r script/requirements.txt |
| 7 | +# |
| 8 | +# python3 ./script/traverse_batch.py --rpc https://l1rpc.internal.taiko.xyz --contract 0xbE71D121291517c85Ab4d3ac65d70F6b1FD57118 --from-block 12700 --to-block 81670 |
| 9 | +# ``` |
| 10 | + |
| 11 | +import argparse |
| 12 | +from web3 import Web3 |
| 13 | +from typing import Dict, Any |
| 14 | +import json |
| 15 | +from datetime import datetime |
| 16 | + |
| 17 | +# Load ABI from JSON file |
| 18 | +with open('script/ITaikoInbox.json', 'r') as f: |
| 19 | + contract_json = json.load(f) |
| 20 | + # Find the BatchProposed event in the ABI |
| 21 | + BATCH_PROPOSED_ABI = next(item for item in contract_json['abi'] if item['type'] == 'event' and item['name'] == 'BatchProposed') |
| 22 | + |
| 23 | +def setup_web3(rpc_url: str) -> Web3: |
| 24 | + """Setup Web3 connection.""" |
| 25 | + w3 = Web3(Web3.HTTPProvider(rpc_url)) |
| 26 | + if not w3.is_connected(): |
| 27 | + raise ConnectionError("Failed to connect to the RPC endpoint") |
| 28 | + return w3 |
| 29 | + |
| 30 | +def traverse_batches(w3: Web3, contract_address: str, block_from: int, block_to: int) -> None: |
| 31 | + """Traverse blocks and find BatchProposed events.""" |
| 32 | + contract = w3.eth.contract(address=contract_address, abi=[BATCH_PROPOSED_ABI]) |
| 33 | + |
| 34 | + # Process blocks in pages of 50 |
| 35 | + page_size = 50 |
| 36 | + current_from = block_from |
| 37 | + |
| 38 | + while current_from <= block_to: |
| 39 | + current_to = min(current_from + page_size - 1, block_to) |
| 40 | + |
| 41 | + try: |
| 42 | + # Get all events in the current page |
| 43 | + logs = w3.eth.get_logs({ |
| 44 | + 'address': contract_address, |
| 45 | + # Hint: copy from explorer |
| 46 | + 'topics': ["0x9eb7fc80523943f28950bbb71ed6d584effe3e1e02ca4ddc8c86e5ee1558c096"], |
| 47 | + 'fromBlock': current_from, |
| 48 | + 'toBlock': current_to |
| 49 | + }) |
| 50 | + |
| 51 | + for log in logs: |
| 52 | + try: |
| 53 | + # Decode the event data |
| 54 | + event = contract.events.BatchProposed().process_log(log) |
| 55 | + batch_id = event['args']['meta']['batchId'] |
| 56 | + l1_block_number = event['blockNumber'] |
| 57 | + print(f'{batch_id}:{l1_block_number},', end='') |
| 58 | + except Exception as e: |
| 59 | + print(f"Error processing log: {str(e)}") |
| 60 | + continue |
| 61 | + |
| 62 | + except Exception as e: |
| 63 | + print(f"Error getting logs for blocks {current_from}-{current_to}: {str(e)}") |
| 64 | + |
| 65 | + # Move to next page |
| 66 | + current_from = current_to + 1 |
| 67 | + |
| 68 | +def main(): |
| 69 | + parser = argparse.ArgumentParser(description='Traverse chain and find BatchProposed events') |
| 70 | + parser.add_argument('--rpc', required=True, help='RPC URL of the target chain') |
| 71 | + parser.add_argument('--contract', required=True, help='Contract address of TaikoInbox') |
| 72 | + parser.add_argument('--from-block', type=int, required=True, help='Starting block number') |
| 73 | + parser.add_argument('--to-block', type=int, required=True, help='Ending block number') |
| 74 | + |
| 75 | + args = parser.parse_args() |
| 76 | + |
| 77 | + w3 = setup_web3(args.rpc) |
| 78 | + traverse_batches(w3, args.contract, args.from_block, args.to_block) |
| 79 | + |
| 80 | +if __name__ == "__main__": |
| 81 | + main() |
0 commit comments