From 30f3461e9b3d4cd200712e5fd13b1341a580c15c Mon Sep 17 00:00:00 2001 From: echo Date: Wed, 13 Nov 2024 16:33:30 +0800 Subject: [PATCH 1/9] xapi oracle --- src/eco/XAPIOracle.sol | 137 +++++++++++++++++++++++++++ src/eco/interfaces/IXAPI.sol | 88 +++++++++++++++++ src/eco/interfaces/IXAPIConsumer.sol | 8 ++ 3 files changed, 233 insertions(+) create mode 100644 src/eco/XAPIOracle.sol create mode 100644 src/eco/interfaces/IXAPI.sol create mode 100644 src/eco/interfaces/IXAPIConsumer.sol diff --git a/src/eco/XAPIOracle.sol b/src/eco/XAPIOracle.sol new file mode 100644 index 0000000..1a98fec --- /dev/null +++ b/src/eco/XAPIOracle.sol @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import "../Verifier.sol"; +import "../interfaces/IORMP.sol"; +import {IXAPI, IXAPIConsumer, ResponseData} from "./interfaces/IXAPIConsumer.sol"; + +contract XAPIOracle is Verifier, IXAPIConsumer { + event SetFee(uint256 indexed chainId, uint256 fee); + event SetApproved(address operator, bool approve); + event Withdrawal(address indexed to, uint256 amt); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event XAPIRequestMade(uint256 indexed requestId, address exAggregator, string requestData); + event XAPIConsumeResult(uint256 indexed requestId, bytes responseData, uint16 errorCode); + event XAPIConsumeError(uint256 indexed requestId, uint16 errorCode); + + address public immutable PROTOCOL; + address public immutable XAPI; + + address public owner; + // chainId => price + mapping(uint256 => uint256) public feeOf; + // operator => isApproved + mapping(address => bool) public approvedOf; + + struct XAPIRequst { + uint256 chainId; + uint256 msgIndex; + address channel; + bool flag; + } + mapping(uint => XAPIRequst) public requests; + uint requestedId; + + modifier onlyOwner() { + require(msg.sender == owner, "!owner"); + _; + } + + modifier onlyXAPI() { + require(msg.sender == XAPI, "!xapi"); + _; + } + + modifier onlyApproved() { + require(isApproved(msg.sender), "!approve"); + _; + } + + constructor(address dao, address ormp, address xapi) { + PROTOCOL = ormp; + owner = dao; + XAPI = xapi; + } + + receive() external payable {} + + function version() public pure returns (string memory) { + return "2.1.0"; + } + + /// @dev Only could be called by approved address. + /// @param exAggregator The aggregator extend address on evm. + /// @param request The XAPI request for specific message. + /// 1. chainId The source chain id. + /// 2. channel The message channel. + /// 3. msgIndex The source chain message index. + function makeRequestForMessageHash(address exAggregator, string calldata request) + external + payable + onlyApproved + { + uint256 fee = IXAPI(XAPI).fee(exAggregator); + require(msg.value >= fee, "!fee"); + uint requestId = IXAPI(XAPI).makeRequest{value: fee}(exAggregator, request, this.xapiCallback.selector); + requires = XAPIRequst({ + chainId; + msgIndex; + channel; + flag; + }); + + emit RequestSent(requestedId, exAggregator, request); + } + + + function xapiCallback(uint256 requestId, ResponseData memory response) external { + function importMessageHash(uint256 chainId, address channel, uint256 msgIndex, bytes32 msgHash) + external + onlyXAPI + { + require(requestedId == requestId, "requestId"); + if (response.errorCode != 0) { + + IORMP(PROTOCOL).importHash(chainId, channel, msgIndex, msgHash); + emit ConsumeResult(requestId, response.result, response.errorCode); + } else { + emit ConsumeError(requestId, response.errorCode); + } + } + + function hashOf(uint256 chainId, address channel, uint256 msgIndex) public view override returns (bytes32) { + return IORMP(PROTOCOL).hashLookup(address(this), keccak256(abi.encode(chainId, channel, msgIndex))); + } + + function changeOwner(address newOwner) external onlyOwner { + address oldOwner = owner; + owner = newOwner; + emit OwnershipTransferred(oldOwner, newOwner); + } + + function setApproved(address operator, bool approve) external onlyOwner { + approvedOf[operator] = approve; + emit SetApproved(operator, approve); + } + + function isApproved(address operator) public view returns (bool) { + return approvedOf[operator]; + } + + function withdraw(address to, uint256 amount) external onlyApproved { + (bool success,) = to.call{value: amount}(""); + require(success, "!withdraw"); + emit Withdrawal(to, amount); + } + + function setFee(uint256 chainId, uint256 fee_) external onlyApproved { + feeOf[chainId] = fee_; + emit SetFee(chainId, fee_); + } + + function fee(uint256 toChainId, address /*ua*/ ) public view returns (uint256) { + uint256 f = feeOf[toChainId]; + require(f != 0, "!fee"); + return f; + } +} diff --git a/src/eco/interfaces/IXAPI.sol b/src/eco/interfaces/IXAPI.sol new file mode 100644 index 0000000..9cde1a2 --- /dev/null +++ b/src/eco/interfaces/IXAPI.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +struct Request { + // Currently, aggregators is deployed on Near. So use `string` type. + string aggregator; + // JSON string + string requestData; + address requester; + address callbackContract; + bytes4 callbackFunction; + RequestStatus status; + // Derived address of aggregator account (on near) + address exAggregator; + ResponseData response; + uint256 reportersFee; + uint256 publishFee; +} + +enum RequestStatus { + Pending, + Fulfilled, + CallbackFailed +} + +struct ResponseData { + address[] reporters; + bytes result; + // 0 if no error + uint16 errorCode; +} + +struct AggregatorConfig { + // Aggregator account on near + string aggregator; + address rewardAddress; + uint256 reportersFee; + uint256 publishFee; + uint256 version; + bool suspended; +} + +interface IXAPI { + event RequestMade( + uint256 indexed requestId, + string aggregator, + string requestData, + address indexed requester, + address indexed exAggregator, + uint256 reportersFee, + uint256 publishFee + ); + event Fulfilled(uint256 indexed requestId, ResponseData response, RequestStatus indexed status); + event RewardsWithdrawn(address indexed withdrawer, uint256 amount); + event AggregatorConfigSet( + address indexed exAggregator, + uint256 reportersFee, + uint256 publishFee, + string aggregator, + address rewardAddress, + uint256 version + ); + event AggregatorSuspended(address indexed exAggregator, string indexed aggregator); + + function makeRequest(address exAggregator, string memory requestData, bytes4 callbackFunction) + external + payable + returns (uint256); + + function fulfill(uint256 requestId, ResponseData memory response) external; + + function retryFulfill(uint256 requestId) external; + + function withdrawRewards() external; + + // Should be called by Aggregator mpc + function setAggregatorConfig( + string memory aggregator, + uint256 reportersFee, + uint256 publishFee, + address rewardAddress, + uint256 version + ) external; + + function fee(address exAggregator) external view returns (uint256); + + function suspendAggregator(address exAggregator) external; +} diff --git a/src/eco/interfaces/IXAPIConsumer.sol b/src/eco/interfaces/IXAPIConsumer.sol new file mode 100644 index 0000000..c0f3ecd --- /dev/null +++ b/src/eco/interfaces/IXAPIConsumer.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import "./IXAPI.sol"; + +interface IXAPIConsumer { + function xapiCallback(uint256 requestId, ResponseData memory response) external; +} From 26c0782105d8c2b9a0abc858d89604563eea8412 Mon Sep 17 00:00:00 2001 From: echo Date: Wed, 13 Nov 2024 16:38:39 +0800 Subject: [PATCH 2/9] forge install: xapi-contracts --- .gitmodules | 3 +++ lib/xapi-contracts | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/xapi-contracts diff --git a/.gitmodules b/.gitmodules index a6260fb..167bffe 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "lib/create3-deploy"] path = lib/create3-deploy url = https://github.com/darwinia-network/create3-deploy +[submodule "lib/xapi-contracts"] + path = lib/xapi-contracts + url = https://github.com/ringecosystem/xapi-contracts diff --git a/lib/xapi-contracts b/lib/xapi-contracts new file mode 160000 index 0000000..b113607 --- /dev/null +++ b/lib/xapi-contracts @@ -0,0 +1 @@ +Subproject commit b113607e3cad0012309dc4a0f5d4522032a56d3c From 1c23f97c6f21664456aa64de149519f4a95a35b5 Mon Sep 17 00:00:00 2001 From: echo Date: Wed, 13 Nov 2024 17:08:37 +0800 Subject: [PATCH 3/9] xapi oracle deps --- lib/xapi-contracts | 2 +- remappings.txt | 2 + src/eco/XAPIOracle.sol | 30 +++++----- src/eco/interfaces/IXAPI.sol | 88 ---------------------------- src/eco/interfaces/IXAPIConsumer.sol | 8 --- 5 files changed, 18 insertions(+), 112 deletions(-) delete mode 100644 src/eco/interfaces/IXAPI.sol delete mode 100644 src/eco/interfaces/IXAPIConsumer.sol diff --git a/lib/xapi-contracts b/lib/xapi-contracts index b113607..e9d7181 160000 --- a/lib/xapi-contracts +++ b/lib/xapi-contracts @@ -1 +1 @@ -Subproject commit b113607e3cad0012309dc4a0f5d4522032a56d3c +Subproject commit e9d71817ab1946f5506bb80c1735c10daae0e66e diff --git a/remappings.txt b/remappings.txt index c7d2aae..2213645 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,3 +1,5 @@ forge-std/=lib/forge-std/src/ ds-test/=lib/forge-std/lib/ds-test/src/ create3-deploy/=lib/create3-deploy/ +xapi/=lib/xapi-contracts/xapi/ +xapi-consumer/=lib/xapi-contracts/xapi-consumer/contracts/ diff --git a/src/eco/XAPIOracle.sol b/src/eco/XAPIOracle.sol index 1a98fec..f4df997 100644 --- a/src/eco/XAPIOracle.sol +++ b/src/eco/XAPIOracle.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.17; +pragma solidity ^0.8.0; import "../Verifier.sol"; import "../interfaces/IORMP.sol"; -import {IXAPI, IXAPIConsumer, ResponseData} from "./interfaces/IXAPIConsumer.sol"; +import {IXAPIConsumer} from "xapi-consumer/interfaces/IXAPIConsumer.sol"; contract XAPIOracle is Verifier, IXAPIConsumer { event SetFee(uint256 indexed chainId, uint256 fee); @@ -70,22 +70,22 @@ contract XAPIOracle is Verifier, IXAPIConsumer { payable onlyApproved { - uint256 fee = IXAPI(XAPI).fee(exAggregator); - require(msg.value >= fee, "!fee"); - uint requestId = IXAPI(XAPI).makeRequest{value: fee}(exAggregator, request, this.xapiCallback.selector); - requires = XAPIRequst({ - chainId; - msgIndex; - channel; - flag; - }); - - emit RequestSent(requestedId, exAggregator, request); + // uint256 fee = IXAPI(XAPI).fee(exAggregator); + // require(msg.value >= fee, "!fee"); + // uint requestId = IXAPI(XAPI).makeRequest{value: fee}(exAggregator, request, this.xapiCallback.selector); + // requires = XAPIRequst({ + // chainId; + // msgIndex; + // channel; + // flag; + // }); + // + // emit RequestSent(requestedId, exAggregator, request); } - function xapiCallback(uint256 requestId, ResponseData memory response) external { - function importMessageHash(uint256 chainId, address channel, uint256 msgIndex, bytes32 msgHash) + function xapiCallback(uint256 requestId, ResponseData memory response) + // function importMessageHash(uint256 chainId, address channel, uint256 msgIndex, bytes32 msgHash) external onlyXAPI { diff --git a/src/eco/interfaces/IXAPI.sol b/src/eco/interfaces/IXAPI.sol deleted file mode 100644 index 9cde1a2..0000000 --- a/src/eco/interfaces/IXAPI.sol +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -struct Request { - // Currently, aggregators is deployed on Near. So use `string` type. - string aggregator; - // JSON string - string requestData; - address requester; - address callbackContract; - bytes4 callbackFunction; - RequestStatus status; - // Derived address of aggregator account (on near) - address exAggregator; - ResponseData response; - uint256 reportersFee; - uint256 publishFee; -} - -enum RequestStatus { - Pending, - Fulfilled, - CallbackFailed -} - -struct ResponseData { - address[] reporters; - bytes result; - // 0 if no error - uint16 errorCode; -} - -struct AggregatorConfig { - // Aggregator account on near - string aggregator; - address rewardAddress; - uint256 reportersFee; - uint256 publishFee; - uint256 version; - bool suspended; -} - -interface IXAPI { - event RequestMade( - uint256 indexed requestId, - string aggregator, - string requestData, - address indexed requester, - address indexed exAggregator, - uint256 reportersFee, - uint256 publishFee - ); - event Fulfilled(uint256 indexed requestId, ResponseData response, RequestStatus indexed status); - event RewardsWithdrawn(address indexed withdrawer, uint256 amount); - event AggregatorConfigSet( - address indexed exAggregator, - uint256 reportersFee, - uint256 publishFee, - string aggregator, - address rewardAddress, - uint256 version - ); - event AggregatorSuspended(address indexed exAggregator, string indexed aggregator); - - function makeRequest(address exAggregator, string memory requestData, bytes4 callbackFunction) - external - payable - returns (uint256); - - function fulfill(uint256 requestId, ResponseData memory response) external; - - function retryFulfill(uint256 requestId) external; - - function withdrawRewards() external; - - // Should be called by Aggregator mpc - function setAggregatorConfig( - string memory aggregator, - uint256 reportersFee, - uint256 publishFee, - address rewardAddress, - uint256 version - ) external; - - function fee(address exAggregator) external view returns (uint256); - - function suspendAggregator(address exAggregator) external; -} diff --git a/src/eco/interfaces/IXAPIConsumer.sol b/src/eco/interfaces/IXAPIConsumer.sol deleted file mode 100644 index c0f3ecd..0000000 --- a/src/eco/interfaces/IXAPIConsumer.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -import "./IXAPI.sol"; - -interface IXAPIConsumer { - function xapiCallback(uint256 requestId, ResponseData memory response) external; -} From 9b3798734eb419e732b7f2215a0bec3099282c96 Mon Sep 17 00:00:00 2001 From: echo Date: Wed, 13 Nov 2024 17:09:53 +0800 Subject: [PATCH 4/9] forge install: chainlink v2.18.0 --- .gitmodules | 3 +++ lib/chainlink | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/chainlink diff --git a/.gitmodules b/.gitmodules index 167bffe..899b5ab 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "lib/xapi-contracts"] path = lib/xapi-contracts url = https://github.com/ringecosystem/xapi-contracts +[submodule "lib/chainlink"] + path = lib/chainlink + url = https://github.com/smartcontractkit/chainlink diff --git a/lib/chainlink b/lib/chainlink new file mode 160000 index 0000000..fb7d6e8 --- /dev/null +++ b/lib/chainlink @@ -0,0 +1 @@ +Subproject commit fb7d6e88ea3471909a4f9aa29992ec080bba9057 From 4e78f929f030887fcd81c7cecee6c36749d1ac5e Mon Sep 17 00:00:00 2001 From: echo Date: Wed, 20 Nov 2024 14:23:16 +0800 Subject: [PATCH 5/9] add xapi oracle --- lib/xapi-contracts | 2 +- remappings.txt | 1 + src/eco/XAPIOracle.sol | 106 ++++++++++++++++++++++++----------------- 3 files changed, 63 insertions(+), 46 deletions(-) diff --git a/lib/xapi-contracts b/lib/xapi-contracts index e9d7181..92466ba 160000 --- a/lib/xapi-contracts +++ b/lib/xapi-contracts @@ -1 +1 @@ -Subproject commit e9d71817ab1946f5506bb80c1735c10daae0e66e +Subproject commit 92466ba49ce1bf1c0b8ef4f846d20923cd70183c diff --git a/remappings.txt b/remappings.txt index 2213645..25fb4ec 100644 --- a/remappings.txt +++ b/remappings.txt @@ -3,3 +3,4 @@ ds-test/=lib/forge-std/lib/ds-test/src/ create3-deploy/=lib/create3-deploy/ xapi/=lib/xapi-contracts/xapi/ xapi-consumer/=lib/xapi-contracts/xapi-consumer/contracts/ +@chainlink/=lib/chainlink/ diff --git a/src/eco/XAPIOracle.sol b/src/eco/XAPIOracle.sol index f4df997..7df4f87 100644 --- a/src/eco/XAPIOracle.sol +++ b/src/eco/XAPIOracle.sol @@ -3,19 +3,23 @@ pragma solidity ^0.8.0; import "../Verifier.sol"; import "../interfaces/IORMP.sol"; -import {IXAPIConsumer} from "xapi-consumer/interfaces/IXAPIConsumer.sol"; +import "xapi-consumer/interfaces/IXAPIConsumer.sol"; +import "xapi/contracts/lib/XAPIBuilder.sol"; contract XAPIOracle is Verifier, IXAPIConsumer { + using XAPIBuilder for XAPIBuilder.Request; + event SetFee(uint256 indexed chainId, uint256 fee); event SetApproved(address operator, bool approve); event Withdrawal(address indexed to, uint256 amt); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - event XAPIRequestMade(uint256 indexed requestId, address exAggregator, string requestData); - event XAPIConsumeResult(uint256 indexed requestId, bytes responseData, uint16 errorCode); - event XAPIConsumeError(uint256 indexed requestId, uint16 errorCode); + event RequestMade(uint256 indexed requestId, XAPIBuilder.Request requestData); + event ConsumeResult(uint256 indexed requestId, bytes responseData, uint16 errorCode); + event ConsumeError(uint256 indexed requestId, uint16 errorCode); address public immutable PROTOCOL; - address public immutable XAPI; + address public immutable XAPI; + address public immutable EXAGGREGATOR; address public owner; // chainId => price @@ -23,14 +27,14 @@ contract XAPIOracle is Verifier, IXAPIConsumer { // operator => isApproved mapping(address => bool) public approvedOf; - struct XAPIRequst { - uint256 chainId; - uint256 msgIndex; - address channel; - bool flag; - } - mapping(uint => XAPIRequst) public requests; - uint requestedId; + struct DataSource { + string name; + string url; + string method; + string resultPath; + } + + uint256 requestId; modifier onlyOwner() { require(msg.sender == owner, "!owner"); @@ -47,10 +51,11 @@ contract XAPIOracle is Verifier, IXAPIConsumer { _; } - constructor(address dao, address ormp, address xapi) { + constructor(address dao, address ormp, address xapi, address exagg) { PROTOCOL = ormp; owner = dao; - XAPI = xapi; + XAPI = xapi; + EXAGGREGATOR = exagg; } receive() external payable {} @@ -59,40 +64,51 @@ contract XAPIOracle is Verifier, IXAPIConsumer { return "2.1.0"; } + function _buildRequest(uint256 chainId, address channel, uint256 msgIndex) + internal + view + returns (XAPIBuilder.Request memory) + { + XAPIBuilder.Request memory requestData; + requestData._initialize(EXAGGREGATOR, this.xapiCallback.selector); + requestData._addParamUint("_dataSources", chainId); + requestData._startNestedParam("*"); + { + requestData._startNestedParam("variables"); + { + requestData._addParamUint("chainId", chainId); + requestData._addParamBytes("channel", abi.encodePacked(channel)); + requestData._addParamUint("msgIndex", msgIndex); + } + requestData._endNestedParam(); + } + requestData._endNestedParam(); + return requestData; + } + /// @dev Only could be called by approved address. - /// @param exAggregator The aggregator extend address on evm. - /// @param request The XAPI request for specific message. - /// 1. chainId The source chain id. - /// 2. channel The message channel. - /// 3. msgIndex The source chain message index. - function makeRequestForMessageHash(address exAggregator, string calldata request) - external - payable - onlyApproved - { - // uint256 fee = IXAPI(XAPI).fee(exAggregator); - // require(msg.value >= fee, "!fee"); - // uint requestId = IXAPI(XAPI).makeRequest{value: fee}(exAggregator, request, this.xapiCallback.selector); - // requires = XAPIRequst({ - // chainId; - // msgIndex; - // channel; - // flag; - // }); - // - // emit RequestSent(requestedId, exAggregator, request); - } - - - function xapiCallback(uint256 requestId, ResponseData memory response) - // function importMessageHash(uint256 chainId, address channel, uint256 msgIndex, bytes32 msgHash) + /// @param chainId The request source chain id. + /// @param channel The request message channel. + /// @param msgIndex The request message index. + function makeRequestForMessageHash(uint256 chainId, address channel, uint256 msgIndex) external - onlyXAPI + payable + onlyApproved { - require(requestedId == requestId, "requestId"); + XAPIBuilder.Request memory requestData = _buildRequest(chainId, channel, msgIndex); + uint256 fee_ = IXAPI(XAPI).fee(EXAGGREGATOR); + require(msg.value >= fee_, "!fee"); + requestId = IXAPI(XAPI).makeRequest{value: fee_}(requestData); + emit RequestMade(requestId, requestData); + payable(msg.sender).transfer(msg.value - fee_); + } + + function xapiCallback(uint256 requestId_, ResponseData memory response) external onlyXAPI { + require(requestId_ == requestId, "requestId"); if (response.errorCode != 0) { - - IORMP(PROTOCOL).importHash(chainId, channel, msgIndex, msgHash); + (uint256 chainId, address channel, uint256 msgIndex, bytes32 msgHash) = + abi.decode(response.result, (uint256, address, uint256, bytes32)); + IORMP(PROTOCOL).importHash(chainId, channel, msgIndex, msgHash); emit ConsumeResult(requestId, response.result, response.errorCode); } else { emit ConsumeError(requestId, response.errorCode); From 42b4c060f9bb49dd67c73ddbfd9847ee0592131c Mon Sep 17 00:00:00 2001 From: echo Date: Wed, 20 Nov 2024 14:24:58 +0800 Subject: [PATCH 6/9] rename event name --- src/eco/XAPIOracle.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/eco/XAPIOracle.sol b/src/eco/XAPIOracle.sol index 7df4f87..fa32aeb 100644 --- a/src/eco/XAPIOracle.sol +++ b/src/eco/XAPIOracle.sol @@ -13,9 +13,9 @@ contract XAPIOracle is Verifier, IXAPIConsumer { event SetApproved(address operator, bool approve); event Withdrawal(address indexed to, uint256 amt); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - event RequestMade(uint256 indexed requestId, XAPIBuilder.Request requestData); - event ConsumeResult(uint256 indexed requestId, bytes responseData, uint16 errorCode); - event ConsumeError(uint256 indexed requestId, uint16 errorCode); + event XAPIRequestMade(uint256 indexed requestId, XAPIBuilder.Request requestData); + event XAPIConsumeResult(uint256 indexed requestId, bytes responseData, uint16 errorCode); + event XAPIConsumeError(uint256 indexed requestId, uint16 errorCode); address public immutable PROTOCOL; address public immutable XAPI; @@ -99,7 +99,7 @@ contract XAPIOracle is Verifier, IXAPIConsumer { uint256 fee_ = IXAPI(XAPI).fee(EXAGGREGATOR); require(msg.value >= fee_, "!fee"); requestId = IXAPI(XAPI).makeRequest{value: fee_}(requestData); - emit RequestMade(requestId, requestData); + emit XAPIRequestMade(requestId, requestData); payable(msg.sender).transfer(msg.value - fee_); } @@ -109,9 +109,9 @@ contract XAPIOracle is Verifier, IXAPIConsumer { (uint256 chainId, address channel, uint256 msgIndex, bytes32 msgHash) = abi.decode(response.result, (uint256, address, uint256, bytes32)); IORMP(PROTOCOL).importHash(chainId, channel, msgIndex, msgHash); - emit ConsumeResult(requestId, response.result, response.errorCode); + emit XAPIConsumeResult(requestId, response.result, response.errorCode); } else { - emit ConsumeError(requestId, response.errorCode); + emit XAPIConsumeError(requestId, response.errorCode); } } From e15f7d33e457a962e21e3e4d037c597166d993ed Mon Sep 17 00:00:00 2001 From: echo Date: Wed, 20 Nov 2024 14:26:00 +0800 Subject: [PATCH 7/9] change version --- src/eco/XAPIOracle.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/eco/XAPIOracle.sol b/src/eco/XAPIOracle.sol index fa32aeb..70e9272 100644 --- a/src/eco/XAPIOracle.sol +++ b/src/eco/XAPIOracle.sol @@ -61,7 +61,7 @@ contract XAPIOracle is Verifier, IXAPIConsumer { receive() external payable {} function version() public pure returns (string memory) { - return "2.1.0"; + return "1.0.0"; } function _buildRequest(uint256 chainId, address channel, uint256 msgIndex) From 4674d31cde7022b1309d6dc0eb95b3dd4f5f2a9c Mon Sep 17 00:00:00 2001 From: echo Date: Wed, 20 Nov 2024 14:32:25 +0800 Subject: [PATCH 8/9] fix --- src/eco/XAPIOracle.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/eco/XAPIOracle.sol b/src/eco/XAPIOracle.sol index 70e9272..01ff796 100644 --- a/src/eco/XAPIOracle.sol +++ b/src/eco/XAPIOracle.sol @@ -97,14 +97,13 @@ contract XAPIOracle is Verifier, IXAPIConsumer { { XAPIBuilder.Request memory requestData = _buildRequest(chainId, channel, msgIndex); uint256 fee_ = IXAPI(XAPI).fee(EXAGGREGATOR); - require(msg.value >= fee_, "!fee"); + require(msg.value == fee_, "!fee"); requestId = IXAPI(XAPI).makeRequest{value: fee_}(requestData); emit XAPIRequestMade(requestId, requestData); - payable(msg.sender).transfer(msg.value - fee_); } function xapiCallback(uint256 requestId_, ResponseData memory response) external onlyXAPI { - require(requestId_ == requestId, "requestId"); + require(requestId_ == requestId, "!requestId"); if (response.errorCode != 0) { (uint256 chainId, address channel, uint256 msgIndex, bytes32 msgHash) = abi.decode(response.result, (uint256, address, uint256, bytes32)); From 988f816e78652db4f50689d335c881c4f0e098c4 Mon Sep 17 00:00:00 2001 From: echo Date: Wed, 20 Nov 2024 15:05:38 +0800 Subject: [PATCH 9/9] convert address to string --- src/eco/XAPIOracle.sol | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/eco/XAPIOracle.sol b/src/eco/XAPIOracle.sol index 01ff796..111ea0f 100644 --- a/src/eco/XAPIOracle.sol +++ b/src/eco/XAPIOracle.sol @@ -77,7 +77,7 @@ contract XAPIOracle is Verifier, IXAPIConsumer { requestData._startNestedParam("variables"); { requestData._addParamUint("chainId", chainId); - requestData._addParamBytes("channel", abi.encodePacked(channel)); + requestData._addParam("channel", toHexString(channel)); requestData._addParamUint("msgIndex", msgIndex); } requestData._endNestedParam(); @@ -149,4 +149,24 @@ contract XAPIOracle is Verifier, IXAPIConsumer { require(f != 0, "!fee"); return f; } + + // Inspired from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/utils/Strings.sol + bytes16 private constant _SYMBOLS = "0123456789abcdef"; + uint8 private constant _ADDRESS_LENGTH = 20; + + function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { + bytes memory buffer = new bytes(2 * length + 2); + buffer[0] = "0"; + buffer[1] = "x"; + for (uint256 i = 2 * length + 1; i > 1; --i) { + buffer[i] = _SYMBOLS[value & 0xf]; + value >>= 4; + } + require(value == 0, "Strings: hex length insufficient"); + return string(buffer); + } + + function toHexString(address addr) internal pure returns (string memory) { + return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); + } }