Skip to content

Commit

Permalink
add oracle adptor
Browse files Browse the repository at this point in the history
  • Loading branch information
JoscelynFarr committed Mar 28, 2024
1 parent fd7598d commit ce27ef0
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 29 deletions.
50 changes: 21 additions & 29 deletions src/oracle/OracleAdaptor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ pragma solidity ^0.8.19;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
import "../interfaces/internal/IChainlink.sol";

contract OracleAdaptor is Ownable {
Expand All @@ -15,44 +17,31 @@ contract OracleAdaptor is Ownable {
uint256 public immutable usdcHeartbeat;
address public immutable usdcSource;
address public immutable chainlink;
uint256 public roundId;
bytes32 public immutable priceId;
uint256 public price;
uint256 public priceThreshold;
bool public isSelfOracle;

// Align with chainlink
event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
IPyth public pyth;

event UpdateThreshold(uint256 oldThreshold, uint256 newThreshold);

constructor(
address _chainlink,
address _pythContract,
uint256 _decimalsCorrection,
uint256 _heartbeatInterval,
uint256 _usdcHeartbeat,
address _usdcSource,
uint256 _priceThreshold
uint256 _priceThreshold,
bytes32 _priceId
) {
chainlink = _chainlink;
pyth = IPyth(_pythContract);
decimalsCorrection = 10 ** _decimalsCorrection;
heartbeatInterval = _heartbeatInterval;
usdcHeartbeat = _usdcHeartbeat;
usdcSource = _usdcSource;
priceThreshold = _priceThreshold;
}

function setMarkPrice(uint256 newPrice) external onlyOwner {
price = newPrice;
emit AnswerUpdated(SafeCast.toInt256(price), roundId, block.timestamp);
roundId += 1;
}

function turnOnJOJOOracle() external onlyOwner {
isSelfOracle = true;
}

function turnOffJOJOOracle() external onlyOwner {
isSelfOracle = false;
priceId = _priceId;
}

function updateThreshold(uint256 newPriceThreshold) external onlyOwner {
Expand All @@ -68,26 +57,29 @@ contract OracleAdaptor is Ownable {
require(block.timestamp - updatedAt <= heartbeatInterval, "ORACLE_HEARTBEAT_FAILED");
require(block.timestamp - usdcUpdatedAt <= usdcHeartbeat, "USDC_ORACLE_HEARTBEAT_FAILED");
uint256 tokenPrice = (SafeCast.toUint256(rawPrice) * 1e8) / SafeCast.toUint256(usdcPrice);
return (tokenPrice * 1e18) / decimalsCorrection;
return tokenPrice;
}

function getPrice() internal view returns (uint256) {
uint256 chainLinkPrice = getChainLinkPrice();
if (isSelfOracle) {
uint256 JOJOPrice = price;
uint256 diff = JOJOPrice >= chainLinkPrice ? JOJOPrice - chainLinkPrice : chainLinkPrice - JOJOPrice;
require((diff * 1e18) / chainLinkPrice <= priceThreshold, "deviation is too big");
return price;
} else {
try pyth.getPrice(priceId) returns (PythStructs.Price memory pythPriceStruct) {
uint256 pythPrice = SafeCast.toUint256(pythPriceStruct.price);
uint256 diff = pythPrice >= chainLinkPrice ? pythPrice - chainLinkPrice : chainLinkPrice - pythPrice;
if ((diff * 1e18) / chainLinkPrice <= priceThreshold) {
return chainLinkPrice;
} else {
return pythPrice;
}
} catch {
return chainLinkPrice;
}
}

function getMarkPrice() external view returns (uint256) {
return getPrice();
return (getPrice() * 1e18) / decimalsCorrection;
}

function getAssetPrice() external view returns (uint256) {
return getPrice();
return (getPrice() * 1e18) / decimalsCorrection;
}
}
32 changes: 32 additions & 0 deletions src/oracle/PythOracleAdaptor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Copyright 2022 JOJO Exchange
SPDX-License-Identifier: BUSL-1.1
*/

pragma solidity ^0.8.19;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";

contract PythOracleAdaptor is Ownable {
IPyth public pyth;

constructor(address _pythContract) {
pyth = IPyth(_pythContract);
}

function setMarkPrice(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64[] calldata publishTimes
)
external
payable
onlyOwner
{
// Update the on-chain Pyth price(s)
uint256 fee = pyth.getUpdateFee(updateData);
pyth.updatePriceFeedsIfNecessary{ value: fee }(updateData, priceIds, publishTimes);
}
}

0 comments on commit ce27ef0

Please sign in to comment.