Skip to content

Commit fb3c9a5

Browse files
authored
Merge pull request #27 from morpho-labs/feat/chainlink-lone-sample
2 parents e6175d5 + 4eb24d6 commit fb3c9a5

File tree

2 files changed

+26
-24
lines changed

2 files changed

+26
-24
lines changed

src/ChainlinkOracle.sol

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ contract ChainlinkOracle is IOracle {
1818

1919
/// @notice Vault.
2020
IERC4626 public immutable VAULT;
21-
/// @notice Conversion sample decimals. The decimals of the shares sample used to convert to the underlying asset.
22-
/// @notice Should be chosen such that converting `10 ** CONVERSION_SAMPLE_DECIMALS` to assets has enough precision.
23-
uint256 public immutable CONVERSION_SAMPLE_DECIMALS;
21+
/// @notice Vault conversion sample. The sample amount of shares used to convert to the underlying asset.
22+
/// @notice Should be chosen such that converting `VAULT_CONVERSION_SAMPLE` to assets has enough precision.
23+
uint256 public immutable VAULT_CONVERSION_SAMPLE;
2424
/// @notice First base feed.
2525
AggregatorV3Interface public immutable BASE_FEED_1;
2626
/// @notice Second base feed.
@@ -39,7 +39,7 @@ contract ChainlinkOracle is IOracle {
3939
/// @param baseFeed2 Second base feed. Pass address zero if the price = 1.
4040
/// @param quoteFeed1 First quote feed. Pass address zero if the price = 1.
4141
/// @param quoteFeed2 Second quote feed. Pass address zero if the price = 1.
42-
/// @param conversionSampleDecimals Conversion sample decimals. Pass 0 if the oracle does not use a vault.
42+
/// @param vaultConversionSample Vault conversion sample. Pass 1 if the oracle does not use a vault.
4343
/// @param baseTokenDecimals Base token decimals.
4444
/// @param quoteTokenDecimals Quote token decimals.
4545
constructor(
@@ -48,15 +48,15 @@ contract ChainlinkOracle is IOracle {
4848
AggregatorV3Interface baseFeed2,
4949
AggregatorV3Interface quoteFeed1,
5050
AggregatorV3Interface quoteFeed2,
51-
uint256 conversionSampleDecimals,
51+
uint256 vaultConversionSample,
5252
uint256 baseTokenDecimals,
5353
uint256 quoteTokenDecimals
5454
) {
5555
// The vault parameter is used for ERC4626 tokens, to price its shares.
56-
// It is used to price `10 ** CONVERSION_SAMPLE_DECIMALS` of the vault shares, so it requires dividing
57-
// by that number, hence the `CONVERSION_SAMPLE_DECIMALS` subtraction in the `SCALE_FACTOR` definition.
56+
// It is used to price `VAULT_CONVERSION_SAMPLE` of the vault shares, so it requires dividing by that number,
57+
// hence the division by `VAULT_CONVERSION_SAMPLE` in the `SCALE_FACTOR` definition.
5858
VAULT = vault;
59-
CONVERSION_SAMPLE_DECIMALS = conversionSampleDecimals;
59+
VAULT_CONVERSION_SAMPLE = vaultConversionSample;
6060
BASE_FEED_1 = baseFeed1;
6161
BASE_FEED_2 = baseFeed2;
6262
QUOTE_FEED_1 = quoteFeed1;
@@ -78,16 +78,16 @@ contract ChainlinkOracle is IOracle {
7878
SCALE_FACTOR = 10
7979
** (
8080
36 + quoteTokenDecimals + quoteFeed1.getDecimals() + quoteFeed2.getDecimals() - baseTokenDecimals
81-
- baseFeed1.getDecimals() - baseFeed2.getDecimals() - CONVERSION_SAMPLE_DECIMALS
82-
);
81+
- baseFeed1.getDecimals() - baseFeed2.getDecimals()
82+
) / VAULT_CONVERSION_SAMPLE;
8383
}
8484

8585
/* PRICE */
8686

8787
/// @inheritdoc IOracle
8888
function price() external view returns (uint256) {
89-
uint256 sample = 10 ** CONVERSION_SAMPLE_DECIMALS;
90-
return (VAULT.getAssets(sample) * BASE_FEED_1.getPrice() * BASE_FEED_2.getPrice() * SCALE_FACTOR)
91-
/ (QUOTE_FEED_1.getPrice() * QUOTE_FEED_2.getPrice());
89+
return (
90+
VAULT.getAssets(VAULT_CONVERSION_SAMPLE) * BASE_FEED_1.getPrice() * BASE_FEED_2.getPrice() * SCALE_FACTOR
91+
) / (QUOTE_FEED_1.getPrice() * QUOTE_FEED_2.getPrice());
9292
}
9393
}

test/ChainlinkOracleTest.sol

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ contract ChainlinkOracleTest is Test {
3333
}
3434

3535
function testOracleWbtcUsdc() public {
36-
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, wBtcBtcFeed, btcUsdFeed, usdcUsdFeed, feedZero, 0, 8, 6);
36+
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, wBtcBtcFeed, btcUsdFeed, usdcUsdFeed, feedZero, 1, 8, 6);
3737
(, int256 firstBaseAnswer,,,) = wBtcBtcFeed.latestRoundData();
3838
(, int256 secondBaseAnswer,,,) = btcUsdFeed.latestRoundData();
3939
(, int256 quoteAnswer,,,) = usdcUsdFeed.latestRoundData();
@@ -45,7 +45,7 @@ contract ChainlinkOracleTest is Test {
4545
}
4646

4747
function testOracleUsdcWbtc() public {
48-
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, usdcUsdFeed, feedZero, wBtcBtcFeed, btcUsdFeed, 0, 6, 8);
48+
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, usdcUsdFeed, feedZero, wBtcBtcFeed, btcUsdFeed, 1, 6, 8);
4949
(, int256 baseAnswer,,,) = usdcUsdFeed.latestRoundData();
5050
(, int256 firstQuoteAnswer,,,) = wBtcBtcFeed.latestRoundData();
5151
(, int256 secondQuoteAnswer,,,) = btcUsdFeed.latestRoundData();
@@ -57,56 +57,57 @@ contract ChainlinkOracleTest is Test {
5757
}
5858

