Normal behavior: The owner calls unwindPosition to close or reduce a leveraged position. The contract takes a flash loan of the debt token, repays Aave debt, withdraws proportional collateral, swaps collateral to debt token via 1inch, and repays the flash loan. The swap is expected to return at least totalDebt (principal + premium); any surplus is supplied back to Aave.
Specific issue: The collateral→debt swap executes at current DEX/liquidity prices. An attacker watching the mempool can front-run the victim’s unwind by trading in the same pools 1inch uses (e.g. buy collateral, sell debt token), worsening the victim’s swap execution. The victim’s swap then returns less debt token. When returnAmount < totalDebt, the callback reverts at require(returnAmount >= totalDebt, "Insufficient funds to repay flash loan"). The unwind fails and the position stays open. By repeating the front-run, the attacker can effectively trap the position until the victim retries with lower minReturnAmount (worse slippage) or conditions improve.
Likelihood:
Unwind transactions are visible in the public mempool. Any actor with front-running capability can submit a trade before the victim’s unwind so that the victim’s swap receives worse execution.
1inch routes through on-chain DEX pools; pool prices are sensitive to the order of trades in the same block. The attacker’s trade and the victim’s swap are in the same block, so the attack is feasible whenever the victim uses a non-private submission path.
Impact:
The victim’s unwind reverts; the position stays open and remains exposed to market and liquidation risk.
A motivated attacker can repeatedly front-run unwind attempts, effectively trapping the victim until they accept worse slippage (lower minReturnAmount) or wait for better conditions, causing economic harm and potential liquidation.
The PoC replicates the unwind repayment check from Stratax. When the swap returns less than totalDebt (e.g. because an attacker front-ran and moved DEX price), the require(returnAmount >= totalDebt, "Insufficient funds to repay flash loan") reverts. The tests demonstrate: (1) passing returnAmount = totalDebt - 1 causes the exact revert used in production; (2) the front-run scenario (swap returns 1002, totalDebt 1005) satisfies the revert condition. So the position cannot close until the victim retries with lower minReturnAmount or better market.
In unwindPosition and/or UnwindParams NatSpec, document that _minReturnAmount must be chosen so that the swap is expected to return at least _debtAmount + flashLoanPremium under adverse execution (e.g. front-run), and that unwinds are sensitive to DEX price movement.
Optional: at the start of _executeUnwindOperation, require that the owner’s minimum return is at least the amount needed to repay the flash loan, so that the user cannot accidentally set a lower bound below the debt (does not stop front-running but aligns parameter with intent):
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.
The contest is complete and the rewards are being distributed.