1

有人可以帮我调查为什么我的 Chainlink 请求没有得到满足。它们在我的测试中得到了满足(请参阅安全帽测试 etherscan 事件(https://kovan.etherscan.io/address/0x8Ae71A5a6c73dc87e0B9Da426c1b3B145a6F0d12#events)。但是当我从我的反应应用程序中制作它们时它们没有得到满足(请参阅反应应用程序合同的etherscan 事件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 标准?

4

1 回答 1

2

删除您的协议变量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()方法的逻辑。因此,在替换请求中的这些变量时,您的代理克隆实际上读取的是空白值。

参考:这是一篇关于代理和委托调用如何工作的好文章。

于 2021-06-16T00:09:48.237 回答