-
Notifications
You must be signed in to change notification settings - Fork 1
XAPI Oracle #178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
hujw77
wants to merge
9
commits into
main
Choose a base branch
from
echo/xapi
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
XAPI Oracle #178
Changes from 6 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
30f3461
xapi oracle
hujw77 26c0782
forge install: xapi-contracts
hujw77 1c23f97
xapi oracle deps
hujw77 9b37987
forge install: chainlink
hujw77 4e78f92
add xapi oracle
hujw77 42b4c06
rename event name
hujw77 e15f7d3
change version
hujw77 4674d31
fix
hujw77 988f816
convert address to string
hujw77 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule xapi-contracts
added at
92466b
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,6 @@ | ||
| 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/ | ||
| @chainlink/=lib/chainlink/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.0; | ||
|
|
||
| import "../Verifier.sol"; | ||
| import "../interfaces/IORMP.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, 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; | ||
| address public immutable EXAGGREGATOR; | ||
|
|
||
| address public owner; | ||
| // chainId => price | ||
| mapping(uint256 => uint256) public feeOf; | ||
| // operator => isApproved | ||
| mapping(address => bool) public approvedOf; | ||
|
|
||
| struct DataSource { | ||
| string name; | ||
| string url; | ||
| string method; | ||
| string resultPath; | ||
| } | ||
|
|
||
| uint256 requestId; | ||
|
|
||
| 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, address exagg) { | ||
| PROTOCOL = ormp; | ||
| owner = dao; | ||
| XAPI = xapi; | ||
| EXAGGREGATOR = exagg; | ||
| } | ||
|
|
||
| receive() external payable {} | ||
|
|
||
| function version() public pure returns (string memory) { | ||
| 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 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 | ||
| payable | ||
| onlyApproved | ||
| { | ||
| 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 XAPIRequestMade(requestId, requestData); | ||
| payable(msg.sender).transfer(msg.value - fee_); | ||
| } | ||
|
|
||
| function xapiCallback(uint256 requestId_, ResponseData memory response) external onlyXAPI { | ||
| require(requestId_ == requestId, "requestId"); | ||
|
hujw77 marked this conversation as resolved.
Outdated
|
||
| if (response.errorCode != 0) { | ||
| (uint256 chainId, address channel, uint256 msgIndex, bytes32 msgHash) = | ||
| abi.decode(response.result, (uint256, address, uint256, bytes32)); | ||
| IORMP(PROTOCOL).importHash(chainId, channel, msgIndex, msgHash); | ||
| emit XAPIConsumeResult(requestId, response.result, response.errorCode); | ||
| } else { | ||
| emit XAPIConsumeError(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; | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.