ChainlinkClient合约state variable 'volume'未更新问题求助
Chainlink回调函数
fulfill未执行问题排查 我正在跟随Chainlink官方bootcamp教程学习,原Demo基于Kovan网络和solc: 0.6,但2023年我使用的是Goerli测试网、solc: 0.8以及@chainlink/contracts/src/v0.8/ChainlinkClient.sol版本的Chainlink客户端。
调用requestVolumeData()后交易已确认成功,但回调函数fulfill未执行,导致状态变量volume未更新。合约部署在Goerli测试网地址:0xF4d2279148183c2eE39Bf35130F567f5C51c402C,我已在goerli.etherscan.io上执行合约并仔细检查了函数调用和输入,期望volume能正常更新。
合约代码
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol"; contract APIConsumer is ChainlinkClient { using Chainlink for Chainlink.Request; uint256 public volume; address private oracle; bytes32 private jobId; uint256 private fee; /** * Network: Goerli * Chainlink - 0xCC79157eb46F5624204f47AB42b3906cAA40eaB7 * Chainlink - ca98366cc7314957b8c012c72f05aeeb * Fee: 0.1 LINK */ constructor() { // setPublicChainlinkToken(); setChainlinkToken(0x326C977E6efc84E512bB9C30f76E30c160eD06FB); oracle = 0xCC79157eb46F5624204f47AB42b3906cAA40eaB7; jobId = "ca98366cc7314957b8c012c72f05aeeb"; fee = 0.1 * 10 ** 18; // 0.1 LINK } function requestVolumeData() public returns (bytes32 requestId) { Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector); // Set the URL to perform the GET request on request.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD"); request.add("path", "RAW.ETH.USD.VOLUME24HOUR"); // Multiply the result by 1000000000000000000 to remove decimals int timesAmount = 10**18; request.addInt("times", timesAmount); // Sends the request return sendChainlinkRequestTo(oracle, request, fee); } /** * Receive the response in the form of uint256 */ function fulfill(bytes32 _requestId, uint256 _volume) public recordChainlinkFulfillment(_requestId) { volume = _volume; } function withdrawLink() external { LinkTokenInterface linkToken = LinkTokenInterface(chainlinkTokenAddress()); require(linkToken.transfer(msg.sender, linkToken.balanceOf(address(this))), "Unable to transfer"); } }
排查方向
- LINK余额检查:合约必须持有足够的LINK支付0.1 LINK的请求费用,余额不足时Oracle不会处理请求,可直接查询合约地址在Goerli链上的LINK余额。
- Job ID匹配验证:确认使用的Job ID
ca98366cc7314957b8c012c72f05aeeb是否对应Goerli网络上该Oracle支持的uint256类型返回的HTTP GET任务,不匹配的任务类型会导致回调失败。 - Oracle活跃性验证:确认Goerli网络上的Oracle地址
0xCC79157eb46F5624204f47AB42b3906cAA40eaB7是否处于活跃状态,部分旧Oracle可能已停止服务。 - API响应路径检查:手动访问指定API地址,确认返回的JSON结构中
RAW.ETH.USD.VOLUME24HOUR是否存在且为数字类型,API返回格式变更会导致Oracle无法解析数据,进而不触发回调。 - 回调权限与签名检查:
recordChainlinkFulfillment修饰器会验证调用者是否为请求对应的Oracle,若Oracle地址配置错误会导致回调被拒绝;同时确保fulfill函数签名与请求中指定的this.fulfill.selector完全匹配。 - Chainlink Token地址验证:确认
setChainlinkToken设置的地址0x326C977E6efc84E512bB9C30f76E30c160eD06FB是Goerli网络官方LINK代币地址,错误的代币地址会导致费用转账失败,Oracle不处理请求。
内容的提问来源于stack exchange,提问作者Waqas Muhammad
相关产品推荐
相关产品推荐

