我的 Chainlink 请求没有得到满足?

My chainlink request isn't getting fulfilled?

谁能帮我调查一下为什么我的 Chainlink 请求没有得到满足。它们在我的测试中得到了满足(参见安全帽测试 etherscan 事件(https://kovan.etherscan.io/address/0x8Ae71A5a6c73dc87e0B9Da426c1b3B145a6F0d12#events). But they don't get fulfilled when I make them from my react app (see react app contract's etherscan events https://kovan.etherscan.io/address/0x6da2256a13fd36a884eb14185e756e89ffa695f8#events)。

相同的合约(不同的地址),相同的函数调用。

更新:

这是我在测试中调用它们的代码

        const tx = await baseAgreement.connect(user).withdraw(
            jobId,
            oracleFee
        );

这是我在 UI

中用来调用它们的代码
    const signer = provider.getSigner();
    const tx = await baseAgreement.connect(signer).withdraw(jobId, oracleFee);

这是我的 Solidity Chainlink 函数


    function withdraw(
        bytes32 _jobId,
        uint256 _oracleFee
    )
        external
        onlyContractActive()
        returns(bytes32 requestId)
    {
        // check Link in this contract to see if we need to request more
        checkLINK(_oracleFee);

        // Build request
        Chainlink.Request memory req = buildChainlinkRequest(_jobId, address(this), this.fulfillWithdraw.selector);
        bytes memory url_bytes = abi.encodePacked(BASE_URL, mediaLink, API_KEY);
        req.add("get", string(url_bytes));


        req.add("path", "items.0.statistics.viewCount");
        return sendChainlinkRequestTo(chainlinkOracleAddress(), req, _oracleFee);
    }

    /**
     * @dev Callback for chainlink, this function pays the user
     */
    function fulfillWithdraw(
        bytes32 _requestId,
        bytes32 _response
    )
        external
        recordChainlinkFulfillment(_requestId)
    {
        // Convert api string response to an int
        string memory _responseString = bytes32ToString(_response);
        uint256 response = uint256(parseInt(_responseString, 0));
        emit IntResponse(response);
        // Pay the user
        payUser(response);
    }

    function payUser(
        uint256 _number
    )
        internal
    {
        // Calculate pay
        uint256 budgetRemaining = getAgreementBalance();
        uint256 accumulatedPay = budget - budgetRemaining;
        uint256 pay = (payPerNumber * _number) - accumulatedPay;
        if (pay > budgetRemaining) {
            pay = budgetRemaining;
        }
        // Calculate platform fee
        uint256 totalPlatformFee = (pay * PLATFORM_FEE) / 100;
        // Transfer funds
        paySomeone(payable(address(this)), user, pay-totalPlatformFee);
        paySomeone(payable(address(this)), platformAddress, totalPlatformFee);
    }

完整的合约代码可以在这里查看:https://github.com/colinsteidtmann/dapplu-contracts/blob/main/contracts/BaseAgreement.sol

更新 2:

我发现我的 UI 正在使用工厂合约和克隆模式(基于 EIP 1167 标准和 OpenZepplin 的克隆 https://docs.openzeppelin.com/contracts/4.x/api/proxy#Clones )部署我的合约。但是,我的安全帽测试是在没有工厂的情况下部署我的合约。一旦我让安全帽测试使用工厂合约部署合约,它们就会停止工作。那么,chainlink 是否不适用于代理合约和 EIP 1167 标准?

删除 MinimalClone.sol 中的协议变量,让用户在 init() 方法中将它们作为参数输入,或者像这样将它们硬编码到请求中:

Chainlink.Request memory req = buildChainlinkRequest(_jobId, address(this), this.fulfillWithdraw.selector);
req.add("get", "https://youtube.googleapis.com/youtube/v3/videos?part=statistics&id=aaaaaakey=aaaaa");

它不起作用的原因是代理合约不继承实施合约的状态,只是通过 delegatecall() 方法的逻辑。因此,在替换请求中的这些变量时,您的代理克隆实际上读取的是空白值。

参考:Here is a good article关于代理和委托调用的工作原理。