测试零地址调用ERC20合约approve方法时遇Unsupported Operation错误求助
问题原因
你遇到的contract runner does not support calling错误,根源是零地址(0x0)无法作为合法的交易签名者:
- 零地址没有对应的私钥,无法生成有效的交易签名,ethers.js v6会直接拦截这种无效的signer连接操作,根本没机会触发合约内的
ERC20InvalidApproverrevert逻辑。 - 你的测试代码中
simpleTokenContract.connect(ZeroAddress)是无效操作,因为ZeroAddress只是一个字符串地址,不是ethers.js认可的Signer对象。
解决方案
要测试_msgSender()为零地址的场景,必须通过Hardhat的虚拟机(VM)工具模拟零地址发起交易,以下是两种可行的实现方式:
方式1:使用Hardhat Network Helpers的vm.prank
这是最简洁的方案,需要确保已安装@nomicfoundation/hardhat-network-helpers:
it("Should revert when owner address is zero ", async () => { const { helper01 } = await getNamedAccounts(); const allowanceAmount = 129; // 模拟零地址发起后续合约调用 await vm.prank(ZeroAddress); // 直接调用合约方法,此时_msgSender()会被替换为零地址 await expect(simpleTokenContract.approve(helper01, allowanceAmount)) .to.be.revertedWithCustomError(simpleTokenContract, "ERC20InvalidApprover") .withArgs(ZeroAddress); })
方式2:直接通过Provider发送原始交易
如果不想依赖额外工具,可以直接构造交易并通过Hardhat Provider发送:
it("Should revert when owner address is zero ", async () => { const { helper01 } = await getNamedAccounts(); const allowanceAmount = 129; const contractAddress = await simpleTokenContract.getAddress(); // 编码approve方法的调用数据 const approveCalldata = simpleTokenContract.interface.encodeFunctionData( "approve", [helper01, allowanceAmount] ); // 构造并发送模拟零地址发起的交易 await expect( hre.ethers.provider.send("eth_sendTransaction", [ { from: ZeroAddress, to: contractAddress, data: approveCalldata } ]) ).to.be.revertedWithCustomError(simpleTokenContract, "ERC20InvalidApprover") .withArgs(ZeroAddress); })
额外说明
- 优先使用
revertedWithCustomError替代revertedWith:OpenZeppelin的ERC20InvalidApprover是自定义错误,直接匹配错误名和参数能避免字符串匹配的潜在问题。 - 链上实际场景中不会出现零地址发起的交易,因为零地址没有私钥无法签名,所以这类测试只能通过VM模拟实现。
内容的提问来源于stack exchange,提问作者Narendra Reddy
相关产品推荐
相关产品推荐

