Stratax Contracts

First Flight #57
Beginner FriendlyDeFi
100 EXP
Submission Details
Impact: low
Likelihood: high

Leftover Swap Tokens Auto-Deposited Without Owner Consent

Author Revealed upon completion

Root + Impact

Description

  • After both the open and unwind operations, the contract checks whether the 1inch swap returned more tokens than needed to repay the flash loan. The normal behavior would be to return any excess to the owner or hold it for explicit withdrawal.

  • Instead, the excess tokens are automatically supplied back to Aave as additional collateral without the owner's knowledge or consent. This silently increases the position size and locks the excess funds in Aave, requiring a separate unwindPosition call to retrieve them.

// In _executeOpenOperation:
uint256 totalDebt = _amount + _premium;
require(returnAmount >= totalDebt, "Insufficient funds to repay flash loan");
// Supply any leftover tokens back to Aave to improve position health
@> if (returnAmount - totalDebt > 0) {
@> IERC20(_asset).approve(address(aavePool), returnAmount - totalDebt);
@> aavePool.supply(_asset, returnAmount - totalDebt, address(this), 0);
@> }
// Same pattern in _executeUnwindOperation:
@> if (returnAmount - totalDebt > 0) {
@> IERC20(_asset).approve(address(aavePool), returnAmount - totalDebt);
@> aavePool.supply(_asset, returnAmount - totalDebt, address(this), 0);
@> }

Risk

Likelihood:

  • 1inch swaps frequently return slightly more tokens than the quoted minimum due to favorable market movement between quote time and execution time. The excess is typically small but nonzero.

  • Every position open and unwind operation routes through this code path, making it a per-transaction occurrence.

Impact:

  • The owner's position size increases unpredictably, changing the effective leverage ratio and health factor without their input.

  • Excess tokens become locked in Aave and require a full unwind cycle to extract, incurring additional gas costs and potential slippage.

Proof of Concept

The code review below traces the leftover handling in both _executeOpenOperation (line 528-532) and _executeUnwindOperation (line 590-595). When the 1inch swap returns more tokens than the flash loan debt, the excess is unconditionally supplied back to Aave as extra collateral. The owner has no way to prevent this or claim the surplus directly.

// Code review finding - the pattern is visible in both internal functions:
//
// _executeOpenOperation (line 528-532):
// returnAmount from 1inch swap = 1.05 ETH
// totalDebt (flash loan + premium) = 1.00 ETH
// leftover = 0.05 ETH -> auto-supplied to Aave as extra collateral
//
// _executeUnwindOperation (line 590-595):
// Same pattern: any leftover after flash loan repayment is auto-supplied
//
// Owner expected 3x leverage but now has 3.05x due to auto-deposited leftover
// They must call unwindPosition again to extract the 0.05 ETH

Recommended Mitigation

Instead of auto-depositing leftover tokens into Aave, transfer them directly back to the user. This preserves the intended position size and leverage ratio, and lets the owner decide how to deploy the surplus. Apply the same change to _executeUnwindOperation.

// In _executeOpenOperation:
if (returnAmount - totalDebt > 0) {
- IERC20(_asset).approve(address(aavePool), returnAmount - totalDebt);
- aavePool.supply(_asset, returnAmount - totalDebt, address(this), 0);
+ // Return leftover to the user instead of auto-depositing
+ IERC20(_asset).transfer(user, returnAmount - totalDebt);
}

Support

FAQs

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

Give us feedback!