You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过EthersJS获取以太坊交易所在区块的Finalized状态

使用EthersJS等待区块Finalized以确保事件不被回滚

核心逻辑

当监听到合约事件时,先记录该事件所在的区块号,等待链上的finalized区块号大于等于这个目标区块号——此时该区块已被以太坊共识层最终确认,不会发生回滚,即可安全处理后续业务逻辑。

实现步骤(基于EthersJS v6)

1. 初始化Provider与合约实例

先连接到支持finalized区块查询的以太坊节点(如Infura、Alchemy提供的RPC节点),并初始化合约实例:

const { ethers } = require("ethers");

// 替换为你的RPC节点地址
const provider = new ethers.JsonRpcProvider("https://mainnet.infura.io/v3/你的项目ID");

// 替换为你的合约ABI和地址
const contractABI = [
  // 包含你要监听的事件定义,示例:
  "event YourEvent(address indexed sender, uint256 value)"
];
const contractAddress = "0x1234567890abcdef1234567890abcdef12345678";

const contract = new ethers.Contract(contractAddress, contractABI, provider);

2. 监听目标事件并触发等待逻辑

监听合约的目标事件,收到事件后立即启动等待区块finalized的流程:

// 监听目标事件
contract.on("YourEvent", async (sender, value, event) => {
  const eventBlockNum = event.blockNumber;
  console.log(`捕获事件,所在区块:${eventBlockNum}`);

  // 等待区块被finalized
  await waitForFinalizedBlock(eventBlockNum);

  // 区块确认后的业务逻辑
  console.log(`区块 ${eventBlockNum} 已Finalized,开始处理业务`);
  // 这里写入你的业务代码:更新数据库、发送通知等
});

3. 实现等待Finalized区块的函数

推荐使用监听finalized区块事件的方式,避免无效轮询:

async function waitForFinalizedBlock(targetBlockNum) {
  return new Promise(async (resolve) => {
    // 先检查当前已finalized的区块是否满足要求
    const currentFinalizedBlock = await provider.getBlock("finalized");
    if (currentFinalizedBlock.number >= targetBlockNum) {
      resolve();
      return;
    }

    // 监听后续finalized区块,满足条件后移除监听并返回
    const listener = provider.on("finalized", (block) => {
      if (block.number >= targetBlockNum) {
        provider.off("finalized", listener);
        resolve();
      }
    });
  });
}

兼容EthersJS v5的实现

如果使用v5版本,调整Provider初始化和监听逻辑即可:

// v5初始化Provider
const provider = new ethers.providers.JsonRpcProvider("你的RPC地址");

// 等待finalized区块的函数(v5)
async function waitForFinalizedBlock(targetBlockNum) {
  return new Promise(async (resolve) => {
    const currentFinalizedBlock = await provider.getBlock("finalized");
    if (currentFinalizedBlock.number >= targetBlockNum) {
      resolve();
      return;
    }

    // v5监听区块事件,间接判断finalized状态
    const listener = provider.on("block", async (blockNum) => {
      const finalizedBlock = await provider.getBlock("finalized");
      if (finalizedBlock.number >= targetBlockNum) {
        provider.off("block", listener);
        resolve();
      }
    });
  });
}

注意事项

  • 确保你的RPC节点支持finalized区块查询:只有以太坊合并后的网络(主网、Sepolia、Goerli等)才有finalized状态,旧测试网如Ropsten已废弃,不支持。
  • 异常处理:建议在代码中添加try-catch块,处理节点连接失败、查询超时等异常,避免业务流程阻塞。
  • 轮询备选方案:如果需要自定义查询间隔,也可以用定时轮询替代事件监听,比如每10秒查询一次finalized区块状态。

内容的提问来源于stack exchange,提问作者Remi_la

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 16:10:25