如何通过Hardhat测试Solidity的fallback()函数
问题根因
Ethers.js 生成的合约实例会基于合约ABI做本地方法校验,你调用ABI中不存在的nonExistentFunction时,错误直接在JS层抛出,根本不会构造交易发送到链上,自然无法触发合约的fallback逻辑。
修复方案
放弃直接调用合约实例上不存在的方法,手动构造交易,传入不存在的函数选择器作为calldata,发送到合约地址即可触发fallback。修改后的测试代码如下:
const { expect } = require('chai'); const { ethers } = require('hardhat'); describe('Demo', () => { let deployer; let demoContract; before(async () => { [deployer] = await ethers.getSigners(); const factory = await ethers.getContractFactory('Demo'); demoContract = await factory.deploy().then((res) => res.deployed()); }); it('should invoke the fallback function', async () => { // 手动构造交易,calldata传入不存在的函数选择器即可 const tx = await deployer.sendTransaction({ to: demoContract.address, data: "0x53229aa6" // 为nonExistentFunction()计算出的4字节函数选择器,任意无效选择器都可触发fallback }); // 等待交易上链拿到收据后再做事件断言 await expect(tx.wait()) .to.emit(demoContract, 'Error') .withArgs('call of a non-existent function'); }); });
注意点
data字段不需要固定填示例值,只要传入的4字节前缀不匹配合约内任何已存在函数的选择器,都会触发fallback,比如填0xdeadbeef效果完全一致- 必须调用
tx.wait()等待交易确认后再做事件校验,否则事件还未被链上执行抛出,断言会失败 - 该写法兼容本地Hardhat网络与RSK测试网,不需要修改hardhat.config.js配置
内容的提问来源于stack exchange,提问作者Aleks Shenshin
相关产品推荐
相关产品推荐

