如何通过 Hardhat 测试 Solidity Fallback() 函数?

Ale*_*hin 5 solidity rsk ethers.js hardhat

我有一个 Solidity 智能合约Demo,正在Hardhat中开发并在RSK Testnet上进行测试。

//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

contract Demo {
    event Error(string);
    fallback() external {
      emit Error("call of a non-existent function");
    }
}
Run Code Online (Sandbox Code Playgroud)

我想确保调用该函数并发出fallback事件。Error为此,我尝试nonExistentFunction在智能合约上调用:

//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

contract Demo {
    event Error(string);
    fallback() external {
      emit Error("call of a non-existent function");
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,HarhatTypeError在实际连接到 RSK 上的智能合约之前就抛出了一个问题:

  Demo
    1) should invoke the fallback function


  0 passing (555ms)
  1 failing

  1) Demo
       should invoke the fallback function:
     TypeError: demoContract.nonExistentFunction is not a function
      at Context.<anonymous> (test/Demo.js:13:29)
      at processImmediate (internal/timers.js:461:21)
Run Code Online (Sandbox Code Playgroud)

我怎样才能智胜 Hardhat/Ethers.js 并最终能够调用不存在的函数,从而调用fallback智能合约中的函数?

作为参考,这是我的hardhat.config.js

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 () => {
    const tx = demoContract.nonExistentFunction();
    await expect(tx)
      .to.emit(demoContract, 'Error')
      .withArgs('call of a non-existent function');
  });
});
Run Code Online (Sandbox Code Playgroud)

bgu*_*uiz 4

您可以使用将不存在的函数签名注入\n到智能合约对象 ( ) 的方法。\n为ethers.Contract创建函数签名nonExistentFunction

\n
const nonExistentFuncSignature =\n  \'nonExistentFunction(uint256,uint256)\';\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,参数列表不应包含空格,并且仅包含参数类型(无参数名称)。

\n

然后实例化一个新的智能合约对象。

\n

当您执行此操作时,您需要修改 ABI,Demo\n以便它包含此附加函数签名。:

\n
const fakeDemoContract = new ethers.Contract(\n  demoContract.address,\n  [\n    ...demoContract.interface.fragments,\n    `function ${nonExistentFuncSignature}`,\n  ],\n  deployer,\n);\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,部署的合约与之前相同 -\n不包含此新功能。\n但是与此智能合约交互的客户端 -\n本例中的测试 -\n确实认为智能合约现在具有此功能。

\n

此时,您将能够运行原始测试,\n只需稍加修改:

\n
const tx = fakeDemoContract[nonExistentFuncSignature](8, 9);\nawait expect(tx)\n  .to.emit(demoContract, \'Error\')\n  .withArgs(\'call of a non-existent function\');\n
Run Code Online (Sandbox Code Playgroud)\n
\n

全面测试:

\n
it(\'should invoke the fallback function\', async () => {\n    const nonExistentFuncSignature = \'nonExistentFunc(uint256,uint256)\';\n    const fakeDemoContract = new ethers.Contract(\n      demoContract.address,\n      [\n        ...demoContract.interface.fragments,\n        `function ${nonExistentFuncSignature}`,\n      ],\n      deployer,\n    );\n    const tx = fakeDemoContract[nonExistentFuncSignature](8, 9);\n    await expect(tx)\n      .to.emit(demoContract, \'Error\')\n      .withArgs(\'call of a non-existent function\');\n });\n
Run Code Online (Sandbox Code Playgroud)\n

测试结果:

\n
  Demo\n    \xe2\x9c\x94 should invoke the fallback function (77933ms)\n\n\n  1 passing (2m)\n
Run Code Online (Sandbox Code Playgroud)\n