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

多账户发起交易时出现from地址不匹配错误的排查求助

问题:Hardhat测试多账户进入Lottery合约失败

使用Hardhat和Mocha测试需要转入ETH的Lottery合约时,单账户进入的测试用例「Allows player to enter」可正常通过,但多账户进入的测试用例「Allow multiple players to enter」失败。

原测试代码

const hre = require("hardhat");
const {expect} = require ("chai");

let account, account2, account3;
let lottery;

beforeEach(async () => {
  [account, account2, account3] = await hre.ethers.getSigners();
  const Lottery = await hre.ethers.getContractFactory("Lottery");
  lottery = await Lottery.deploy();
  await lottery.waitForDeployment();
});


describe("Lottery Contract", () => {
  it("Deploys a contract", () =>{
    expect(lottery.target).to.be.ok; 
  });

  it("Allows player to enter", async() =>{
    await lottery.enter({
      from: account,
      value: hre.ethers.parseUnits("0.11","ether"),
    });
        
    const players = await lottery.getPlayers({
      from: account
    });

    expect(account.address, players[0]).to.equal;
    expect(1, players.length).to.equal;
  });
  
  it("Allow multiple players to enter", async() =>{
    await lottery.enter({
      from: account.address,
      value: hre.ethers.parseUnits("0.11","ether"),
    });
    await lottery.enter({
      from: account2.address,
      value: hre.ethers.parseUnits("0.11","ether"),
    });
    await lottery.enter({
      from: account3,
      value: hre.ethers.parseUnits("0.11","ether"),
    });
    
    const players = await lottery.getPlayers({
      from: account
    });

    expect(account.address, players[0]).to.equal;
    expect(account2.address, players[1]).to.equal;
    expect(account3.address, players[2]).to.equal;
    expect(3, players.length).to.equal;
  });
});

合约enter函数

function enter() external payable minLimit{
  players.push(msg.sender);
}

错误信息

Lottery Contract
    √ Deploys a contract
    √ Allows player to enter
    1) Allow multiple players to enter


  2 passing (2s)
  1 failing

  1) Lottery Contract
       Allow multiple players to enter:
     TypeError: from address mismatch (argument="transaction", value={ "data": "0xe97dcb62", "from": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "to": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9", "value": 110000000000000000 }, code=INVALID_ARGUMENT, version=6.13.1)
      at makeError (node_modules\ethers\src.ts\utils\errors.ts:687:21)
      at assert (node_modules\ethers\src.ts\utils\errors.ts:715:25)
      at assertArgument (node_modules\ethers\src.ts\utils\errors.ts:727:5)
      at C:\Users\Заур\Desktop\lottery\node_modules\@nomicfoundation\hardhat-ethers\src\signers.ts:214:25
      at async Promise.all (index 0)
      at HardhatEthersSigner._sendUncheckedTransaction (node_modules\@nomicfoundation\hardhat-ethers\src\signers.ts:256:7)
      at HardhatEthersSigner.sendTransaction (node_modules\@nomicfoundation\hardhat-ethers\src\signers.ts:125:18)
      at send (node_modules\ethers\src.ts\contract\contract.ts:313:20)
      at Proxy.enter (node_modules\ethers\src.ts\contract\contract.ts:352:16)
      at Context.<anonymous> (test\Lottery.test.js:39:5)

问题原因

  1. Signer使用错误:在ethers.js v6和Hardhat环境中,不能直接在合约调用参数里用from指定账户地址或signer对象,正确方式是用对应账户的signer连接合约后再调用方法。
  2. Chai断言顺序错误:expect(实际值, 期望值).to.equal的参数顺序颠倒,正确语法为expect(实际值).to.equal(期望值)。

修正后的测试代码

const hre = require("hardhat");
const {expect} = require ("chai");

let account, account2, account3;
let lottery;

beforeEach(async () => {
  [account, account2, account3] = await hre.ethers.getSigners();
  const Lottery = await hre.ethers.getContractFactory("Lottery");
  lottery = await Lottery.deploy();
  await lottery.waitForDeployment();
});


describe("Lottery Contract", () => {
  it("Deploys a contract", () =>{
    expect(lottery.target).to.be.ok; 
  });

  it("Allows player to enter", async() =>{
    // 用account连接合约后调用enter
    await lottery.connect(account).enter({
      value: hre.ethers.parseUnits("0.11","ether"),
    });
        
    const players = await lottery.getPlayers();

    expect(players[0]).to.equal(account.address);
    expect(players.length).to.equal(1);
  });
  
  it("Allow multiple players to enter", async() =>{
    // 分别用不同账户连接合约调用enter
    await lottery.connect(account).enter({
      value: hre.ethers.parseUnits("0.11","ether"),
    });
    await lottery.connect(account2).enter({
      value: hre.ethers.parseUnits("0.11","ether"),
    });
    await lottery.connect(account3).enter({
      value: hre.ethers.parseUnits("0.11","ether"),
    });
    
    const players = await lottery.getPlayers();

    expect(players[0]).to.equal(account.address);
    expect(players[1]).to.equal(account2.address);
    expect(players[2]).to.equal(account3.address);
    expect(players.length).to.equal(3);
  });
});

说明

  • 使用lottery.connect(signer)方法指定交易发起账户,替代原有的from参数,这是ethers.js v6和Hardhat推荐的调用方式。
  • 修正Chai断言的参数顺序,确保实际值在前、期望值在后,符合断言语法规范。
  • 只读方法getPlayers无需指定from参数,因为不涉及交易发起者。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 17:57:13