Skip to content

Commit f630fbc

Browse files
committed
docs(oracle): clarify SCALE_FACTOR def
1 parent 16f372f commit f630fbc

File tree

1 file changed

+26
-18
lines changed

1 file changed

+26
-18
lines changed

src/ChainlinkOracle.sol

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,34 +53,42 @@ contract ChainlinkOracle is IOracle {
5353
uint256 baseTokenDecimals,
5454
uint256 quoteTokenDecimals
5555
) {
56-
// The vault parameter is used for ERC4626 tokens, to price its shares.
57-
// It is used to price `VAULT_CONVERSION_SAMPLE` of the vault shares, so it requires dividing by that number,
58-
// hence the division by `VAULT_CONVERSION_SAMPLE` in the `SCALE_FACTOR` definition.
56+
// The ERC4626 vault parameter is used to price `VAULT_CONVERSION_SAMPLE` of its shares, so it requires dividing
57+
// by that number, hence the division by `VAULT_CONVERSION_SAMPLE` in the `SCALE_FACTOR` definition.
5958
// Verify that vault = address(0) => vaultConversionSample = 1.
6059
require(
6160
address(vault) != address(0) || vaultConversionSample == 1, ErrorsLib.VAULT_CONVERSION_SAMPLE_IS_NOT_ONE
6261
);
62+
6363
VAULT = vault;
6464
VAULT_CONVERSION_SAMPLE = vaultConversionSample;
6565
BASE_FEED_1 = baseFeed1;
6666
BASE_FEED_2 = baseFeed2;
6767
QUOTE_FEED_1 = quoteFeed1;
6868
QUOTE_FEED_2 = quoteFeed2;
69-
// Let pB1 and pB2 be the base prices, and pQ1 and pQ2 the quote prices (price taking into account the
70-
// decimals of both tokens), in a common currency.
71-
// We tackle the most general case in the remainder of this comment, where we assume that no feed is the address
72-
// zero. Similar explanations would hold in the case where some of the feeds are the address zero.
73-
// Let dB1, dB2, dB3, and dQ1, dQ2, dQ3 be the decimals of the tokens involved.
74-
// For example, pB1 is the number of 1e(dB2) of the second base asset that can be obtained from 1e(dB1) of
75-
// the first base asset.
76-
// We notably have dB3 = dQ3, because those two quantities are the decimals of the same common currency.
77-
// Let fpB1, fpB2, fpQ1 and fpQ2 be the feed precision of the corresponding prices.
78-
// Chainlink feeds return pB1*1e(fpB1), pB2*1e(fpB2), pQ1*1e(fpQ1) and pQ2*1e(fpQ2).
79-
// Because the Blue oracle does not take into account decimals, `price()` should return
80-
// 1e36 * (pB1*1e(dB2-dB1) * pB2*1e(dB3-dB2)) / (pQ1*1e(dQ2-dQ1) * pQ2*1e(dQ3-dQ2))
81-
// Yet `price()` returns (pB1*1e(fpB1) * pB2*1e(fpB2) * SCALE_FACTOR) / (pQ1*1e(fpQ1) * pQ2*1e(fpQ2))
82-
// So 1e36 * pB1 * pB2 * 1e(-dB1) / (pQ1 * pQ2 * 1e(-dQ1)) =
83-
// (pB1*1e(fpB1) * pB2*1e(fpB2) * SCALE_FACTOR) / (pQ1*1e(fpQ1) * pQ2*1e(fpQ2))
69+
70+
// In the following comment, we explain in the general case (where we assume that no feed is the address
71+
// zero) how to scale the output price as Morpho Blue expects, given the input feed prices.
72+
// Similar explanations would hold in the case where some of the feeds are the address zero.
73+
74+
// Let A, B1, B2, Q1, Q2 be 5 assets, each respectively having dA, dB1, dB2, dQ1, dQ2 decimals.
75+
// Let pB1 and pB2 be the base prices, and pQ1 and pQ2 the quote prices, so that:
76+
// - pB1 is the quantity of assets B2 that can be exchanged for 1e(dB1) assets B1, with dB2 decimals.
77+
// - pB2 is the quantity of assets A that can be exchanged for 1e(dB2) assets B2, with dA decimals.
78+
// - pQ1 is the quantity of assets Q2 that can be exchanged for 1e(dQ1) assets Q1, with dQ2 decimals.
79+
// - pQ2 is the quantity of assets A that can be exchanged for 1e(dQ2) assets B2, with dA decimals.
80+
81+
// Because Blue's oracle does not take into account decimals, this oracle's `price()` should return:
82+
// 1e36 * (pB1 * 1e(dB2 - dB1)) * (pB2 * 1e(dA - dB2)) / (pQ1 * 1e(dQ2 - dQ1)) * (pQ2 * 1e(dA - dQ2))
83+
// = 1e36 * (pB1 * 1e(-dB1) * pB2) / (pQ1 * 1e(-dQ1) * pQ2)
84+
85+
// Let fpB1, fpB2, fpQ1, fpQ2 be the feed precision of the respective prices pB1, pB2, pQ1, pQ2.
86+
// Chainlink feeds return pB1 * 1e(fpB1), pB2 * 1e(fpB2), pQ1 * 1e(fpQ1) and pQ2 * 1e(fpQ2).
87+
88+
// Based on the implementation of `price()` below, the value of `SCALE_FACTOR` should thus satisfy:
89+
// (pB1 * 1e(fpB1)) * (pB2 * 1e(fpB2)) * SCALE_FACTOR / ((pQ1 * 1e(fpQ1)) * (pQ2 * 1e(fpQ2)))
90+
// = 1e36 * pB1 * pB2 * 1e(-dB1) / (pQ1 * pQ2 * 1e(-dQ1))
91+
8492
// So SCALE_FACTOR = 1e36 * 1e(-dB1) * 1e(dQ1) * 1e(-fpB1) * 1e(-fpB2) * 1e(fpQ1) * 1e(fpQ2)
8593
// = 1e(36 + dQ1 + fpQ1 + fpQ2 - dB1 - fpB1 - fpB2)
8694
SCALE_FACTOR = 10

0 commit comments

Comments
 (0)