From af79d0b35d3280437e2cc70bfe1a58e8b6ea883e Mon Sep 17 00:00:00 2001 From: ryanbajollari <54822716+rbajollari@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:45:41 +0100 Subject: [PATCH] feat: OjoPTOraclePriceAdapter (#1) --- .env.example | 6 +++ .gitignore | 2 +- ...dleOracle.s.sol => OjoPendleOracles.s.sol} | 17 +++++++++ src/OjoPTOraclePriceAdapter.sol | 38 +++++++++++++++++++ src/interfaces/IPTOracle.sol | 6 +++ .../MinimalAggregatorV3Interface.sol | 17 +++++++++ 6 files changed, 85 insertions(+), 1 deletion(-) rename script/{OjoPendleOracle.s.sol => OjoPendleOracles.s.sol} (51%) create mode 100644 src/OjoPTOraclePriceAdapter.sol create mode 100644 src/interfaces/IPTOracle.sol create mode 100644 src/interfaces/MinimalAggregatorV3Interface.sol diff --git a/.env.example b/.env.example index e21592b..81c5248 100644 --- a/.env.example +++ b/.env.example @@ -2,5 +2,11 @@ ETH_RPC_URL= HOLESKY_RPC_URL= ETHERSCAN_API_KEY= +# OjoPendleOracle PT_ADDRESS= BASE_DISCOUNT_PER_YEAR= + +# OjoPTOraclePriceAdapter +PT_ORACLE= +MARKET= +DESCRIPTION= diff --git a/.gitignore b/.gitignore index 499e3c5..3ff91c0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ cache/ out/ # Ignores development broadcast logs -!/broadcast +broadcast /broadcast/*/31337/ /broadcast/**/dry-run/ diff --git a/script/OjoPendleOracle.s.sol b/script/OjoPendleOracles.s.sol similarity index 51% rename from script/OjoPendleOracle.s.sol rename to script/OjoPendleOracles.s.sol index 9f8d057..72311fc 100644 --- a/script/OjoPendleOracle.s.sol +++ b/script/OjoPendleOracles.s.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.19; import {Script} from "forge-std/Script.sol"; import {OjoPendleOracle} from "src/OjoPendleOracle.sol"; +import {OjoPTOraclePriceAdapter} from "src/OjoPTOraclePriceAdapter.sol"; import {console} from "forge-std/console.sol"; contract DeployOjoPendleOracle is Script { @@ -19,3 +20,19 @@ contract DeployOjoPendleOracle is Script { console.log("OjoPendleOracle Address:", address(ojoPendleOracle)); } } + +contract DeployOjoPTOraclePriceAdapter is Script { + function run() external { + address _ptoracle = vm.envAddress("PT_ORACLE"); + address _market = vm.envAddress("MARKET"); + string memory _description = vm.envString("DESCRIPTION"); + + vm.startBroadcast(); + + OjoPTOraclePriceAdapter ojoPTOraclePriceAdapter = new OjoPTOraclePriceAdapter(_ptoracle, _market, _description); + + vm.stopBroadcast(); + + console.log("OjoPTOraclePriceAdapter Address:", address(ojoPTOraclePriceAdapter)); + } +} diff --git a/src/OjoPTOraclePriceAdapter.sol b/src/OjoPTOraclePriceAdapter.sol new file mode 100644 index 0000000..ce69806 --- /dev/null +++ b/src/OjoPTOraclePriceAdapter.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.8.19; + +import {IPTOracle} from "./interfaces/IPTOracle.sol"; +import {MinimalAggregatorV3Interface} from "./interfaces/MinimalAggregatorV3Interface.sol"; + +contract OjoPTOraclePriceAdapter is MinimalAggregatorV3Interface { + uint8 public constant decimals = 18; + + address public immutable PTOracle; + + address public immutable market; + + string public description; + + constructor(address _ptoracle, address _market, string memory _description) { + require(_ptoracle != address(0), "_ptoracle zero address"); + require(_market != address(0), "_market zero address"); + + PTOracle = _ptoracle; + market = _market; + description = _description; + } + + /// @inheritdoc MinimalAggregatorV3Interface + /// @dev Returns zero for roundId, startedAt, updatedAt and answeredInRound. + /// @dev Silently overflows if `price`'s average is greater than `type(int256).max`. + function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80) { + IPTOracle oracle = IPTOracle(PTOracle); + + uint256 price = oracle.getPtToAssetRate( + market, + 900 // 15 mins twap duration + ); + + return (0, int256(price), 0, 0, 0); + } +} diff --git a/src/interfaces/IPTOracle.sol b/src/interfaces/IPTOracle.sol new file mode 100644 index 0000000..c33768a --- /dev/null +++ b/src/interfaces/IPTOracle.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +interface IPTOracle { + function getPtToAssetRate(address market, uint32 duration) external view returns (uint256); +} diff --git a/src/interfaces/MinimalAggregatorV3Interface.sol b/src/interfaces/MinimalAggregatorV3Interface.sol new file mode 100644 index 0000000..22887af --- /dev/null +++ b/src/interfaces/MinimalAggregatorV3Interface.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.5.0; + +/// @dev Inspired by +/// https://github.com/smartcontractkit/chainlink/blob/master/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol +/// @dev This is the minimal feed interface required by `MorphoChainlinkOracleV2`. +interface MinimalAggregatorV3Interface { + /// @notice Returns the precision of the feed. + function decimals() external view returns (uint8); + + /// @notice Returns Chainlink's `latestRoundData` return values. + /// @notice Only the `answer` field is used by `MorphoChainlinkOracleV2`. + function latestRoundData() + external + view + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); +}