When a liquidator attempts to liquidate another user, they specify an amount of debtToCover
to pay to liquidate a specified collateral
for a user
. As part of this function, to determine how much collateral to return to the liquidator, it calls tokenAmountFromDebtCovered
, which should return the amount of collateral equal to the USD value of the DSC token they are using to pay down the debt. However, this function always returns an amount of collateral assuming the collateral has 18 decimals of precision. This means that if the collateral has < 18 decimals of precision, this will severely overpay the liquidator for the amount of debt they are paying down. This can even cause the liquidation to revert, if the tokenAmountFromDebtCovered
function returns a value larger than the amount of collateral deposited by that user.
In the liquidate
function, the following call is made:
The getTokenAmountFromUsd
function is defined as follows:
Let's consider the case where we are using a collateral with 6 decimals of precision and 1e6 of this collateral is worth 1000 USD. Here the liquidator is intending to pay off 10 USD in debt, so debtToCover
is 10e18. The output from getTokenAmountFromUsd
will be the following: 10e18 * 1e18 / (1000e8 * 1e10)
= 10e18 / 1000
= 1e16
of collateral. However, considering the collateral has 6 decimals of precision, this returns an amount of collateral worth significantly more than 10 USD, and so the liquidator is getting overpaid.
The logic of the getTokenAmountFromUsd
function called during liquidations will revert or overpay collateral to the liquidator for the amount of debt they are paying down. This breaks the entire protocol design.
Manual review
The getTokenAmountFromUsd
function needs to be updated to convert the returned amount to use the native precision of the collateral
token.
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.