5959
function testOracleWbtcEth() public {
60-
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero,wBtcBtcFeed, btcEthFeed, feedZero, feedZero, 0, 8, 18);
60+
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero,wBtcBtcFeed, btcEthFeed, feedZero, feedZero, 1, 8, 18);
6161
(, int256 firstBaseAnswer,,,) = wBtcBtcFeed.latestRoundData();
6262
(, int256 secondBaseAnswer,,,) = btcEthFeed.latestRoundData();
6363
assertEq(oracle.price(), (uint256(firstBaseAnswer) * uint256(secondBaseAnswer) * 10 ** (36 + 18 - 8 - 8 - 18)));
6464
}
6565

6666
function testOracleStEthUsdc() public {
67-
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, stEthEthFeed, feedZero, usdcEthFeed, feedZero,0, 18, 6);
67+
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, stEthEthFeed, feedZero, usdcEthFeed, feedZero, 1, 18, 6);
6868
(, int256 baseAnswer,,,) = stEthEthFeed.latestRoundData();
6969
(, int256 quoteAnswer,,,) = usdcEthFeed.latestRoundData();
7070
assertEq(oracle.price(), uint256(baseAnswer) * 10 ** (36 + 18 + 6 - 18 - 18) / uint256(quoteAnswer));
7171
}
7272

