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

Solidity合约PaymentDone事件未触发或Node.js服务未接收问题

问题排查与解决方案

一、确认合约事件是否真的触发

  1. 检查授权是否完成
    transferFrom 调用要求用户先通过DAI合约的 approve 方法授权PaymentProcessor合约转移指定金额的代币。如果未授权,transferFrom 会执行失败,交易回滚,事件不会触发。

    • 测试方法:在Truffle控制台执行以下命令(替换对应地址和金额):
      const dai = await IERC20.at("你的DAI合约地址");
      const pp = await PaymentProcessor.at("你的PaymentProcessor合约地址");
      await dai.approve(pp.address, ethers.utils.parseEther("1"), {from: "你的测试账户地址"});
      await pp.pay(ethers.utils.parseEther("1"), 123, {from: "你的测试账户地址"});
      
    • 执行后查看控制台是否输出 PaymentDone 事件,或在Ganache的交易详情中查看日志是否存在该事件。
  2. 检查合约核心逻辑是否正常执行

    • 确认构造函数传入的 daiAddress 是正确的DAI合约地址(本地部署或测试网地址),若地址错误,transferFrom 会失败导致交易回滚。
    • 确认 admin 地址不为零地址,避免无意义的代币转移失败。

二、修复Node.js监听服务的问题

  1. 验证合约地址与ABI正确性

    • 确保 PaymentProcessor 变量正确导入了Truffle编译后的合约文件:
      const PaymentProcessor = require('./build/contracts/PaymentProcessor.json');
      
    • 核对 PaymentProcessor.networks[5777].address 是否与部署后的合约地址一致(可在Truffle部署日志或Ganache中查看)。
    • 检查ABI中是否包含 PaymentDone 事件的定义,可直接从编译后的JSON文件中复制ABI字段。
  2. 修正Provider与Ethers版本兼容问题

    • 若使用Ethers v6,Provider的创建方式需改为:
      const provider = new ethers.JsonRpcProvider("http://localhost:9545");
      
    • 确保package.json中的ethers版本与代码写法匹配,避免API差异导致连接失败。
  3. 添加错误监听与调试

    • 在监听代码中增加错误捕获,排查潜在问题:
      paymentProcessor.on('error', (error) => {
        console.error('事件监听错误:', error);
      });
      
    • 尝试查询历史事件,确认事件是否已上链:
      const events = await paymentProcessor.queryFilter('PaymentDone', 0, 'latest');
      console.log('历史事件:', events);
      
      如果能查询到事件,说明实时监听逻辑存在问题;若查不到,则合约未触发事件。
  4. 确保Ganache服务正常运行

    • 确认本地Ganache节点在 http://localhost:9545 端口正常运行,无其他进程占用该端口。
    • 重启Ganache和Node.js服务,避免连接缓存问题。

三、优化监听代码示例

修改后的监听代码(包含错误处理与历史事件查询):

const ethers = require('ethers');
const PaymentProcessor = require('./build/contracts/PaymentProcessor.json');
const Payment = require('./models/Payment'); // 假设你的Payment模型路径

const listenToEvent = async () => {
    console.log("启动事件监听...");
    try {
        const provider = new ethers.providers.JsonRpcProvider("http://localhost:9545"); // Ethers v5写法,v6请改为new ethers.JsonRpcProvider
        const networkId = "5777";

        const contractAddress = PaymentProcessor.networks[networkId]?.address;
        if (!contractAddress) {
            throw new Error("未找到对应网络的合约地址");
        }

        const paymentProcessor = new ethers.Contract(
            contractAddress,
            PaymentProcessor.abi,
            provider
        );

        // 查询历史事件用于调试
        const historicalEvents = await paymentProcessor.queryFilter('PaymentDone', 0, 'latest');
        console.log("已上链的历史事件数量:", historicalEvents.length);

        // 监听实时事件
        paymentProcessor.on('PaymentDone', async (payer, amount, paymentId, date) => {
            console.log("\n收到PaymentDone事件:");
            console.log(`
                付款人: ${payer} 
                金额: ${ethers.utils.formatEther(amount)} DAI
                付款ID: ${paymentId} 
                时间: ${(new Date(date.toNumber() * 1000)).toLocaleString()}
            `);

            try {
                const payment = await Payment.findOne({id: paymentId.toNumber()}); // 注意将BigNumber转为数字
                if(payment) {
                    payment.paymentDone = true;
                    await payment.save();
                    console.log("数据库更新成功");
                } else {
                    console.log("未找到对应付款记录");
                }
            } catch (dbError) {
                console.error("数据库操作错误:", dbError);
            }
        });

        paymentProcessor.on('error', (error) => {
            console.error("事件监听异常:", error);
        });

        console.log("事件监听已启动");
    } catch (initError) {
        console.error("监听服务初始化失败:", initError);
    }
}

listenToEvent();

注意:代码中 paymentId 是Solidity的uint类型,在ethers中会转为BigNumber,需要用 toNumber() 转换后再查询数据库(若数据库字段为数字类型)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 14:07:50