diff --git a/src/decoding/evm.py b/src/decoding/evm.py index afc21e1..4cd7f98 100644 --- a/src/decoding/evm.py +++ b/src/decoding/evm.py @@ -8,8 +8,42 @@ from src.core.abis import CONTROLLER_ABI, MARKET_ABI logger = logging.getLogger(__name__) +# Vault Factory & User Vault Events ABI +VAULT_EVENTS_ABI = [ + { + "anonymous": False, + "inputs": [ + {"indexed": True, "name": "user", "type": "address"}, + {"indexed": True, "name": "vault", "type": "address"}, + {"indexed": False, "name": "vaultIndex", "type": "uint256"} + ], + "name": "VaultCreated", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + {"indexed": True, "name": "token", "type": "address"}, + {"indexed": True, "name": "from", "type": "address"}, + {"indexed": False, "name": "amount", "type": "uint256"} + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": False, + "inputs": [ + {"indexed": True, "name": "token", "type": "address"}, + {"indexed": True, "name": "to", "type": "address"}, + {"indexed": False, "name": "amount", "type": "uint256"} + ], + "name": "Withdrawn", + "type": "event" + } +] + class EVMDecoder: - """EVM ABI 日志规范化解码器 (Layer 2: Decoding)""" + """EVM ABI 日志规范化解码器 (包含 Controller, Market 与 User Vault)""" def __init__(self, chain_id: int): self.chain_id = chain_id @@ -19,8 +53,7 @@ class EVMDecoder: def _build_topic_maps(self): self.event_abi_map = {} - # 解析 Controller 与 Market ABI 中的 events - for abi in CONTROLLER_ABI + MARKET_ABI: + for abi in CONTROLLER_ABI + MARKET_ABI + VAULT_EVENTS_ABI: if abi.get("type") == "event": name = abi.get("name") inputs = abi.get("inputs", []) @@ -30,7 +63,6 @@ class EVMDecoder: self.event_abi_map[topic0] = abi def decode_log(self, log: Dict[str, Any], block_timestamp: int = 0) -> Optional[NormalizedEvent]: - """将原始 EVM 日志解析为统一的 NormalizedEvent""" topics = log.get("topics", []) if not topics: return None @@ -46,19 +78,16 @@ class EVMDecoder: block_number = log.get("blockNumber", 0) log_index = log.get("logIndex", 0) - # 解码 Indexed 参数与 Non-Indexed Data payload: Dict[str, Any] = {} indexed_inputs = [i for i in abi.get("inputs", []) if i.get("indexed")] non_indexed_inputs = [i for i in abi.get("inputs", []) if not i.get("indexed")] - # 1. Indexed topics for idx, inp in enumerate(indexed_inputs): if idx + 1 < len(topics): raw_topic = topics[idx + 1] t_hex = raw_topic.hex() if isinstance(raw_topic, bytes) else raw_topic payload[inp["name"]] = t_hex - # 2. Non-indexed data data = log.get("data", "0x") if isinstance(data, str) and data.startswith("0x"): data_bytes = bytes.fromhex(data[2:]) @@ -79,7 +108,6 @@ class EVMDecoder: except Exception as e: logger.error(f"Failed to decode non-indexed data for {event_name}: {e}") - # 标准化 Event Type type_mapping = { "DeployMarket": "MARKET_DEPLOYED", "SetOutcome": "OUTCOME_RESOLVED", @@ -87,12 +115,9 @@ class EVMDecoder: "Mint": "ORDER_MINT", "Redeem": "ORDER_REDEEM", "Claim": "POSITION_CLAIMED", - "SetProtocolFeeRate": "GOV_FEE_RATE_UPDATED", - "SetTreasury": "GOV_TREASURY_UPDATED", - "SetCentralWallet": "GOV_CENTRAL_WALLET_UPDATED", - "SetCreatorShare": "GOV_CREATOR_SHARE_UPDATED", - "Paused": "PROTOCOL_PAUSED", - "Unpaused": "PROTOCOL_UNPAUSED", + "VaultCreated": "VAULT_CREATED", + "Deposited": "VAULT_DEPOSITED", + "Withdrawn": "VAULT_WITHDRAWN" } normalized_type = type_mapping.get(event_name, f"EVM_{event_name.upper()}")