DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: medium
Invalid

Collateral with a loanToValue value of 0 cannot be withdrawn if the user does not meet the initialMarginRequrements

Lines of code

https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/perpetuals/branches/TradingAccountBranch.sol#L386-L392

Impact

In case a collateral/margin is removed from the collateralLiquidationPriority and its loanToValue is set to 0, a user can not withdraw his deposited collateral if his account does not meet the initialMargin requirements. This results in the collateral being stuck in the protocol until the user meets the initialMargin requirements even though the collateral has no value in the protocol.

Proof of Concept

Users can withdraw collateral they deposited to the protocol by calling withdrawMargin. Before the withdrawal is executed it is ensure that the account still meets the initialMarginRequirements for the open positions after the withdrawal of the collateral. For this, the required initialMargin for the open positions is determined and checked against the marginBalance of the account after the collateral is withdrawn:

(UD60x18 requiredInitialMarginUsdX18,, SD59x18 accountTotalUnrealizedPnlUsdX18) =
tradingAccount.getAccountMarginRequirementUsdAndUnrealizedPnlUsd(0, SD59x18_ZERO);
// get trader's margin balance
SD59x18 marginBalanceUsdX18 = tradingAccount.getMarginBalanceUsd(accountTotalUnrealizedPnlUsdX18);
// check against initial margin requirement as initial margin > maintenance margin
// hence prevent the user from withdrawing all the way to the maintenance margin
// so that they couldn't be liquidated very soon afterwards if their position
// goes against them even a little bit
tradingAccount.validateMarginRequirement(requiredInitialMarginUsdX18, marginBalanceUsdX18, UD60x18_ZERO);

The issue arises from the fact that this check is also done even if the collateral which should be withdrawn is no longer contributing to the marginBalance of the account. This can happen when the collateral was active before when the user deposited it but got removed from the collateralLiquidationPriority and therefore its loanToValue value was set to 0 after that. This would lead to the collateral being stuck in the protocol if the account does not meet the initialMargin requirements even though the collateral has no value in the protocol.

Recommended Mitigation Steps

Add an if statement at the beginning of the margin checks that determines if the loanToValue value for the collateral that should be withdrawn is 0. If this is the case, skip the margin checks and execute the withdrawal.

function withdrawMargin(uint128 tradingAccountId, address collateralType, uint256 amount) external {
tradingAccount.withdraw(collateralType, amountX18);
+// load collateral margin config for this collateral type
+ MarginCollateralConfiguration.Data storage marginCollateralConfiguration = MarginCollateralConfiguration.load(collateralType);
+if(marginCollateralConfiguration.loanToValue != 0){
// load account required initial margin requirement & unrealized USD profit/loss
// ignores "required maintenance margin" output parameter
(UD60x18 requiredInitialMarginUsdX18,, SD59x18 accountTotalUnrealizedPnlUsdX18) =
tradingAccount.getAccountMarginRequirementUsdAndUnrealizedPnlUsd(0, SD59x18_ZERO);
+}
// finally send the tokens
IERC20(collateralType).safeTransfer(msg.sender, amount);
emit LogWithdrawMargin(msg.sender, tradingAccountId, collateralType, amount);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

`withdrawMargin` will fail because `validateMarginRequirement` will not pass after removing a collateral from the collateralLiquidationPriority. Stuck funds

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

`withdrawMargin` will fail because `validateMarginRequirement` will not pass after removing a collateral from the collateralLiquidationPriority. Stuck funds

Appeal created

benrai Submitter
over 1 year ago
inallhonesty Lead Judge
over 1 year ago
benrai Submitter
over 1 year ago
inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

`withdrawMargin` will fail because `validateMarginRequirement` will not pass after removing a collateral from the collateralLiquidationPriority. Stuck funds

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!