首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >链链接多变量响应智能契约请求未被oracle.sol满足

链链接多变量响应智能契约请求未被oracle.sol满足
EN

Stack Overflow用户
提问于 2021-11-25 07:47:35
回答 2查看 284关注 0票数 1

我已经创建了一个链接外部适配器,并定义了一个多字请求作业。现在,我已经为作业创建了一个多变量响应契约(即externalAPIConsumer.sol),但是当调用requestValidationData()时,作业成功运行并完成,但是事务失败,因为oracle.sol契约给出了如下错误:

代码语言:javascript
复制
Warning! Error encountered during contract execution [execution reverted] 

以下是externalAPIConsumer.sol:

代码语言:javascript
复制
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";

contract ExternalAPIConsumer is ChainlinkClient {
    using Chainlink for Chainlink.Request;

    uint256 public allInSystem;
    uint256 public isProject;
    uint256 public senderAuthority;
    uint256 public receiverAuthority;

    address private oracle;
    bytes32 private jobId;
    uint256 private fee;

    event requestFulfilled(
        uint256 isProject,
        uint256 senderAuthority,
        uint256 allInSystem,
        uint256 receiverAuthority
    );

    constructor(address _oracle) {
        setPublicChainlinkToken();
        oracle = _oracle;
        jobId = "0b0e0c3944a94c989515e2dd81087356";
        fee = 0.1 * 10**18; // (Varies by network and job)
    }

    /**
     * Initial request
     */
    function requestValidationData(
        string memory _jwtToken,
        string memory _jobId
    ) public {
        jobId = stringToBytes32(_jobId);
        Chainlink.Request memory request = buildChainlinkRequest(
            jobId,
            address(this),
            this.fulfill.selector
        );
        request.add("orgAddress", "2021-11-02");
        request.add("senderAddress", "12111");
        request.add("receiverAddress", "FL");
        request.add("jwtToken", _jwtToken);
        sendChainlinkRequestTo(oracle, request, fee);
    }

    /**
     * Callback function
     */
    function fulfill(
        bytes32 _requestId,
        uint256 _allInSystem,
        uint256 _isProject,
        uint256 _senderAuthority,
        uint256 _receiverAuthority
    ) public recordChainlinkFulfillment(_requestId) {
        allInSystem = _allInSystem;
        isProject = _isProject;
        senderAuthority = _senderAuthority;
        receiverAuthority = _receiverAuthority;
        emit requestFulfilled(
            isProject,
            senderAuthority,
            allInSystem,
            receiverAuthority
        );
    }

    function stringToBytes32(string memory source)
        public
        pure
        returns (bytes32 result)
    {
        bytes memory tempEmptyStringTest = bytes(source);
        if (tempEmptyStringTest.length == 0) {
            return 0x0;
        }

        assembly {
            result := mload(add(source, 32))
        }
    }
}

下面是我如何用TOML格式定义我的工作:

