totalCdsDepositedAmountWithOptionFees is incorrectly reduced in CDSLib::withdrawUser(), leading to stuck option fees
Summary
totalCdsDepositedAmountWithOptionFees in CDSLib::withdrawUser() is reduced by:
totalCdsDepositedAmountWithOptionFees -= (params.cdsDepositDetails.depositedAmount - params.cdsDepositDetails.liquidationAmount + params.optionsFeesToGetFromOtherChain);This is incorrect as the correct amount to reduce in option fees is params.optionFees - params.optionsFeesToGetFromOtherChain, not optionsFeesToGetFromOtherChain in this chain. As such, depending on the cds amounts of each chain, it will lead to too many/little option fees registered in the local chain, which will lead to stuck option fees.###
Root Cause
In CDSLib.sol:731, totalCdsDepositedAmountWithOptionFees is reduced by the incorrect amount.
Internal pre-conditions
None.
External pre-conditions
None.
Attack Path
- Cds depositor withdraws, having option fees, in which
params.optionsFeesToGetFromOtherChainis null. Suppose a liquidation happened of 500, deposited amount is 1000 and options fees are 50, the resultingtotalCdsDepositedAmountWithOptionFeesis :
totalCdsDepositedAmountWithOptionFees -= (params.cdsDepositDetails.depositedAmount - params.cdsDepositDetails.liquidationAmount + params.optionsFeesToGetFromOtherChain); = 550 - (1000 - 500 + 0) = 50Note: for simplicity, it was assumed that the liquidation that happened reduced totalCdsDepositedAmountWithOptionFees by 500, which is not precise but it's an okay approximation for this example. The user withdraws the option fees, but the CDS contract still has the 50 option fees stored in totalCdsDepositedAmountWithOptionFees, even though it is not actually backed.
Impact
As totalCdsDepositedAmountWithOptionFees is 50, but the global totalCdsDepositedAmountWithOptionFees is null (it was correctly decreased), it will lead to incorrect calculations when getting the option fees proportions. For example, if someone deposits 1000 cds and another user deposits borrows (suppose it pays more 50 USD), it will add option fees on deposit. Then, when the borrower withdraws and the cds depositor withdraws, getOptionsFeesProportions() will calculate totalOptionFeesInOtherChain as 1050 - 1100, which underflows.
PoC
See above.
Mitigation
The correct code is:
totalCdsDepositedAmountWithOptionFees -= (params.cdsDepositDetails.depositedAmount - params.cdsDepositDetails.liquidationAmount + (params.optionFees - params.optionsFeesToGetFromOtherChain));