DSCEngine contract arbitrarily assumes that the price feeds will have 8 decimals. If the token basket contains tokens for which the price feed has different number of decimals, the price calculation will be wrong, resulting in the system malfuction.
The DSCEngine contract uses the following formula for calculating the USD value of a token:
The ADDITIONAL_FEED_PRECISION
constant is used to adjust the price returned from the oracle to 18 decimals. This constant is currently hardcoded to 1e10
, as the contract assumes the price feed will have 8 decimals.
While this holds true for the token basket used in the deploy script (WETH and WBTC), the documentation states:
The system is meant to be such that someone could fork this codebase, swap out WETH & WBTC for any basket of assets they like, and the code would work the same.
This assumption is not true for all of the price feeds. As per ChainLink documentation, an example of price feed that will break this assumption is AMPL/USD
price feed on Ethereum Mainnet, which has 18 decimals.
Using incorrect decimals number in price calculation can lead to severe issues, including users taking debts unproportional to their collaterals. Please consider the following scenario:
The Foundry DeFi Stablecoin codebase is forked and deployed with the WAMPL token included in the assets basket. The AMPL/USD
price is at 11 USD at the moment.
The attacker deposits the collateral of 1 AMPL. Because the system assumes that the oracle price feed for AMPL/USD
has 8 decimals, it will multiply the price by ADDITIONAL_FEED_PRECISION = 1e10
in the USD value calculation. The actual number of decimals for AMPL/USD
feed is 18. The collateral value in USD for the attacker should be 11 USD, but it will be 1e10
times bigger - 110 000 000 000 USD.
The attacker is now able to mint up to 55 billion DSC, even though his real collateral value is only 11 USD.
Manual Review
Consider implementing the additional state variable, which will be a mapping holding the additional feed precisions for each of the token in the basket:
The mapping could be initialized in the constructor as such:
This mapping could be then utilized in the calculations instead of an arbitrary ADDITIONAL_FEED_PRECISION
constant.
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.