Improper decimal precision handling for the non 18 decimal ERC20 token can result in DOS for the many user and their collateral being locked forever
Protocol is design to work perfectly for the 18-decimal ERC20 tokens, however it can fail for decimal other than 18, such as WBTC (one of the key collateral token) which has 8 decimal on Ethereum Mainnet.
There are two fold issue with this :
liquidate()
function uses getTokenAmountFromUsd()
wherein it returns the token amount in 18 decimals instead of the tokens decimal (8 for the case-in-point). as a result protocols liquidate()
ends up consider 10,000,000,000 times more collateral than it is supposed to, essentially it will revert in most cases (as the chances of any user having that much collateral are very rare).
Health factor calculations in _revertIfHealthFactorIsBroken()
accounts for all of the users collateral token values in USD, then sums it up in for loop. At that time getUsdValue()
is used to fetch the USD values.
Problem here is that it returns these value in tokens decimal instead of 18 decimal, As a result total value summation will be incorrect.
Lets consider the case wherein the user has put in 1 token of WETH(18 Decimals) and 1 token of WBTC(8 Decimals) as collateral. Lets Also assume WETH is at 2000 USD and 1 WBTC is at 25000 USD.
So, ideally its total collateral should be worth 27000 USD and ideally getAccountCollateralValue()
should return 27000e18.
But, what will happen is that getUsdValue()
will return 2000e18 for WETH as it should and in case of WBTC it will return 25000e8 (instead of 25000e18).
As a result getAccountCollateralValue()
will return 2000000002500000000000 (~2000e18) implying collateral is worth ~2000 USD instead of 27000 USD.
_revertIfHealthFactorIsBroken()
end up reverting where it should not, essentially breaking the protocol for many users.
Since _revertIfHealthFactorIsBroken()
and liquidate()
will be broken due to this, it will lead to manyb users being DOS of the many important functionality lead to their funds being stuck in protocol forever.
Manual Review
Implement proper precision calculation considering the decimals of token under calculation for liquidate()
functions getTokenAmountFromUsd()
so that it returns the token amount in tokens native decimals
In similar way for the _revertIfHealthFactorIsBroken()
function implement precision calculation such that all the USD values return by getUsdValue()
are in 18 decimals, which will be summed up accurately in getAccountCollateralValue()
leading to proper calculation.
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.