Ошибка тестирования при вызове функции для внеконтрактной учетной записи
При тестировании нашего VRF getRandomNumber(s) с помощью тестовых помощников мы продолжаем получать ошибку: транзакция возвращена: вызов функции на неконтрактную учетную запись по адресу:
require(LINK.balanceOf(address(this))> fee, «Недостаточно ССЫЛКИ для инициализации вызова функции»);
LINK здесь используется правильно. В чем смысл / проблема внеконтрактной учетной записи?
1 ответ
Любой
LINK.xxx()
вызов относится к внешнему контракту LINK, которого нет в вашем коде. Это контракт, уже развернутый в сети, поэтому вы, скорее всего, передаете адрес LINK конструктору вашего контракта.
Чтобы заставить его работать в тесте, вам нужно что-то имитировать, чтобы ваш тест не вызывал реальный интерфейс. Одним из способов было бы издеваться над вашим
getRandomNumber
функция. так как это
public
, это должно быть легко выполнимо с помощью имитирующих утилит Waffle: https://ethereum-waffle.readthedocs.io/en/latest/mock-contract.html.
В качестве альтернативы (вероятно, более законной, но дольше) вы можете издеваться над всем
LINK
договор:
- Есть немного
Mocks.sol
договор:pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol"; abstract contract LinkMock is LinkTokenInterface {}
- Инициализируйте его как макет в своем тесте и передайте его адрес вашему макету контракта в качестве первого аргумента, как указано в документации 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', ]) }
- Вызов
rawFulfillRandomness()
который VRF называет сам, всякий раз, когда вы хотите имитировать VRF, генерирующий случайность:const contract = await getContract() await contract.connect(vrfCoordinatorMock).rawFulfillRandomness('0x0000000000000000000000000000000000000000000000000000000000000000', mockedRandomnessValue)
Обратите внимание, что я жестко закодирован
requestId
для краткости в приведенном выше примере. Вам придется придумать способ заглушить его, если вы полагаетесь на его значение в своем контракте.