0

在使用测试助手测试我们的 VRF getRandomNumber(s) 时,我们不断收到 Error: Transaction reverted: function call to a non-contract account at:

require(LINK.balanceOf(address(this)) > fee, "没有足够的 LINK 来初始化函数调用");

LINK 似乎在这里正确使用。非合约账户的含义/问题是什么?

对同一 RandomNumberConsumer 对象的其他测试是成功的。

contract RandomNumberConsumer is VRFConsumerBase {
[...]
    function getRandomNumber(uint256 userProvidedSeed) public returns (bytes32 requestId) {
        require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
        return requestRandomness(keyHash, fee, userProvidedSeed);
    }
  describe("getRandomNumber()", function() {
    it("Should return a requestID", async function() {
       const requestId = await randomNumberConsumer.getRandomNumber(12);
    // checks on requestId
    });
  });
4

1 回答 1

0

任何LINK.xxx()调用都是指您的代码中不存在的外部 LINK 合约。这是一个已经部署在网络上的合约——这就是为什么你很可能将 LINK 地址传递给你的合约的构造函数。

为了让它在测试中工作,你需要模拟一些东西,这样你的测试就不会最终调用真实的LINK接口。其中一种方法是模拟您的getRandomNumber功能。既然是public,那么使用 Waffle 的模拟工具应该可以轻松实现:https ://ethereum-waffle.readthedocs.io/en/latest/mock-contract.html 。

或者(可能更合法,但更长)您可以模拟整个LINK合同:

  1. 有一些Mocks.sol合同:
    pragma solidity ^0.8.7;
    
    import "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";
    
    abstract contract LinkMock is LinkTokenInterface {}
    
  2. 根据 VRF 文档,在您的测试中将其初始化为模拟并将其地址作为第一个参数传递给模拟合约:
    import { waffle } from 'hardhat'
    import { abi as linkMockAbi } from '../artifacts/contracts/Mocks.sol/LinkMock.json'
    
    const [deployer, vrfCoordinatorMock, ...actors] = waffle.provider.getWallets()
    
    const getContract = async ({ mockedLinkBalance }: { mockedLinkBalance: string }) => {
      const linkMockContract = await waffle.deployMockContract(deployer, linkMockAbi)
    
      // Mocks the external LINK contract that we don't have access to during tests
      await linkMockContract.mock.balanceOf.returns(ethers.utils.parseEther(mockedLinkBalance))
      await linkMockContract.mock.transferAndCall.returns(true)
    
      return waffle.deployContract(deployer, ContractJson, [
        vrfCoordinatorMock.address,
        linkMockContract.address,
       '0x0000000000000000000000000000000000000000000000000000000000000000',
        '100000000000000000',
      ])
    }
    
  3. rawFulfillRandomness()每当您想模拟 VRF 生成随机性时,VRF 都会调用它自己 :
    const contract = await getContract()
    await contract.connect(vrfCoordinatorMock).rawFulfillRandomness('0x0000000000000000000000000000000000000000000000000000000000000000', mockedRandomnessValue)
    

requestId请注意,为了简洁起见,我在上面的示例中进行了硬编码。如果你在合同中依赖它的价值,你将不得不想出一种方法来存根它。

于 2022-01-29T00:53:03.510 回答