如何在web3py中为合约创建的子合约创建事件过滤器
解决AttributeError: 'ContractEvents' object has no attribute 'MergeEvent'问题
这问题我之前调试合约事件时也碰到过,核心原因完全符合你的怀疑:你创建merge_contract实例时,没有传入MergeModule的ABI,导致Web3把这个实例错误识别成了Handler合约,自然找不到只在MergeModule里定义的MergeEvent事件。
下面是具体的解决步骤,帮你快速搞定:
1. 拿到MergeModule的ABI
如果你用Hardhat、Truffle这类开发框架,编译合约后会在项目目录的artifacts(Hardhat)或build/contracts(Truffle)文件夹里生成MergeModule.json文件,打开它就能找到abi字段,这就是我们需要的合约ABI。
如果没有用框架,也可以手动从Solidity代码里提取ABI,但框架生成的更准确,推荐优先用框架输出的文件。
2. 正确创建MergeModule合约实例
在你的test_handler.py测试代码里,要明确传入MergeModule的ABI来创建实例,而不是默认用Handler的ABI。举个具体的代码示例:
import json from web3 import Web3 # 加载MergeModule的ABI文件 with open("./artifacts/contracts/MergeModule.sol/MergeModule.json") as abi_file: merge_module_abi = json.load(abi_file)["abi"] # 假设你已经通过某种方式拿到了MergeModule的地址(比如从Handler合约里读取) merge_module_address = "0x..." # 替换成实际的合约地址 # 用正确的地址和ABI创建MergeModule合约实例 merge_contract = Web3.eth.contract(address=merge_module_address, abi=merge_module_abi)
3. 正常创建事件过滤器
现在实例关联了正确的合约定义,你就能顺利创建MergeEvent的过滤器了:
# 创建MergeEvent的过滤器,监听最新区块开始的事件 event_filter = merge_contract.events.MergeEvent.create_filter(fromBlock="latest") # 获取事件日志 logs = event_filter.get_all_entries() # 遍历日志处理数据 for log in logs: print(f"触发MergeEvent:{log.args}")
额外注意点
- 一定要确认
merge_module_address是Handler构造函数中实际创建的MergeModule实例地址,别填错成Handler的地址了。 - 如果是用pytest这类测试框架,可以把ABI加载的逻辑放到
setUp方法里,避免每个测试用例重复加载。
内容的提问来源于stack exchange,提问作者Paymahn Moghadasian
相关产品推荐
相关产品推荐

