Skip to content

Commit

Permalink
fix: scale factor computation
Browse files Browse the repository at this point in the history
  • Loading branch information
MathisGD committed Oct 3, 2023
1 parent 2861c82 commit 16622f5
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 18 deletions.
10 changes: 8 additions & 2 deletions src/chainlink/Oracle2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,15 @@ contract Oracle2 is IOracle {
) {
BASE_FEED = baseFeed;
QUOTE_FEED = quoteFeed;
// SCALE_FACTOR = 10 ** (36 + (baseTokenDecimals - baseFeedDecimals) - (quoteTokenDecimals - quoteFeedDecimals))
// We note pB the base price, and pQ the quote price (price of 1e(decimals) asset).
// We want to return 1e36 * (pB/1e(bDecimals) / (pQ/1e(qDecimals)).
// Chainlink returns pB * bFeedPrecision and pQ * qFeedPrecision.
// So we have 1e36 * (pB/1e(bDecimals) / (pQ/1e(qDecimals) = pB * 1e(bFeedPrecision) * SCALE_FACTOR / (pQ *
// 1e(qFeedPrecision))
// So SCALE_FACTOR = 1e36 / 1e(bDecimals) * 1e(qDecimals) * 1e(qFeedPrecision) / 1e(bFeedPrecision)
// So SCALE_FACTOR = 1e(36 + qDecimals + qFeedPrecision - bDecimals - bFeedPrecision)
SCALE_FACTOR =
10 ** (36 + baseTokenDecimals + quoteFeed.getDecimals() - baseFeed.getDecimals() - quoteTokenDecimals);
10 ** (36 + quoteTokenDecimals + quoteFeed.getDecimals() - baseFeed.getDecimals() - baseTokenDecimals);
}

/* PRICE */
Expand Down
6 changes: 2 additions & 4 deletions src/chainlink/Oracle4.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,10 @@ contract Oracle4 is IOracle {
SECOND_BASE_FEED = secondBaseFeed;
FIRST_QUOTE_FEED = firstQuoteFeed;
SECOND_QUOTE_FEED = secondQuoteFeed;
// SCALE_FACTOR = 10 ** (36 + (firstQuoteFeedDecimals + secondQuoteFeedDecimals - quoteTokenDecimals) -
// (firstBaseFeedDecimals + secondBaseFeedDecimals - baseTokenDecimals))
SCALE_FACTOR = 10
** (
36 + baseTokenDecimals + firstQuoteFeed.getDecimals() + secondQuoteFeed.getDecimals()
- firstBaseFeed.getDecimals() - secondBaseFeed.getDecimals() - quoteTokenDecimals
36 + quoteTokenDecimals + firstQuoteFeed.getDecimals() + secondQuoteFeed.getDecimals()
- firstBaseFeed.getDecimals() - secondBaseFeed.getDecimals() - baseTokenDecimals
);
}

Expand Down
21 changes: 15 additions & 6 deletions test/chainlink/Oracle2Test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ AggregatorV3Interface constant stEthEthFeed = AggregatorV3Interface(0x86392dC19c
AggregatorV3Interface constant usdcEthFeed = AggregatorV3Interface(0x986b5E1e1755e3C2440e960477f25201B0a8bbD4);
// 8 decimals of precision
AggregatorV3Interface constant ethUsdFeed = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);
// 8 decimals of precision
AggregatorV3Interface constant usdcUsd = AggregatorV3Interface(0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6);

contract FakeAggregator {
int256 public answer;
Expand All @@ -37,25 +39,32 @@ contract OracleTest is Test {
Oracle2 oracle = new Oracle2(stEthEthFeed, usdcEthFeed, 18, 6);
(, int256 baseAnswer,,,) = stEthEthFeed.latestRoundData();
(, int256 quoteAnswer,,,) = usdcEthFeed.latestRoundData();
assertEq(oracle.price(), uint256(baseAnswer) * 10 ** (36 + 18 + 18 - 18 - 6) / uint256(quoteAnswer));
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);
(, int256 expectedPrice,,,) = ethUsdFeed.latestRoundData();
assertEq(oracle.price(), uint256(expectedPrice) * 10 ** (36 + 18 - 8));
assertEq(oracle.price(), uint256(expectedPrice) * 10 ** (36 - 18 - 8));
}

function testOracleStEthEth() public {
Oracle2 oracle = new Oracle2(stEthEthFeed, AggregatorV3Interface(address(0)), 18, 0);
Oracle2 oracle = new Oracle2(stEthEthFeed, AggregatorV3Interface(address(0)), 18, 18);
(, int256 expectedPrice,,,) = stEthEthFeed.latestRoundData();
assertEq(oracle.price(), uint256(expectedPrice) * 10 ** (36 + 18 - 18));
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, 0, 18);
Oracle2 oracle = new Oracle2(AggregatorV3Interface(address(0)), stEthEthFeed, 18, 18);
(, int256 expectedPrice,,,) = stEthEthFeed.latestRoundData();
assertEq(oracle.price(), 10 ** (36 + 18 - 18) / uint256(expectedPrice));
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);
assertApproxEqRel(oracle.price(), 1e36 / 1e6, 0.01 ether);
}

function testNegativeAnswer() public {
Expand Down
10 changes: 4 additions & 6 deletions test/chainlink/Oracle4Test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ contract OracleTest is Test {
(, int256 quoteAnswer,,,) = usdcUsdFeed.latestRoundData();
assertEq(
oracle.price(),
(uint256(firstBaseAnswer) * uint256(secondBaseAnswer) * 10 ** (36 + 8 + 8 - 6 - 8 - 8))
/ uint256(quoteAnswer)
(uint256(firstBaseAnswer) * uint256(secondBaseAnswer) * 10 ** (36 + 8 + 6 - 8 - 8 - 8)) / uint256(quoteAnswer)
);
}

Expand All @@ -38,16 +37,15 @@ contract OracleTest is Test {
(, int256 secondQuoteAnswer,,,) = btcUsdFeed.latestRoundData();
assertEq(
oracle.price(),
(uint256(baseAnswer) * 10 ** (36 + 8 + 8 + 6 - 8 - 8))
/ (uint256(firstQuoteAnswer) * uint256(secondQuoteAnswer))
(uint256(baseAnswer) * 10 ** (36 + 8 + 8 + 8 - 6 - 8)) / (uint256(firstQuoteAnswer) * uint256(secondQuoteAnswer))
);
}

function testOracleWbtcEth() public {
Oracle4 oracle =
new Oracle4(wBtcBtcFeed, btcEthFeed, AggregatorV3Interface(address(0)), AggregatorV3Interface(address(0)), 8, 0);
new Oracle4(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 + 8 - 8 - 18)));
assertEq(oracle.price(), (uint256(firstBaseAnswer) * uint256(secondBaseAnswer) * 10 ** (36 + 18 - 8 - 8 - 18)));
}
}

0 comments on commit 16622f5

Please sign in to comment.