Traders may decrease the loss via decrease the position's margin
Summary
When traders decrease the position's margin, _executeReduceMargin did not consider current Pnl.
Vulnerability Detail
In function updatePositionMargin, we can decrease one isolated position's margin and transfer some margin to users' account.
The vulnerability exists in function _executeReduceMargin. Function _executeReduceMargin will calculate maxReduceMarginInUsd. Users' reduceMargin cannot be larger than maxReduceMarginInUsd. The calculation of maxReduceMarginInUsd is initialMarginInUsd - margins for maximum leverage based on current position.
The vulnerability is that the system does not consider the positions' Pnl. If this position is at the edge of liquidation, he may get back a little funds by closing this position. However, the trader can get back more funds via decreasing margin. In below Poc, even if this position is unhealthy and needed to be liquidated and the user cannot close this position, the user can still get part of funds back via decreasing margin.
function updatePositionMargin(uint256 requestId, UpdatePositionMargin.Request memory request) external {
Position.Props storage position = Position.load(request.positionKey);
......
Symbol.Props memory symbolProps = Symbol.load(position.symbol);
Account.Props storage accountProps = Account.load(request.account);
//add margin, transfer from vault to LP Pool
if (request.isAdd) {
......
} else {
// decrease margin, transfer from LP Pool to the trader.
uint256 reduceMarginAmount = _executeReduceMargin(position, symbolProps, request.updateMarginAmount, true);
VaultProcess.transferOut(symbolProps.stakeToken, request.marginToken, request.account, reduceMarginAmount);
position.emitPositionUpdateEvent(requestId, Position.PositionUpdateFrom.DECREASE_MARGIN, 0);
}
function _executeReduceMargin(
Position.Props storage position,
Symbol.Props memory symbolProps,
uint256 reduceMargin,
bool needUpdateLeverage
) internal returns (uint256) {
AppConfig.SymbolConfig memory symbolConfig = AppConfig.getSymbolConfig(symbolProps.code);
//calculate minimum margin for max leverage, left margin should not be less than minimum margin
uint256 maxReduceMarginInUsd = position.initialMarginInUsd -
CalUtils.divRate(position.qty, symbolConfig.maxLeverage).max(
AppTradeConfig.getTradeConfig().minOrderMarginUSD
);
jennifer37
High
Traders may decrease the loss via decrease the position's margin
Summary
When traders decrease the position's margin,
_executeReduceMargin
did not consider current Pnl.Vulnerability Detail
In function
updatePositionMargin
, we can decrease one isolated position's margin and transfer some margin to users' account. The vulnerability exists in function_executeReduceMargin
. Function_executeReduceMargin
will calculatemaxReduceMarginInUsd
. Users'reduceMargin
cannot be larger thanmaxReduceMarginInUsd
. The calculation ofmaxReduceMarginInUsd
isinitialMarginInUsd
- margins for maximum leverage based on current position.The vulnerability is that the system does not consider the positions' Pnl. If this position is at the edge of liquidation, he may get back a little funds by closing this position. However, the trader can get back more funds via decreasing margin. In below Poc, even if this position is unhealthy and needed to be liquidated and the user cannot close this position, the user can still get part of funds back via decreasing margin.
Poc
Add this part into increaseMarketOrder.test.ts.
Impact
Traders can get back some funds via decreasing one position's margin. LP holders will lose some expected profits.
Code Snippet
https://github.com/sherlock-audit/2024-05-elfi-protocol/blob/main/elfi-perp-contracts/contracts/process/PositionMarginProcess.sol#L370-L383
Tool used
Manual Review
Recommendation
Consider the unrealised Pnl when we decrease one position's margin.