Depositor funds are at severe risk due to front-run attacks and slippage mishandling. An emergencyClose()
can lead to complete investment loss, The same issue observed in other functions (processDepositFailureLiquidityWithdrawal and processWithdraw) but with less impact.
The emergencyClose()
function repays all debt to the lendingVault
contract, then sets the status to closed
. Subsequently, users who deposited into the strategy contract can withdraw their deposits.
If the contract balance of one token is insufficient to cover its debt, the contract swaps the other token for the necessary amount using swapTokensForExactTokens
.
Notice that the _sp
struct includes the _sp.slippage
parameter. Here, _sp.amountIn
represents the entire contract balance of tokenFrom
, while _sp.amountOut
represent only the necessary amount to settle the debt of tokenTo
. This function is vulnerable to front-running if the contract's tokenFrom
balance exceeds the required amount to swap for amountOut
of tokenTo
. In such cases, all remaining tokens from _tokenFrom
can be stolen in a front-run attack, as the _sp.slippage
parameter has no effect in this scenario and we can see that here :
the contract first call GMXManager.swapTokensForExactTokens(self, _sp)
then call GMXWorker.swapTokensForExactTokens(self, sp);
then call self.swapRouter.swapTokensForExactTokens(sp)
notice that the function swapTokensForExactTokens
calls exactOutputSingle
from uniswap router and the _sp.slipage
have no effect .
the vault faces a significant risk, losing all remaining assets, which primarily consist of depositors' funds. This vulnerability is exacerbated by the Vault contract withdrawing liquidity from GMX without performing any swaps during the emergencyPause
action, leaving withdrawed liquidity in terms of both tokens and making swaps in emergencyClose
will be almost always necessary.
The same vulnerability also exists in the processDepositFailureLiquidityWithdrawal and processWithdraw functions. However, the impact in the emergencyClose()
function is significantly more severe compared to these cases. but the vulnerability is the same.
consider the following sinario :
assume that The vault is a long vault has a debt of 10000
tokenA
.
When the contract paused, it withdrawed 5000 tokenA
and 10000 tokenB
. so The contract still needs 5000 tokenA
to cover all the debt.
The contract attempts to swap a maximum of tokenB
to obtain the required 5000 tokenA
. Typically, this swap requires 6000 tokenB
to yield 5000 tokenA
. After the swap, there are 4000 tokenB
left, representing users deposits. These deposits can only be redeemed after the debt is settled.
The amountIn
parameter is set to 10000 tokenB
. A malicious actor exploit this by front-running the swap, inflating the price. The contract ends up swapping 10000 tokenB
for 5000 tokenA
and repays the debt.
After the swap and debt repayment, the vault's balance becomes zero, leaving no funds to cover user deposits.
NOTICE
Depositors' funds in this case are always will be in terms oftokenFrom
(or tokenB in our example), ensuring consistent losses. - In a Neutral strategy, the attacker must keep enoughtokenFrom
to the contract to paytokenFrom
debt to prevent transaction from revert and only take all the depositors funds.
in emergencyClose()
all depositors loses all thier deposits .
in processDepositFailureLiquidityWithdrawal one user lose all his deposit (the failed deposit).
in processWithdraw user have the ability to set the minTokenOut
he will get but still possible that the user lose his funds if he misspass the right amount.
vs code
manual review
after the swap. make sure that amountIn
swapped for amountOut
Get swapped for a reasonable price(in a specific buffer) using chainlink Oracle and if not revert.
Impact: High Likelihood: Low Note that the submission assumes the feasibility of price manipulation on exchanges. Also swaps are out of scope. Because it seems like slippage control does not exist in the codebase, leaving this for now for sponsor's review.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.