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

You can create positions where you are always on profit and farm USDz

Summary

In the current implementation a user can choose his sizeDelta and he can deposit as much collateral in his account as he wants and in order to have his position in liquidatable state he needs to lose all his collateral in the account. This means you can create a position with really small margin compared to your collateral in your account which means at some point this position will be on profit and you can just close it and farm USDz

Vulnerability Details

This is how we check if someone's position is in liquidatable state now:

if (!TradingAccount.isLiquidatable(requiredMaintenanceMarginUsdX18, ctx.marginBalanceUsdX18)) {
continue;
}

And the marginBalanceUsdX18 is calculated in this function

function getMarginBalanceUsd(
Data storage self,
SD59x18 activePositionsUnrealizedPnlUsdX18
)
internal
view
returns (SD59x18 marginBalanceUsdX18)
{
// cache colllateral length
uint256 cachedMarginCollateralBalanceLength = self.marginCollateralBalanceX18.length();
// iterate over every collateral account has deposited
for (uint256 i; i < cachedMarginCollateralBalanceLength; i++) {
// read key/value from storage for current iteration
(address collateralType, uint256 balance) = self.marginCollateralBalanceX18.at(i);
// load collateral margin config for this collateral type
MarginCollateralConfiguration.Data storage marginCollateralConfiguration =
MarginCollateralConfiguration.load(collateralType);
// calculate the collateral's "effective" balance as:
// collateral_price * deposited_balance * collateral_loan_to_value_ratio
UD60x18 adjustedBalanceUsdX18 = marginCollateralConfiguration.getPrice().mul(ud60x18(balance)).mul(
ud60x18(marginCollateralConfiguration.loanToValue)
);
// add this account's "effective" collateral balance to cumulative output
marginBalanceUsdX18 = marginBalanceUsdX18.add(adjustedBalanceUsdX18.intoSD59x18());
}
// finally add the unrealized PNL to the cumulative output
marginBalanceUsdX18 = marginBalanceUsdX18.add(activePositionsUnrealizedPnlUsdX18);
}

As we can see we are collecting all of the collateral that we previously deposited in our account.

Let's review how a malicious user can create a position where he will always be on profit and just farm the USDz

Attacker deposits 10000$ as collateral and he opens a position with 100$

This means that in order for his position to be liquidated he needs to lose all of the 10000$

So your positions would need to be on 9900% loss to go from 100$ to a loss of 10,000$

The attacker will just trade in market like ETH/USD for example which means that he can just hold this position until his pnl goes positive and just close it. It is close to impossible for such a position to suddenly go to -9900%.

Impact

High because a malicious user can just use this strategy to farm USDz

Tools Used

Manual review

Recommendations

When checking if a user's position is liquidatable you should check if only his margin can cover the loss, not all of his collateral in the account. If a user has lost like 98% of his margin he should be then liquidated.

Updates

Lead Judging Commences

inallhonesty Lead Judge
11 months ago
inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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