代码语言:javascript
复制
type = "directrequest"
schemaVersion = 1
name = "Pliant-Chian_Adapter_5"
contractAddress = "0xec5368C5C258412B8518AEeb6966FAE07d0fc545"
maxTaskDuration = "0s"
observationSource = """
    decode_log   [type=ethabidecodelog
                  abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)"
                  data="$(jobRun.logData)"
                  topics="$(jobRun.logTopics)"]

    decode_cbor  [type=cborparse data="$(decode_log.data)"]
    fetch        [type=bridge name="test_pliant-chain_adaptor" requestData="{\\"id\\":$(jobSpec.externalJobID),\\"data\\":{\\"orgAddress\\": $(decode_cbor.orgAddress),\\"senderAddress\\":$(decode_cbor.senderAddress),\\"receiverAddress\\": $(decode_cbor.receiverAddress),\\"jwtToken\\": $(decode_cbor.jwtToken)}}"]
    
    decode_log -> decode_cbor -> fetch

    fetch -> parse_allInSystem
    fetch -> parse_isProject
    fetch -> parse_senderAuthority
    fetch -> parse_receiverAuthority
    
    parse_allInSystem               [type=jsonparse path="data,allInSystem" data="$(fetch)"]
    parse_isProject                 [type=jsonparse path="data,isProject" data="$(fetch)"]
    parse_senderAuthority           [type=jsonparse path="data,senderAuthority" data="$(fetch)"]
    parse_receiverAuthority         [type=jsonparse path="data,receiverAuthority" data="$(fetch)"]

    parse_allInSystem -> encode_mwr
    parse_isProject -> encode_mwr
    parse_senderAuthority -> encode_mwr
    parse_receiverAuthority -> encode_mwr

    encode_mwr   [type=ethabiencode abi="(bytes32 requestId, uint256 allInSystem, uint256 isProject, uint256 senderAuthority, uint256 receiverAuthority)" data="{ \\"requestId\\": $(decode_log.requestId), \\"allInSystem\\": $(parse_allInSystem), \\"isProject\\": $(parse_isProject), \\"senderAuthority\\": $(parse_senderAuthority), \\"receiverAuthority\\": $(parse_receiverAuthority)}"]
    encode_tx    [type=ethabiencode
                  abi="fulfillOracleRequest(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)"
                  data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_mwr)}"
                 ]
    submit_tx    [type=ethtx to="0xec5368C5C258412B8518AEeb6966FAE07d0fc545" data="$(encode_tx)"]

    encode_mwr -> encode_tx -> submit_tx
"""

更新:

我使用sendChainlinkRequestTo()发送请求,但根据@chainlink/contracts/src/v0.8/ChainlinkClient.sol的说法,只有sendOperatorRequestTo()才能支持多字响应。

/** * @notice创建指向指定oracle地址的Chainlink请求* @dev此函数支持多字响应* @dev生成和存储请求ID,增加本地nonce,并使用transferAndCall *发送链接在目标甲骨文合同上创建请求。*发射ChainlinkRequested事件。* @param oracleAddress请求的oracle地址* @param req初始化的Chainlink请求* @param支付请求发送的链接数量*@返回requestId请求ID */函数sendOperatorRequestTo(地址oracleAddress、Chainlink.Request内存req、uint256支付) 区块报价

当我使用sendOperatorRequestTo()时,事务将被还原为以下错误:

将事务处理为ExternalAPIConsumer.requestValidationData错误:执行已恢复:必须使用已白化的函数{ "originalError":{“代码”:3“数据”:“消息”:“执行还原:必须使用白函数”}}

EN

回答 2

Stack Overflow用户

发布于 2022-05-27 07:09:53

AFAIK oracle.sol不支持“大响应”,因此不支持多字响应。

您需要切换到operator.sol,在客户端合同中使用sendOperatorRequest(req, ORACLE_PAYMENT);,在节点的作业规范中使用fulfillOracleRequest2

您可以在这篇博客文章中阅读更多有关整个设置的信息。

票数 2
EN

Stack Overflow用户

发布于 2022-05-27 07:11:10

通常,您尝试调用多个using 256请求,但使用oracle.sol作为encode_tx任务中引用的encode_tx任务,在节点job-spec.toml中使用abi="fulfillOracleRequest(...)。通常,您的错误来源于oracle.sol不支持更重的数据需求,例如单个请求中的多个uint256。有关operator.sol的代码,请参阅下面的代码

如果您想解决这个问题,需要部署operator.sol,就像使用oracle.sol一样,用白名单显示您的["node_address"],并将job-spec.toml中的contractAddress替换为operator.sol契约地址。此外,在encode_tx任务中,observerationSource中的节点job-spec.toml指定abi="fulfillOracleRequest2(...)以正确引用operator.sol。最后,切换出测试智能协议中指向的oracle地址,将数据请求到operator.sol

operator.sol如下所示:

代码语言:javascript
复制
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0;
import "@chainlink/contracts/src/v0.7/Operator.sol";
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70107436

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档