peanuts
high
The price of DAI in terms of USD is not calculated properly.
This is the current calculation of DAI in terms of USD. Note that the return value has to be in 18 decimal places in order to integrate well with other contracts in the protocol.
return
(wethPriceUSD * 1e18) /
((DAIWethPrice + uint256(price) * 1e10) / 2);
}
The pricing formula comprises 3 types of price. wethPriceUSD, DAIWethPrice and the price variable from priceFeedDAIETH.
wethPriceUSD
is derived from ethOracle price, presumably the ETH/USD Chainlink oracle, and returns the ETH price in USD.DAIWethPrice
is derived from the on-chain Uniswap oracle, and calculates the WETH price in terms of DAI.price
is derived from priceFeedDAIETH oracle, which is the DAI/ETH Chainlink oracle,
uint256 wethPriceUSD = ethOracle.getPriceUSD();
uint256 DAIWethPrice = DAIEthOracle.quoteSpecificPoolsWithTimePeriod(
(, int256 price, , , ) = priceFeedDAIETH.latestRoundData();
Assuming all integrations work well, this is how the calculation will go:
(wethPriceUSD * 1e18) / ((DAIWethPrice + uint256(price) * 1e10) / 2);
wethPriceUSD
= 181759000000 (8 decimal places)
DAIWethPrice
= 1817331962824889681175 (18 decimal places)
price
= 551720649183640 ( 18 decimal places)
(181759000000 * 1e18) / ((1817331962824889681175 + 551720649183640 * 1e10) / 2) = 65866.3581832, which is not the correct DAI/USD price.
Here is why it is different:
price
is returned in 18 decimals already. There is no need to scale by another 1e10price
returns DAI price in ETH, means it returns 0.0005517206, and not ETH price in DAI. The intention of addingDAIWethPrice
andprice
and then dividing by 2 is to get the average of ETH price in terms of DAI using an onChain oracle (uniswap) and an off chain oracle (chainlink). However,DAIWethPrice
returns ETH price in DAI (1 ETH is worth 1817 DAI), andprice
returns DAI price in ETH (1 DAI is worth 0.00055 ETH), so the addition does not make sense.
References:
-
price
(priceFeedDAIETH) DAI/ETH Chainlink oracle: https://data.chain.link/ethereum/mainnet/stablecoins/dai-eth Etherscan: https://etherscan.io/address/0x773616e4d11a78f511299002da57a0a94577f1f4#readContract -
wethPriceUSD
(ethOracle.getPriceUSD()) ETH/USD Chainlink oracle: https://data.chain.link/ethereum/mainnet/crypto-usd/eth-usd Etherscan: https://etherscan.io/address/0x5f4ec3df9cbd43714fe2740f5e3616155c5b8419#readContract -
DAIEthOracle
(DAIWethPrice) quoteSpecificPoolsWithTimePeriod: https://etherscan.io/address/0xB210CE856631EeEB767eFa666EC7C1C57738d438#readContract
(Calculation will differ due to fluctuation in prices)
Wrong pricing of DAI will break protocol especially since DAI is integral to the protocol. (rebalance, collateral etc.)
Manual Review
Recommend using the DAI/USD chainlink oracle for simplicity: 0xaed0c38402a5d19df6e4c03f4e2dced6e29c1ee9. https://data.chain.link/ethereum/mainnet/stablecoins/dai-usd
If intent is to calculate DAI-ETH and then ETH-USD, make sure that the decimal calculations are correct. wethPriceUSD returns 8 decimals so have to scale up by 10. Afterwards, scale by 1e18 since other contracts in the protocol assumes oracle returns decimals in 1e18 format.
((wethPriceUSD * 1e10) / DAIWethPrice) * 1e18 ((181759000000 * 1e10) / (1817331962824889681175) ) * 1e18 = 1.000142e+18
1 DAI = 1.000142e18 USD