sherlock-audit / 2024-08-woofi-solana-deployment-judging

0 stars 0 forks source link

Glamorous Violet Chameleon - When withdrawing, the check that balance is enough for unclaimed fees is wrong #65

Open sherlock-admin4 opened 13 hours ago

sherlock-admin4 commented 13 hours ago

Glamorous Violet Chameleon

Medium

When withdrawing, the check that balance is enough for unclaimed fees is wrong

Summary

When withdrawing, the check that there is enough balance for unclaimed fees is wrong. It does not prevent withdrawing funds from the token vault so there is enough balance for unclaimed fees.

Since the check is done before the withdrawal and not after, funds can be withdrawn so that there will not be enough for unclaimed fees.

A pool can have a token vault balance that is lower than the sum of the pool reserve and unclaimed fees due to the incase_token_got_stuck instruction.

Root Cause

In token.rs:12-14, the quote pool's vault is checked that it has enough balance for unclaimed fees.

  (token_vault.amount as u128)
      .checked_sub(woopool.unclaimed_fee)
      .ok_or(ErrorCode::ReserveLessThanFee)?

However, the check is done before withdrawal and it does not account for the withdrawal amount.

  let _balance_before = balance(woopool, token_vault)?;

Internal pre-conditions

  1. Pool owner has deducted funds using incase_token_got_stuck.

External pre-conditions

None

Attack Path

  1. Since the Pool owner has deducted funds with incase_token_got_stuck, the Pool now has a token vault balance of 100, 100 pool reserves, and 20 unclaimed fees.
  2. The Pool owner withdraws 100 tokens and this is not prevented since the check that balance is enough for unclaimed funds is insufficient.

Impact

If the Pool owner wants to withdraw without regard for unclaimed fees and reserves, they can always use incase_token_got_stuck. All withdrawals via withdraw should ensure enough vault funds for at least the unclaimed fees.

PoC

No response

Mitigation

Consider using the _balance_before in the check for enough balance when withdrawing.

  require!(
-      woopool.reserve >= amount && token_vault.amount as u128 >= amount,
+     woopool.reserve >= amount && _balance_before as u128 >= amount,
      ErrorCode::NotEnoughBalance
  );