DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

In `PerpetualVault::_withdraw` function, positive PnL is not added to `collateralDeltaAmount`, which leads to users not receiving profit that belongs to them

Description:

In the withdrawing process, when there is an open GMX position which is in profit, the calculated pnl value does not get added to collateralDeltaAmount, which gets passed to PerpetualVault::_createDecreasePosition function as a parameter that gets set as initialCollateralDeltaAmount in the orderData that gets passed to GMX when sending the order request.

@> int256 pnl = vaultReader.getPnl(curPositionKey, prices, sizeDeltaInUsd);
if (pnl < 0) {
collateralDeltaAmount = collateralDeltaAmount - feeAmount - uint256(-pnl) / prices.shortTokenPrice.max;
} else {
@> collateralDeltaAmount = collateralDeltaAmount - feeAmount;
}
uint256 acceptablePrice = abi.decode(metadata, (uint256));
@> _createDecreasePosition(collateralDeltaAmount, sizeDeltaInUsd, beenLong, acceptablePrice, prices);
}
}
IGmxProxy.OrderData memory orderData = IGmxProxy.OrderData({
market: market,
indexToken: indexToken,
initialCollateralToken: address(collateralToken),
swapPath: swapPath,
isLong: _isLong,
sizeDeltaUsd: sizeDeltaInUsd,
@> initialCollateralDeltaAmount: collateralDeltaAmount,
amountIn: 0,
callbackGasLimit: callbackGasLimit,
acceptablePrice: acceptablePrice,
minOutputAmount: 0
});
_gmxLock = true;
@> gmxProxy.createOrder(orderType, orderData);
}

When executing MarketDecrease orders, GMX transfers the amount of collateral tokens to the owner of the position (which is GMXProxy) based on the provided initialCollateralDeltaAmount value. Due to this, GMXProxy will receive a collateral token amount that does not include the user's PnL, and the user who initiated the withdrawal will receive only this amount.

Impact:

Users will not receive the profit from GMX positions, which completely negates the user incentive to use the Gamma protocol.

Recommended Mitigation:

Add the pnl to collateralDeltaAmount if the pnl is positive:

int256 pnl = vaultReader.getPnl(curPositionKey, prices, sizeDeltaInUsd);
if (pnl < 0) {
collateralDeltaAmount = collateralDeltaAmount - feeAmount - uint256(-pnl) / prices.shortTokenPrice.max;
} else {
- collateralDeltaAmount = collateralDeltaAmount - feeAmount;
+ collateralDeltaAmount = collateralDeltaAmount - feeAmount + uint256(pnl) / prices.shortTokenPrice.max;
}
uint256 acceptablePrice = abi.decode(metadata, (uint256));
_createDecreasePosition(collateralDeltaAmount, sizeDeltaInUsd, beenLong, acceptablePrice, prices);
}
}
Updates

Lead Judging Commences

n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

Suppositions

There is no real proof, concrete root cause, specific impact, or enough details in those submissions. Examples include: "It could happen" without specifying when, "If this impossible case happens," "Unexpected behavior," etc. Make a Proof of Concept (PoC) using external functions and realistic parameters. Do not test only the internal function where you think you found something.

Support

FAQs

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

Give us feedback!