Skip to content

Commit

Permalink
Merge branch 'feat/chainlink' of github.com:morpho-labs/morpho-blue-o…
Browse files Browse the repository at this point in the history
…racles into merlin-review
  • Loading branch information
MerlinEgalite committed Oct 4, 2023
2 parents ef5cb20 + a5fdad8 commit 8a6bbf5
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import {IOracle} from "morpho-blue/interfaces/IOracle.sol";

import {AggregatorV3Interface, DataFeedLib} from "./libraries/DataFeedLib.sol";

/// @title Oracle4
/// @title OracleFourFeeds
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @notice Oracle using 4 Chainlink-compliant feeds to compute the price of a collateral token quoted in a borrowable
/// token within a Morpho Blue market.
contract Oracle4 is IOracle {
contract OracleFourFeeds is IOracle {
using DataFeedLib for AggregatorV3Interface;

/* IMMUTABLES */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import {IOracle} from "morpho-blue/interfaces/IOracle.sol";

import {AggregatorV3Interface, DataFeedLib} from "./libraries/DataFeedLib.sol";

/// @title Oracle2
/// @title OracleTwoFeeds
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @notice Oracle using 2 Chainlink-compliant feeds to compute the price of a collateral token quoted in a borrowable
/// token within a Morpho Blue market.
contract Oracle2 is IOracle {
contract OracleTwoFeeds is IOracle {
using DataFeedLib for AggregatorV3Interface;

/* IMMUTABLES */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "src/chainlink/Oracle4.sol";
import "src/chainlink/OracleFourFeeds.sol";
import "src/chainlink/libraries/ErrorsLib.sol";

// 8 decimals of precision
Expand All @@ -14,13 +14,13 @@ AggregatorV3Interface constant btcEthFeed = AggregatorV3Interface(0xdeb288F73706
// 8 decimals of precision
AggregatorV3Interface constant wBtcBtcFeed = AggregatorV3Interface(0xfdFD9C85aD200c506Cf9e21F1FD8dd01932FBB23);

contract OracleTest is Test {
contract OracleFourFeedsTest is Test {
function setUp() public {
vm.selectFork(vm.createFork(vm.envString("ETH_RPC_URL")));
}

function testOracleWbtcUsdc() public {
Oracle4 oracle = new Oracle4(wBtcBtcFeed, btcUsdFeed, usdcUsdFeed, AggregatorV3Interface(address(0)), 8, 6);
OracleFourFeeds oracle = new OracleFourFeeds(wBtcBtcFeed, btcUsdFeed, usdcUsdFeed, AggregatorV3Interface(address(0)), 8, 6);
(, int256 firstBaseAnswer,,,) = wBtcBtcFeed.latestRoundData();
(, int256 secondBaseAnswer,,,) = btcUsdFeed.latestRoundData();
(, int256 quoteAnswer,,,) = usdcUsdFeed.latestRoundData();
Expand All @@ -32,7 +32,7 @@ contract OracleTest is Test {
}

function testOracleUsdcWbtc() public {
Oracle4 oracle = new Oracle4(usdcUsdFeed, AggregatorV3Interface(address(0)), wBtcBtcFeed, btcUsdFeed, 6, 8);
OracleFourFeeds oracle = new OracleFourFeeds(usdcUsdFeed, AggregatorV3Interface(address(0)), wBtcBtcFeed, btcUsdFeed, 6, 8);
(, int256 baseAnswer,,,) = usdcUsdFeed.latestRoundData();
(, int256 firstQuoteAnswer,,,) = wBtcBtcFeed.latestRoundData();
(, int256 secondQuoteAnswer,,,) = btcUsdFeed.latestRoundData();
Expand All @@ -44,8 +44,8 @@ contract OracleTest is Test {
}

function testOracleWbtcEth() public {
Oracle4 oracle =
new Oracle4(wBtcBtcFeed, btcEthFeed, AggregatorV3Interface(address(0)), AggregatorV3Interface(address(0)), 8, 18);
OracleFourFeeds oracle =
new OracleFourFeeds(wBtcBtcFeed, btcEthFeed, AggregatorV3Interface(address(0)), AggregatorV3Interface(address(0)), 8, 18);
(, int256 firstBaseAnswer,,,) = wBtcBtcFeed.latestRoundData();
(, int256 secondBaseAnswer,,,) = btcEthFeed.latestRoundData();
assertEq(oracle.price(), (uint256(firstBaseAnswer) * uint256(secondBaseAnswer) * 10 ** (36 + 18 - 8 - 8 - 18)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "src/chainlink/Oracle2.sol";
import "src/chainlink/OracleTwoFeeds.sol";
import "src/chainlink/libraries/ErrorsLib.sol";

// 18 decimals of precision
Expand Down Expand Up @@ -30,48 +30,49 @@ contract FakeAggregator {
}
}

contract OracleTest is Test {
contract OracleTwoFeedsTest is Test {
function setUp() public {
vm.selectFork(vm.createFork(vm.envString("ETH_RPC_URL")));
}

function testOracleStEthUsdc() public {
Oracle2 oracle = new Oracle2(stEthEthFeed, usdcEthFeed, 18, 6);
OracleTwoFeeds oracle = new OracleTwoFeeds(stEthEthFeed, usdcEthFeed, 18, 6);
(, int256 baseAnswer,,,) = stEthEthFeed.latestRoundData();
(, int256 quoteAnswer,,,) = usdcEthFeed.latestRoundData();
assertEq(oracle.price(), uint256(baseAnswer) * 10 ** (36 + 18 + 6 - 18 - 18) / uint256(quoteAnswer));
}

function testOracleEthUsd() public {
Oracle2 oracle = new Oracle2(ethUsdFeed, AggregatorV3Interface(address(0)), 18, 0);
OracleTwoFeeds oracle = new OracleTwoFeeds(ethUsdFeed, AggregatorV3Interface(address(0)), 18, 0);
(, int256 expectedPrice,,,) = ethUsdFeed.latestRoundData();
assertEq(oracle.price(), uint256(expectedPrice) * 10 ** (36 - 18 - 8));
}

function testOracleStEthEth() public {
Oracle2 oracle = new Oracle2(stEthEthFeed, AggregatorV3Interface(address(0)), 18, 18);
OracleTwoFeeds oracle = new OracleTwoFeeds(stEthEthFeed, AggregatorV3Interface(address(0)), 18, 18);
(, int256 expectedPrice,,,) = stEthEthFeed.latestRoundData();
assertEq(oracle.price(), uint256(expectedPrice) * 10 ** (36 + 18 - 18 - 18));
assertApproxEqRel(oracle.price(), 1e36, 0.01 ether);
}

function testOracleEthStEth() public {
Oracle2 oracle = new Oracle2(AggregatorV3Interface(address(0)), stEthEthFeed, 18, 18);
OracleTwoFeeds oracle = new OracleTwoFeeds(AggregatorV3Interface(address(0)), stEthEthFeed, 18, 18);
(, int256 expectedPrice,,,) = stEthEthFeed.latestRoundData();
assertEq(oracle.price(), 10 ** (36 + 18 + 18 - 18) / uint256(expectedPrice));
assertApproxEqRel(oracle.price(), 1e36, 0.01 ether);
}

function testOracleUsdcUsd() public {
Oracle2 oracle = new Oracle2(usdcUsd, AggregatorV3Interface(address(0)), 6, 0);
OracleTwoFeeds oracle = new OracleTwoFeeds(usdcUsd, AggregatorV3Interface(address(0)), 6, 0);
assertApproxEqRel(oracle.price(), 1e36 / 1e6, 0.01 ether);
}

function testNegativeAnswer() public {
function testNegativeAnswer(int price) public {
vm.assume(price < 0);
FakeAggregator aggregator = new FakeAggregator();
Oracle2 oracle =
new Oracle2(AggregatorV3Interface(address(aggregator)), AggregatorV3Interface(address(0)), 18, 0);
aggregator.setAnwser(-1);
OracleTwoFeeds oracle =
new OracleTwoFeeds(AggregatorV3Interface(address(aggregator)), AggregatorV3Interface(address(0)), 18, 0);
aggregator.setAnwser(price);
vm.expectRevert(bytes(ErrorsLib.NEGATIVE_ANSWER));
oracle.price();
}
Expand Down

0 comments on commit 8a6bbf5

Please sign in to comment.