我已经创建了一个链接外部适配器,并定义了一个多字请求作业。现在,我已经为作业创建了一个多变量响应契约(即externalAPIConsumer.sol),但是当调用requestValidationData()时,作业成功运行并完成,但是事务失败,因为oracle.sol契约给出了如下错误:
Warning! Error encountered during contract execution [execution reverted] 以下是externalAPIConsumer.sol:
// 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格式定义我的工作:
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“数据”:“消息”:“执行还原:必须使用白函数”}}
发布于 2022-05-27 07:09:53
AFAIK oracle.sol不支持“大响应”,因此不支持多字响应。
您需要切换到operator.sol,在客户端合同中使用sendOperatorRequest(req, ORACLE_PAYMENT);,在节点的作业规范中使用fulfillOracleRequest2。
您可以在这篇博客文章中阅读更多有关整个设置的信息。
发布于 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如下所示:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0;
import "@chainlink/contracts/src/v0.7/Operator.sol";https://stackoverflow.com/questions/70107436
复制相似问题