Cds amounts to reduce from each chain are incorrect and will lead to the inability to withdraw cds in one of the chains
Summary
The cds amount to reduce on liquidations from each chain is given by the share of cds deposit, but then the liquidation amount by each cds depositor is given by the available liquidation amount pro-rata to the depositor's liquidation amount, which renders the first share calculation incorrect.
Root Cause
In CDSLib.sol:728, totalCdsDepositedAmount is reduced by params.cdsDepositDetails.depositedAmount - params.cdsDepositDetails.liquidationAmount, but in BorrowLib:390, the share is given by the cds amounts of each chain, not the available liquidation amounts.
Internal pre-conditions
None.
External pre-conditions
None.
Attack Path
- Consider 2 chains, A has 1000 cds deposited with 1000 available liquidation amount; chain B has 19000 cds deposited, also 1000 available liquidation amount. 1 borrower is liquidated with 1 ETH deposited at a price of 1000 USD / ETH and 800 USDa borrowed.
- The calculations in BorrowLib::getLiquidationAmountProportions() yield, for chain A, B, respectively:
- shares 0.05;0.95.
_liqAmountis 820 (1000 - 800 - 20, where 800 is the debt and 20 is the amount to return to abond, given by(1000 - 800) * 10 / 100)liqAmountToGetis 41;779 (820 multiplied by the shares of each chain)cdsProfitsare 9;171 (total is 180, 1000 - 820, these 2 are multiplied by shares)cdsAmounts32;608 (chainA cds amount to get is 41 - 9 = 32 and chainB is 779 - 171 = 608).
Chain B will have 18000 cds withdrawn (consider that the price goes back up in the meantime and they don't take losses), and only the cds depositor that provided liquidation amount is left. As it will fetch 608 cds amount from the cds, it becomes 19000 - 18000 - 608 = 392. Then, when it loops through the liquidations that happened, share is 50% (availableLiquidationAmount / totalAvailableLiquidationAmount), so params.cdsDepositDetails.liquidationAmount becomes 1000 - 0.5 * 820 = 590. Then, totalCdsDepositedAmount -= (params.cdsDepositDetails.depositedAmount - params.cdsDepositDetails.liquidationAmount); = 392 - (1000 - 590) = -18, which underflows. This proves that Chain B is overcharged.
Impact
The chain with the most cds will be charged to much cds as the liquidation amount to subtract for each depositor is given by the available liquidation amount, but the cds was removed based on the cds amount.
PoC
See above.
Mitigation
Consider using share calculation in borrowingLiquidation.sol based on the available liquidation amounts themselves.