57898 sc high unprotected swap function allows sandwich attacks

Submitted on Oct 29th 2025 at 12:02:14 UTC by @count_sum for Audit Comp | Belongarrow-up-right

  • Report ID: #57898

  • Report Type: Smart Contract

  • Report severity: High

  • Target: https://github.com/immunefi-team/audit-comp-belong/blob/main/contracts/v2/platform/BelongCheckIn.sol

  • Impacts:

    • Theft of unclaimed yield

Description

Summary

The _swapExact function in BelongCheckIn.sol calculates the minimum output amount (amountOutMinimum) on-chain during the same transaction, making it vulnerable to sandwich attacks via MEV bots. Attackers can manipulate the pool price before the victim's transaction, causing the victim to receive unfavorable swap rates while the slippage protection becomes ineffective.

Vulnerability Details

Root Cause

The vulnerability exists in the _swapExact function at BelongCheckIn.sol:652-694:

function _swapExact(address tokenIn, address tokenOut, address recipient, uint256 amount)
    internal
    returns (uint256 swapped)
{
    // ...

    // VULNERABLE: amountOutMinimum calculated on-chain in same transaction
    uint256 amountOutMinimum =
        IV3Quoter(_paymentsInfo.swapV3Quoter).quoteExactInput(path, amount)
            .amountOutMin(_paymentsInfo.slippageBps);

    IV3Router.ExactInputParamsV1 memory swapParamsV1 = IV3Router.ExactInputParamsV1({
        path: path,
        recipient: recipient,
        deadline: block.timestamp,  // Also vulnerable: no real deadline protection
        amountIn: amount,
        amountOutMinimum: amountOutMinimum
    });

    // ...
}
1

Attack Flow — Step 1: Detection

MEV bot detects a pending venueDeposit transaction in the mempool.

2

Attack Flow — Step 2: Front-run

Bot submits a transaction with higher gas to:

  • Buy LONG tokens, increasing the price

  • This manipulates the pool reserves before the victim's transaction

3

Attack Flow — Step 3: Victim Transaction Executes

  • quoteExactInput() returns the manipulated (inflated) price

  • amountOutMin() calculates slippage from this already-manipulated price

  • Swap executes at the bad rate (but within the newly calculated slippage)

4

Attack Flow — Step 4: Back-run

Bot sells LONG tokens back, capturing the price difference as profit.

Why Slippage Protection Fails

The slippage protection is calculated AFTER the price manipulation:

Normal scenario (no attack):

  • Pool price: 1 USDC = 1 LONG

  • Quote: 1000 USDC -> 1000 LONG

  • With 5% slippage: minOut = 950 LONG

Under sandwich attack:

  • Bot manipulates price: 1 USDC = 0.95 LONG

  • Quote NOW: 1000 USDC -> 950 LONG (using manipulated price)

  • With 5% slippage: minOut = 902.5 LONG

  • Victim gets 950 LONG (seems "protected" but actually lost 5%)

Impact Details

Financial Loss

  • Users lose 5-20% of their deposit value to MEV bots

  • Affects all venueDeposit transactions involving swaps

  • Higher deposits face proportionally larger absolute losses

Affected Functions

  • venueDeposit() - when convenience fees are swapped to LONG

  • _handleRevenue() - when platform revenue is swapped

  • Any future functions using _swapExact()

triangle-exclamation

Recommendations

Primary Fix: Off-chain Slippage Calculation

Calculate amountOutMinimum off-chain and pass it as a parameter:

Secondary Fix: Add Meaningful Deadline

Replace block.timestamp with a user-provided deadline:

Additional Mitigations

  1. TWAP Oracle: Use time-weighted average price for reference

  2. Private Mempool: Submit transactions through private pools (e.g., Flashbots)

  3. Commit-Reveal: Two-phase deposits to hide transaction details

  4. Maximum Slippage Check: Revert if price deviates too much from oracle

Proof of Concept

Running the POC

1

Save the test file to test/foundry/H2_SandwichAttack_POC.t.sol

2

Run the tests:

POC CODE

Was this helpful?