DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: medium
Valid

Native ETH sent as a result of Liquidations or ADL is not handled.

Summary

Native ETH can be sent to the account address in case of Liquidations or ADL per GMX documentation (https://github.com/gmx-io/gmx-synthetics#Integrations). However, the callback function afterOrderExecution on GmxProxy.sol does not handle the case of native token being sent.

Vulnerability Details

afterOrderExecution function is responsible for handling the callbacks from GMX. In case of any tokens being sent to the GmxProxycontract by GMX, it is transferred to the PerpetualVault contract via the logic of the callback function. However, the logic only supports ERC20 transfers but not native token transfers. This will lead to a situation where the callback call will revert as a result of trying to transfer ERC20 that does not exist or the amount that does not exist(it depends on what the GMX will use as the place holder for native ETH in the eventData.addressItems.items.valuefield). Which in the end will break the flow of the protocol at certain situations due to the end of the call not reaching PerpetualVault.afterLiquidationExecution().

if (order.numbers.orderType == Order.OrderType.Liquidation) {
if (eventData.uintItems.items[0].value > 0) {
IERC20(eventData.addressItems.items[0].value).safeTransfer(perpVault, eventData.uintItems.items[0].value);
}
if (eventData.uintItems.items[1].value > 0) {
IERC20(eventData.addressItems.items[1].value).safeTransfer(perpVault, eventData.uintItems.items[1].value);
}
IPerpetualVault(perpVault).afterLiquidationExecution();
} else if (msg.sender == address(adlHandler)) {
uint256 sizeInUsd = dataStore.getUint(keccak256(abi.encode(positionKey, SIZE_IN_USD)));
if (eventData.uintItems.items[0].value > 0) {
IERC20(eventData.addressItems.items[0].value).safeTransfer(perpVault, eventData.uintItems.items[0].value);
}
if (eventData.uintItems.items[1].value > 0) {
IERC20(eventData.addressItems.items[1].value).safeTransfer(perpVault, eventData.uintItems.items[1].value);
}
if (sizeInUsd == 0) {
IPerpetualVault(perpVault).afterLiquidationExecution();
}

Impact

Broken flow of the protocol due to the callback on PerpetualVault.afterLiquidationExecution()not being triggered potentially leading to DOS. Protocol flow may not be aware whether the position was liquidated or full size reduction was carried out by ADL. The ETH sent to the contract may be partially lost if it is used as the posititionExecutionFee before the protocol manually transfers them out.

Tools Used

Manual review.

Recommendations

Validate the addresses of the tokens sent inside the afterOrderExecution logic and handle the reverts with try catch blocks.

Updates

Lead Judging Commences

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

invalid_gmx_send_WETH_fees

`TokenUtils.sol::sendNativeToken()` has no reason to fail since there is a `receive` function without any instruction in the GmxProxy. It’s the simpliest and cheapest transfer possible. Good finding, but there is no likelihood.

Appeal created

kirkeelee Submitter
8 months ago
kirkeelee Submitter
8 months ago
n0kto Lead Judge
8 months ago
n0kto Lead Judge 8 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_ADL_unwrap_ether_for_WETH_market

Impact: High, native ETH is sent to Gamma and won’t be accounted or withdrawn with the shares. Lead to revert of the transfer in the proxy. Likelihood: Low/Medium: Happen during ADL order (too many PnL), only on WETH/USDC market.

Support

FAQs

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