105 lines
3.7 KiB
Solidity
105 lines
3.7 KiB
Solidity
|
// SPDX-License-Identifier: MIT
|
||
|
pragma solidity ^0.6.12;
|
||
|
|
||
|
import "@openzeppelin/contracts/math/SafeMath.sol";
|
||
|
import "@openzeppelin/contracts/access/Ownable.sol";
|
||
|
|
||
|
import "./interfaces/DioneStakingInterface.sol";
|
||
|
|
||
|
contract DioneOracle is Ownable {
|
||
|
using SafeMath for uint256;
|
||
|
|
||
|
uint256 private requestCounter;
|
||
|
uint256 constant public MAXIMUM_DELAY = 5 minutes;
|
||
|
DioneStakingInterface public dioneStaking;
|
||
|
|
||
|
struct OracleRequest {
|
||
|
uint8 originChain; // origin blockchain for request
|
||
|
string requestType; // rpc call type
|
||
|
string requestParams; // rpc call params
|
||
|
address callbackAddress; // callback address for users request contract
|
||
|
bytes4 callbackMethodID; // method for users request contract
|
||
|
uint256 reqID; // request counter
|
||
|
uint256 deadline;
|
||
|
bytes data;
|
||
|
}
|
||
|
|
||
|
mapping(uint256 => bytes32) private pendingRequests;
|
||
|
mapping(address => bool) private activeNodes;
|
||
|
|
||
|
event NewOracleRequest(
|
||
|
uint8 originChain,
|
||
|
string requestType,
|
||
|
string requestParams,
|
||
|
address callbackAddress,
|
||
|
bytes4 callbackMethodID,
|
||
|
uint256 reqID,
|
||
|
uint256 deadline
|
||
|
);
|
||
|
|
||
|
event CancelOracleRequest(
|
||
|
uint256 reqID
|
||
|
);
|
||
|
|
||
|
event SubmittedOracleRequest(
|
||
|
string requestParams,
|
||
|
address callbackAddress,
|
||
|
bytes4 callbackMethodID,
|
||
|
uint256 reqID,
|
||
|
uint256 deadline,
|
||
|
bytes data
|
||
|
);
|
||
|
|
||
|
modifier onlyPendingRequest(uint256 _reqID) {
|
||
|
require(pendingRequests[_reqID] != 0, "Invalid requestId");
|
||
|
_;
|
||
|
}
|
||
|
|
||
|
modifier onlyActiveNode() {
|
||
|
require(activeNodes[msg.sender], "Not an active miner");
|
||
|
_;
|
||
|
}
|
||
|
|
||
|
constructor(DioneStakingInterface _dioneStaking) public {
|
||
|
dioneStaking = _dioneStaking;
|
||
|
}
|
||
|
|
||
|
function requestOracles(uint8 _originChain, string memory _requestType, string memory _requestParams, address _callbackAddress, bytes4 _callbackMethodID) public returns (uint256) {
|
||
|
requestCounter += 1;
|
||
|
require(pendingRequests[requestCounter] == 0, "This counter is not unique");
|
||
|
uint256 requestDeadline = now.add(MAXIMUM_DELAY);
|
||
|
pendingRequests[requestCounter] = keccak256(abi.encodePacked(_requestParams, _callbackAddress, _callbackMethodID, requestCounter, requestDeadline));
|
||
|
|
||
|
emit NewOracleRequest(_originChain, _requestType, _requestParams, _callbackAddress, _callbackMethodID, requestCounter, requestDeadline);
|
||
|
return requestCounter;
|
||
|
}
|
||
|
|
||
|
function cancelOracleRequest(string memory _requestParams, bytes4 _callbackMethodID, uint256 _reqID, uint256 _requestDeadline) public {
|
||
|
bytes32 requestHash = keccak256(abi.encodePacked(_requestParams, msg.sender, _callbackMethodID, _reqID, _requestDeadline));
|
||
|
require(requestHash == pendingRequests[_reqID], "Request hash do not match it's origin");
|
||
|
require(_requestDeadline <= now, "Request didn't reached it's deadline");
|
||
|
|
||
|
delete pendingRequests[_reqID];
|
||
|
emit CancelOracleRequest(_reqID);
|
||
|
}
|
||
|
|
||
|
function submitOracleRequest(string memory _requestParams, address _callbackAddress, bytes4 _callbackMethodID, uint256 _reqID, uint256 _requestDeadline, bytes memory _data) public onlyActiveNode returns (bool) {
|
||
|
bytes32 requestHash = keccak256(abi.encodePacked(_requestParams, _callbackAddress, _callbackMethodID, _reqID, _requestDeadline));
|
||
|
require(pendingRequests[_reqID] == requestHash, "Params do not match request ID");
|
||
|
delete pendingRequests[_reqID];
|
||
|
dioneStaking.mine(msg.sender);
|
||
|
(bool success, ) = _callbackAddress.call(abi.encodeWithSelector(_callbackMethodID, _reqID, _data));
|
||
|
emit SubmittedOracleRequest(_requestParams, _callbackAddress, _callbackMethodID, _reqID, _requestDeadline, _data);
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
function setNodeStatus(address _miner, bool _status) public {
|
||
|
activeNodes[_miner] = _status;
|
||
|
}
|
||
|
|
||
|
function isActiveNode(address _miner) public view returns (bool) {
|
||
|
return activeNodes[_miner];
|
||
|
}
|
||
|
|
||
|
}
|