Skip to content

Latest commit

 

History

History
89 lines (67 loc) · 3.04 KB

File metadata and controls

89 lines (67 loc) · 3.04 KB

Fast Khaki Raccoon

Medium

_swapForRewards can be MEVed

Summary

Users and MEV bots can extract value from the system as _swapForRewards will sometimes perform a faulty swap.

Root Cause

The bellow try would execute a swap with 0 amountOut when amountIn == REWARDS_SWAP_OVERRIDE_MIN https://github.com/sherlock-audit/2025-01-peapods-finance/blob/main/contracts/contracts/TokenRewards.sol#L300-L313

        try DEX_ADAPTER.swapV3Single(
            PAIRED_LP_TOKEN,
            rewardsToken,
            REWARDS_POOL_FEE,
            _amountIn,
            //@finding M users can MEV this with FR and backrun to manipulate the prices
            _amountIn == REWARDS_SWAP_OVERRIDE_MIN 
                ? 0 
                : (_amountOut * (1000 - REWARDS_SWAP_SLIPPAGE)) / 1000,
            address(this)
        ) {

Internal Pre-conditions

No response

External Pre-conditions

No response

Attack Path

  1. depositFromPairedLpToken is triggered, however due to slippage or any other reason the swap fails
  2. We have entered the catch and the second case in the short if, which have set _rewardsSwapAmountInOverride to REWARDS_SWAP_OVERRIDE_MIN
            _rewardsSwapAmountInOverride = _amountIn / 2 < REWARDS_SWAP_OVERRIDE_MIN 
                ? REWARDS_SWAP_OVERRIDE_MIN 
                : _amountIn / 2;
  1. The next user or MEV bot who calls depositFromPairedLpToken would trigger this if, which would set the new _amountIn to _rewardsSwapAmountInOverride, which is equal to REWARDS_SWAP_OVERRIDE_MIN
        if (_rewardsSwapAmountInOverride > 0) {
            _adminAmt = (_adminAmt * _rewardsSwapAmountInOverride) / _amountIn;
            _amountOut = (_amountOut * _rewardsSwapAmountInOverride) / _amountIn;
            _amountIn = _rewardsSwapAmountInOverride;
        }
  1. We would execute the swap, with 0 out as the bellow if will set it to 0, when _amountIn == REWARDS_SWAP_OVERRIDE_MIN
        try DEX_ADAPTER.swapV3Single(
            PAIRED_LP_TOKEN,
            rewardsToken,
            REWARDS_POOL_FEE,
            _amountIn,
            _amountIn == REWARDS_SWAP_OVERRIDE_MIN 
                ? 0 
                : (_amountOut * (1000 - REWARDS_SWAP_SLIPPAGE)) / 1000,
            address(this)
        ) {

Meaning that a user would just need to:

  1. swap and change the price
  2. call depositFromPairedLpToken
  3. Swap back to the original price

Thus every time we enter the catch and set _rewardsSwapAmountInOverride to REWARDS_SWAP_OVERRIDE_MIN this vulnerability becomes exploitable.

Note that this may be more profitable on expensive chains like ETH, as there the REWARDS_SWAP_OVERRIDE_MIN will be a bigger value, as each swap would cost somewhere between 5 and 20 USD in eth, so REWARDS_SWAP_OVERRIDE_MIN of 100 USD in token value would be reasonable.

Impact

Users can MEV the system. MEV bots can exploit swaps to extract value.

PoC

No response

Mitigation

Don't have 0 as out, consider still applying some percentage of in as out