The ShortRecordFacet::increaseCollateral()
is vulnerable to front-running attacks, as the function calculates the Short's collateral ratio using a cached price, which can be front-run by attackers.
As a result, an attacker can spend less collateral than the actual to reset the liquidation flag from their flagged Short position.
The increaseCollateral()
can be invoked by a shorter to increase collateral (zETH
) of their active Short position. After increasing the collateral, the increaseCollateral()
will execute the LibShortRecord::getCollateralRatio()
to calculate the Short's collateral ratio (cRatio
). Then, if the resulting cRatio
is above the primaryLiquidationCR
threshold, the function will invoke the LibShortRecord::resetFlag()
to reset the liquidation flag of the Short position.
However, the increaseCollateral()
is vulnerable to front-running attacks since the getCollateralRatio()
will calculate the cRatio
using a cached price retrieved from the LibOracle::getPrice()
.
Let's say Chainlink has updated the price to be higher than the protocol's oracle price (cached). An attacker (i.e., shorter) can front-run the protocol's oracle price update and execute the increaseCollateral()
. Since the protocol's oracle still retains the lower price (lower debt than the actual), the attacker can spend less collateral than the actual to reset the liquidation flag, deferring their Short position from being liquidated by the MarginCallPrimaryFacet::liquidate()
(Primary liquidation method).
Note that to liquidate the attacker's Short again, a flagger must flag that Short again. It will take at least 10 hours (the default of the firstLiquidationTime
parameter) for the flagged Short to be liquidatable.
Consequently, this vulnerability can indirectly increase bad debt to the Ditto
protocol. The protocol can become insolvent, and the protocol's minted stable assets (e.g., cUSD) can eventually be de-pegged.
https://github.com/Cyfrin/2023-09-ditto/blob/a93b4276420a092913f43169a353a6198d3c21b9/contracts/facets/ShortRecordFacet.sol#L55
https://github.com/Cyfrin/2023-09-ditto/blob/a93b4276420a092913f43169a353a6198d3c21b9/contracts/facets/ShortRecordFacet.sol#L59-L61
https://github.com/Cyfrin/2023-09-ditto/blob/a93b4276420a092913f43169a353a6198d3c21b9/contracts/libraries/LibShortRecord.sol#L27
This vulnerability enables an attacker (i.e., shorter) to spend less collateral than the actual to reset the liquidation flag from their flagged Short position, deferring their Short position from being liquidated (Primary liquidation method).
Note that to liquidate the attacker's Short again, a flagger must flag that Short again. It will take at least 10 hours (the default of the firstLiquidationTime
parameter) for the flagged Short to be liquidatable.
The vulnerability can indirectly increase bad debt to the Ditto
protocol. The protocol can become insolvent, and the protocol's minted stable assets (e.g., cUSD) can eventually be de-pegged.
Manual Review
Since the cached oracle price is prone to front-running attacks, always execute the LibOracle::getOraclePrice()
to get the accurate price from Chainlink.
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.