The protocol assumes that every oracle price feed using USD has 8 decimals but in reality some XXX/USD price feed oracles can have a different decimal count, for example, 18 decimals.
In the current implementation, the protocol assumes (uint256(price) * ADDITIONAL_FEED_PRECISION
has 18 decimals, since it thinks uint256(price)
has always 8 decimals and that multiplied by ADDITIONAL_FEED_PRECISION
(1e10) results in 18 decimals.
`return (usdAmountInWei * PRECISION) / (uint256(price) * ADDITIONAL_FEED_PRECISION);`
However, there are tokens with USD price feed's decimals different than 8 (for example AMPL / USD feed decimals are 18). Since the protocol states they wish to support any price feed, it is important to also support these edge cases in the price feed oracles.
To showcase this issue, we have created a plug-and-play POC you can test. To try it, create a file in your test
folder called POC_Oracle_without_8_decimals.t.sol
and paste the content of this gist: https://gist.github.com/TheNaubit/39074a56cddcccdf979f7fd37b798207
Then run the POC by running this command: forge test --match-contract POC_Oracle_without_8_decimals -vvv
Similar reports in other contests:
This breaks the basic protocol functionality and makes it impossible to support all the Oracle price feeds. It also makes the users receive a wrong amount of DSC tokens when minting using collateral with an oracle price feed with other than 8 decimals. We set this as a high since when minting DSC using a collateral token with other than 8 decimals, the amount the user receives is way off the amount they should receive, breaking the protocol and impacting the user funds.
Manual review and Foundry.
Instead of assuming the oracle decimals are 8, use the decimals()
function the oracle has to normalize the returned price value to one using always 18 decimals.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.