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

如何在Hardhat中正确测试EIP-1167克隆合约的初始化逻辑?

问题排查与修复方案

嘿,我一眼就发现了导致你克隆合约初始化失败的核心问题,另外也给你优化下测试代码的写法:

1. 合约代码的致命错误:变量名不匹配

看你CloneFactory合约里的createClone函数,参数明明定义的是_whoopyCreator,但调用initialize的时候却用了一个完全没定义的_creator变量!在Solidity里未赋值的地址变量默认是address(0),这就是为什么测试里拿到的creator是空地址。

错误代码片段:

function createClone(address _whoopyCreator) payable external returns(address instance) { 
    instance = Clones.clone(implementationContract); 
    // 这里的_creator根本没定义!应该用_whoopyCreator
    (bool success, ) = instance.call{value: msg.value}(abi.encodeWithSignature("initialize(address)", _creator)); 
    // ... 其他代码
}

修复只需要把调用里的_creator改成_whoopyCreator就行:

(bool success, ) = instance.call{value: msg.value}(abi.encodeWithSignature("initialize(address)", _whoopyCreator)); 

2. 测试代码的优化建议(非核心错误,但能让代码更可靠)

你的测试代码有些冗余的地方,优化后会更简洁且不易出错:

  • 不需要手动读取JSON文件拿ABI,直接用合约工厂的Main.interface.abi就能获取
  • 不需要重新创建Web3Provider,Hardhat测试环境里的ethers已经自带了正确的 provider,直接用签名者连接合约即可
  • 通过事件名而非索引获取克隆地址,避免事件顺序变化导致的错误

优化后的测试代码:

it("Initialises contract correctly", async function () { 
    // 部署实现合约
    const Main = await ethers.getContractFactory("Main"); 
    const main = await Main.deploy(); 
    await main.deployed(); 

    // 部署克隆工厂
    const CloneFactory = await ethers.getContractFactory("CloneFactory"); 
    const cf = await CloneFactory.deploy(main.address); 
    await cf.deployed(); 

    const [addr1] = await ethers.getSigners(); 
    // 调用创建克隆合约
    const tx = await cf.createClone(addr1.address, { value: ethers.utils.parseEther("0") }); 
    const txReceipt = await tx.wait(1); 

    // 通过事件名精准获取克隆地址
    const newCloneEvent = txReceipt.events.find(evt => evt.event === "NewClone");
    const cloneAddress = newCloneEvent.args._instance;

    // 直接用Main的ABI创建克隆合约实例,并用addr1连接
    const clonedContract = new ethers.Contract(cloneAddress, Main.interface.abi, addr1); 
    const creator = await clonedContract.getCreator(); 

    expect(addr1.address).to.equal(creator); 
});

另外确认下你的initialize函数已经用了initializer修饰符(看起来你已经加了),这个能确保初始化函数只能被调用一次,是正确的做法。

修复完合约里的变量名问题,再用上优化后的测试代码,你的测试应该就能顺利通过了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 13:47:47