7373
function testOracleEthUsd() public {
74-
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, ethUsdFeed, feedZero, feedZero, feedZero, 0, 18, 0);
74+
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, ethUsdFeed, feedZero, feedZero, feedZero, 1, 18, 0);
7575
(, int256 expectedPrice,,,) = ethUsdFeed.latestRoundData();
7676
assertEq(oracle.price(), uint256(expectedPrice) * 10 ** (36 - 18 - 8));
7777
}
7878

7979
function testOracleStEthEth() public {
80-
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, stEthEthFeed, feedZero, feedZero, feedZero, 0, 18, 18);
80+
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, stEthEthFeed, feedZero, feedZero, feedZero, 1, 18, 18);
8181
(, int256 expectedPrice,,,) = stEthEthFeed.latestRoundData();
8282
assertEq(oracle.price(), uint256(expectedPrice) * 10 ** (36 + 18 - 18 - 18));
8383
assertApproxEqRel(oracle.price(), 1e36, 0.01 ether);
8484
}
8585

8686
function testOracleEthStEth() public {
87-
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, feedZero, feedZero, stEthEthFeed, feedZero, 0, 18, 18);
87+
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, feedZero, feedZero, stEthEthFeed, feedZero, 1, 18, 18);
8888
(, int256 expectedPrice,,,) = stEthEthFeed.latestRoundData();
8989
assertEq(oracle.price(), 10 ** (36 + 18 + 18 - 18) / uint256(expectedPrice));
9090
assertApproxEqRel(oracle.price(), 1e36, 0.01 ether);
9191
}
9292

9393
function testOracleUsdcUsd() public {
94-
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, usdcUsdFeed, feedZero, feedZero, feedZero, 0, 6, 0);
94+
ChainlinkOracle oracle = new ChainlinkOracle(vaultZero, usdcUsdFeed, feedZero, feedZero, feedZero, 1, 6, 0);
9595
assertApproxEqRel(oracle.price(), 1e36 / 1e6, 0.01 ether);
9696
}
9797

9898
function testNegativeAnswer(int256 price) public {
9999
price = bound(price, type(int256).min, -1);
100100
ChainlinkAggregatorMock aggregator = new ChainlinkAggregatorMock();
101101
ChainlinkOracle oracle =
102-
new ChainlinkOracle(vaultZero, AggregatorV3Interface(address(aggregator)), feedZero, feedZero, feedZero, 0, 18, 0);
102+
new ChainlinkOracle(vaultZero, AggregatorV3Interface(address(aggregator)), feedZero, feedZero, feedZero, 1, 18, 0);
103103
aggregator.setAnwser(price);
104104
vm.expectRevert(bytes(ErrorsLib.NEGATIVE_ANSWER));
105105
oracle.price();
106106
}
107107

108108
function testSDaiEthOracle() public {
109-
ChainlinkOracle oracle = new ChainlinkOracle(sDaiVault, daiEthFeed, feedZero, feedZero, feedZero, 18, 18, 18);
109+
ChainlinkOracle oracle =
110+
new ChainlinkOracle(sDaiVault, daiEthFeed, feedZero, feedZero, feedZero, 10 ** 18, 18, 18);
110111
(, int256 expectedPrice,,,) = daiEthFeed.latestRoundData();
111112
assertEq(
112113
oracle.price(),
@@ -115,7 +116,8 @@ contract ChainlinkOracleTest is Test {
115116
}
116117

117118
function testSDaiUsdcOracle() public {
118-
ChainlinkOracle oracle = new ChainlinkOracle(sDaiVault, daiEthFeed, feedZero, usdcEthFeed, feedZero, 18, 18, 6);
119+
ChainlinkOracle oracle =
120+
new ChainlinkOracle(sDaiVault, daiEthFeed, feedZero, usdcEthFeed, feedZero, 10 ** 18, 18, 6);
119121
(, int256 baseAnswer,,,) = daiEthFeed.latestRoundData();
120122
(, int256 quoteAnswer,,,) = usdcEthFeed.latestRoundData();
121123
assertEq(

0 commit comments

Comments
 (0)