如何使用web3.py根据给定合约地址查询合约创建区块号?
web3.py 查询合约创建区块号实现方案
完全可以通过web3.py实现传入合约地址返回对应创建区块号的需求,核心逻辑是定位到生成该合约的部署交易,交易所在的区块就是合约创建区块,以下是三种可落地的实现方案:
方案1:区块遍历法(无特殊节点要求,通用型最强)
该方案不依赖节点的特殊接口,只要节点支持基础的区块、交易回执查询即可使用,适配所有标准EVM链RPC。
- 实现逻辑:从区块范围中逐块拉取交易回执,判断回执中记录的创建合约地址是否和目标地址匹配,匹配成功后直接返回对应区块号。默认从最新区块倒序遍历,适配大部分合约部署时间距当前较近的场景,查询效率更高。
- 参考实现代码:
from web3 import Web3 from typing import Optional # 初始化web3实例,替换为自己使用的RPC节点地址 w3 = Web3(Web3.HTTPProvider("替换为你的RPC节点连接地址")) def query_contract_creation_block( contract_address: str, start_block: Optional[int] = None, end_block: Optional[int] = None, query_batch: int = 500 ) -> int: """ 传入合约地址查询对应创建区块号 :param contract_address: 待查询的已部署合约地址 :param start_block: 遍历起始区块,传空则默认从创世块开始 :param end_block: 遍历结束区块,传空则默认取当前链最新区块 :param query_batch: 单批遍历的区块数量,根据RPC限流规则调整 """ target_addr = Web3.to_checksum_address(contract_address) if not end_block: end_block = w3.eth.block_number if not start_block: start_block = 0 current_cursor = end_block while current_cursor >= start_block: batch_start = max(start_block, current_cursor - query_batch + 1) # 倒序遍历当前批次区块 for block_num in range(current_cursor, batch_start - 1, -1): block_data = w3.eth.get_block(block_num, full_transactions=False) for tx_hash in block_data.transactions: tx_receipt = w3.eth.get_transaction_receipt(tx_hash) # 仅合约部署交易的回执会携带contractAddress字段 if tx_receipt.contractAddress and tx_receipt.contractAddress == target_addr: return block_num current_cursor = batch_start - 1 raise ValueError(f"链上未找到地址 {contract_address} 对应的合约部署记录") # 调用示例 if __name__ == "__main__": test_contract = "0x替换为你要查询的合约地址" creation_block = query_contract_creation_block(test_contract) print(f"目标合约创建区块号:{creation_block}")
- 注意事项:
- 如果已知合约的大致部署时间,可以手动缩小
start_block和end_block的范围,能大幅缩短查询时间 - 公共RPC一般有请求频率限制,遇到限流可以调小
query_batch参数,在请求之间加适当间隔 - 裁剪过历史数据的全节点可能无法查询到早于数据裁剪点的合约记录,查询早期合约建议使用归档节点
- 如果已知合约的大致部署时间,可以手动缩小
方案2:Trace接口查询法(查询效率最高,需节点支持)
如果使用的节点开启了Trace相关API(Erigon、OpenEthereum、开了debug模块的Geth都支持),可以直接通过trace过滤合约创建行为,不需要逐块遍历,查询速度可以达到毫秒级。
- 参考实现代码:
def query_creation_block_by_trace(contract_address: str) -> int: target_addr = Web3.to_checksum_address(contract_address) # 调用trace_filter接口过滤所有创建目标合约的trace记录 resp = w3.provider.make_request( "trace_filter", [ { "type": ["create"], "toAddress": [target_addr] } ] ) trace_result = resp.get("result", []) if not trace_result: raise ValueError(f"未找到地址 {contract_address} 对应的合约创建trace") return trace_result[0]["blockNumber"]
- 注意事项:大部分公共RPC默认不开放Trace接口,该方案更适合自有节点场景使用。
方案3:第三方索引服务查询(接入成本最低)
如果不想自行维护节点、也不想做遍历逻辑,可以直接调用链上索引服务(比如各链区块链浏览器开放的公开API),传入合约地址即可直接返回创建区块等元信息,不需要同步链上数据,接入成本最低。
提示:该方案依赖第三方服务的数据准确性,业务场景对数据可信度要求高的话,建议优先选择前两种方案。
内容的提问来源于stack exchange,提问作者Kavita Joshi
相关产品推荐
相关产品推荐

