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

使用Hardhat+Chai测试Solidity众筹合约提款功能时余额断言失败

众筹Solidity合约测试用例问题

我编写了一个众筹Solidity合约,在最后一个测试用例中遇到问题:

it("should allow the owner of the campaign to withdraw funds if the campaign is successful", async () => {
    const target = ethers.utils.parseEther("1");
    await contract
      .connect(aliceAccount)
      .createCampaign(
        "Test Campaign",
        "Test Description",
        target,
        "testimage.jpg"
      );
    await contract
      .connect(bobAccount)
      .donateToCampaign(0, { value: ethers.utils.parseEther("1") });
  
    const campaign = await contract.campaigns(0);
    const ownerInitialBalance = await aliceAccount.getBalance();
    const tx = await contract.connect(aliceAccount).withdrawFunds(0);
    const receipt = await tx.wait()
   const ownerFinalBalance = await aliceAccount.getBalance();
    
    const result = ownerInitialBalance.add(target).sub(receipt.gasUsed)
   
    expect(campaign.status).to.equal(2);
    expect(ownerFinalBalance).to.equal(result);
   
  });

控制台输出错误:

AssertionError: expected 10000997823969736606208 to equal 10000997858212031010378. The numerical values of the given "ethers.BigNumber" and "ethers.BigNumber" inputs were compared, and they differed.
      + expected - actual

      -10000997823969736606208
      +10000997858212031010378

问题原因

你对gas消耗的计算逻辑错误:receipt.gasUsed只是交易消耗的gas数量,但账户实际被扣的是gas数量 × gas单价(即gasUsed × effectiveGasPrice),你只减去了gas数量,没有乘以单价,导致计算出的预期余额和实际余额出现差值。

另外还有个逻辑瑕疵:你在执行提现交易前就获取了campaign的状态,此时拿到的是交易前的旧状态,虽然这个测试里status的断言可能碰巧通过,但不符合测试逻辑,应该在交易完成后再获取最新状态。

修正方案

  1. 修正gas消耗的计算方式:
// 计算实际消耗的gas费用:gas数量 × 实际gas单价
const gasCost = receipt.gasUsed.mul(receipt.effectiveGasPrice);
const result = ownerInitialBalance.add(target).sub(gasCost);
  1. 调整campaign状态的获取时机:
// 先执行提现交易并等待确认
const tx = await contract.connect(aliceAccount).withdrawFunds(0);
const receipt = await tx.wait()
// 再获取最新的campaign状态
const campaign = await contract.campaigns(0);

修正后的完整测试代码:

it("should allow the owner of the campaign to withdraw funds if the campaign is successful", async () => {
    const target = ethers.utils.parseEther("1");
    await contract
      .connect(aliceAccount)
      .createCampaign(
        "Test Campaign",
        "Test Description",
        target,
        "testimage.jpg"
      );
    await contract
      .connect(bobAccount)
      .donateToCampaign(0, { value: ethers.utils.parseEther("1") });
  
    const ownerInitialBalance = await aliceAccount.getBalance();
    const tx = await contract.connect(aliceAccount).withdrawFunds(0);
    const receipt = await tx.wait()
    // 交易完成后再获取campaign状态
    const campaign = await contract.campaigns(0);
    const ownerFinalBalance = await aliceAccount.getBalance();
    
    // 计算实际gas费用
    const gasCost = receipt.gasUsed.mul(receipt.effectiveGasPrice);
    const result = ownerInitialBalance.add(target).sub(gasCost)
   
    expect(campaign.status).to.equal(2);
    expect(ownerFinalBalance).to.equal(result);
   
  });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 23:30:43