DeFiFoundrySolidity
16,653 OP
View results
Submission Details
Severity: medium
Invalid

Known Swap Path Manipulation in claimAndSwap Function

Summary

The claimAndSwap function in StrategyMainnet.sol uses a predefined swap path that can be manipulated by attackers to either minimize profits or cause swaps to fail by manipulating pool liquidity ratios. Any ability to successfully DoS this function means that core functionality will be unusable since the purpose of this function is to be used during depegs which only have a small window of arbitrage opportunities.

Vulnerability Details

In the claimAndSwap function, the swap path is determined by stored parameters in the contract's state:

function claimAndSwap(
uint256 _amountClaim,
uint256 _minOut,
uint256 _routeNumber
) external onlyKeepers {
// ...
router.exchange(
routes[_routeNumber], // Predefined route
swapParams[_routeNumber],
_amountClaim,
_minOut,
pools[_routeNumber],
address(this)
);
// ...
}

Since the swap path is known and stored on-chain, attackers can:

  1. Monitor for keeper transactions attempting to execute claimAndSwap

  2. Front-run these transactions by manipulating liquidity in the known pools along the swap path

  3. Either:

    • Shift liquidity to minimize the profit from the swap during depegs

    • Move enough liquidity to cause the swap to fail slippage requirements

This is particularly problematic since this functionality is designed to be used during depegs when timely swaps are critical for the strategy's effectiveness. Move the liquidity is relatively simple all it would take would be to swap liquidity out some of just one of the pools that the protocol will be swapping with, and the swap will fail due to minout not being achieved.

Impact

  • Loss of arbitrage opportunities during depegs

  • Reduced profits from swaps

  • Failed swaps due to slippage requirements not being met

  • Potential denial of service for one of the strategy's core profit mechanisms

Tools Used

Manual Review

Recommendations

  1. Implement a backup swap path that can be used if the primary swap fails:

function claimAndSwap(
uint256 _amountClaim,
uint256 _minOut,
uint256 _primaryRouteNumber,
uint256 _backupRouteNumber
) external onlyKeepers {
try router.exchange(
routes[_primaryRouteNumber],
swapParams[_primaryRouteNumber],
_amountClaim,
_minOut,
pools[_primaryRouteNumber],
address(this)
) {
// Primary route succeeded
} catch {
// Try backup route
router.exchange(
routes[_backupRouteNumber],
swapParams[_backupRouteNumber],
_amountClaim,
_minOut,
pools[_backupRouteNumber],
address(this)
);
}
}

These changes force attackers to control more liquidity across multiple paths. This fix can also be done in the form of a loop where you iterate over possible routes and swap params until one succeeds. This will make it even more expensive to manipulate the swap path.

It is also important to note that this is possible in all of the strategy contracts and each will need to implement back out routes/paths to ensure successful swaps.

Updates

Appeal created

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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