For collaterals with less than 18 decimals, the formula used in tradingAccount.withdrawMarginUsd() is wrong,
function withdrawMarginUsd()is used for: 1. liquidation 2. charge orderFee, settlementFee and negative unsettled PnL.
For margins with less than 18 decimals(for example, WBTC has 8 decimals), There is a problem with the following logic:
convertUd60x18ToTokenAmount(requiredMarginInCollateralX18)will truncate the last 10 digits of 18 decimals, so that the actual value received by the receiver is always less than withdrawnMarginUsdX18. The difference between the two value is locked into the contract forever.
It is worth noting that withdrawMarginUsd() is executed multiple times in a single order. For users with multiple margins, this rounding issue can happen dozens of times.
If we assume withdrawMarginUsd() is executed ten times in an order and WBTC's price = 70000usd, that means 0.007usd worth of WBTC would be locked in the contract. As orders accumulate, users suffer more and more losses.
Likelihood: high - Every transaction for every user with a margin that is not 18 decimals will experience this.
+
Impact: low - Losses from a single order are small, but can accumulate.
=
Severity: medium
Manual review
Recalculate withdrawnMarginUsdX18 based on amountToTransfer
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.