I am having trouble testing Chainlink API calls locally. I have a contract which calls my API consumer contract to make an API call. However, when I try to do that, the MockOracle (mocked oracle for local testing, from chainlink) contract reverts (VM exception) saying "Must use whitelisted functions". I am making an API call for a bytes32 get request.
This is the function modifier (inside of LinkTokenReceiver) where the MockOracle reverts (it gets called by the MockOracle when receiving LINK tokens):
/**
* @dev Reverts if the given data does not begin with the `oracleRequest` function selector
* @param _data The data payload of the request
*/
modifier permittedFunctionsForLINK(bytes memory _data) {
bytes4 funcSelector;
assembly {
// solhint-disable-next-line avoid-low-level-calls
funcSelector := mload(add(_data, 32))
}
require(funcSelector == ORACLE_REQUEST_SELECTOR, "Must use whitelisted functions");
_;
}
The ApiConsumer is properly funded, and the LINK token is a local deployment of the chainlink Token. So, what am I doing wrong? Or what is the best way to test Chainlink API calls (bytes32 get request) locally using hardhat?
In Chainlink oracle workflow, consumers are basically supposed to send a request to the off-chain oracle node so that the oracle node can fetch data from the API specified by consumers. In the workflow, request sent by user must be caught by off-chain oracle node.
What you are doing here is to send your request to smart contract oracle
and the oracle
save your request into event log oracleRequest
so that it could be caught by off-chain oracle.
Your problem here is as suggested by modifier permittedFunctionForLINK
, the function selector is not oracleRequest
so that off-chain oracle cannot recognize the request.
I am guessing you are currently using the oracle.sol
and ChainlinkClient.sol
in version v0.6. In version v0.6, AFAIK, ChainlinkClient doesn't not help users to add function selector oracleRequest
in the users' Chainlink request, which means you will get the error if you doesn't manually add the function selector in your request. In v0.7, ChainlinkClient helps you add the selector in the request. Just check the function sendChainlinkRequestTo
in ChainlinkClient v0.6 and ChainlinkClient v0.7 by yourself.
Solutions: