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

Lack of Handling for Partial Fills or Errors in Swaps

Description

In the function _swapUnderlyingToAsset, the contract calls swapExactTokensForTokens, assuming the swap will fully fill at or above _minOut. Many decentralized exchanges (or future upgrades to them) can implement partial fills if liquidity is insufficient. If the swap only partially fills—or fails due to unexpected router behavior—the contract does not retry or offer alternative routes. It also does not handle the scenario where only a portion of _amount gets swapped.

Impact: Medium

  1. Missed Trade Opportunities

    • Under low-liquidity conditions, an “all-or-nothing” swap may revert instead of performing a partial fill that could at least secure part of the desired trade.

  2. Protocol Downtime or Reverts

    • If slippage or partial fill triggers a revert, the strategy’s swapping logic is effectively blocked, requiring manual intervention.

  3. Rigid User Experience

    • Users might experience failed or delayed withdrawals, harvests, or swaps without an automatic fallback method.


Evidence from Code

A snippet from _swapUnderlyingToAsset (simplified):

function _swapUnderlyingToAsset(
uint256 _amount,
uint256 minOut,
IVeloRouter.route[] calldata _path
) internal {
// Attempt exact swap
IVeloRouter(router).swapExactTokensForTokens(
_amount,
minOut,
_path,
address(this),
block.timestamp
);
// The code assumes a full swap or reverts on slippage beyond minOut.
}

The function reverts if the swap cannot deliver at least minOut. There is no logic to handle partial fills or route changes in real time.


Potential Attack or Failure Scenario

  1. Low Liquidity Environment

    • Liquidity might drop in the designated pool, making it impossible to swap the entire _amount at the requested minOut.

  2. Partial Fill or Failure

    • The router tries to fill as much as possible. If partial fills are allowed by the DEX, it could fill only a portion. If the contract’s code or DEX strictly enforces “exact” swaps, it reverts entirely.

  3. Swap Fails or Reverts

    • The entire transaction is undone. The strategy remains stuck with unconverted tokens, potentially missing profitable opportunities or preventing successful user withdrawals.


Recommended Mitigations

  1. Support Partial Fills

    • Use a function or approach that allows partial fills, then handle the leftover tokens as needed.

    • Example: an internal loop or logic that swaps in increments until liquidity is exhausted or a minimum threshold is reached.

  2. Alternative Routing / Retry Mechanism

    • If a swap fails due to insufficient liquidity, attempt another path or break the transaction into smaller chunks.

    • Integrate with a DEX aggregator that can automatically route among multiple pools.

  3. Dynamic Slippage Mechanism

    • Instead of a fixed _minOut, use a range or formula based on real-time liquidity checks or oracles.

    • If the slippage is too high, revert early or try a smaller partial swap.

  4. Graceful Error Handling / Event Emission

    • If a swap cannot fill fully, emit an event indicating partial fill or insufficient liquidity.

    • This can trigger off-chain keepers or watchers to attempt alternative measures.


Conclusion

Relying on “all-or-nothing” exact swaps can hamper the protocol under low-liquidity or high-slippage conditions, resulting in reverts instead of partial executions. By introducing partial fills, alternative routing, or dynamic slippage tolerances, the strategy can adapt to varying liquidity conditions and reduce the risk of lost opportunities or blocking user operations.

Updates

Appeal created

inallhonesty Lead Judge 5 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.