Creamy Carrot Yeti
Medium
swap_fee
parameter is calculated using quote_amount
, fee_rate
. However, due to incorrect divisor, incorrect amount of fees would be calculated.
In the current implementation of the handler()
function in the swap.rs
, the swap_fee
parameter is calculated the following way:
let swap_fee = checked_mul_div_round_up(quote_amount, fee_rate as u128, ONE_E5_U128)?;
As you can see here, divisor is set to ONE_E5_U128
from the constants
:
pub const ONE_E5_U128: u128 = 100_000;
Now imagine the following scenario:
- We have the pool SOL / USDT where USDT is the quote token (6 decimal places)
- After swapping SOL to the quote token, we got 200 USDT (200e6).
- Fee is set to 2.5% - 25e3 in the current implementation:
// unit: 0.1 bps (1e6 = 100%, 25 = 2.5 bps)
// Fee amount = total_amount * fee_rate / 100_000.
// Max fee rate supported is u16::MAX around 65.5%.
The issue is that the protocol assumes that 100_000
is 1e6 when in fact it's 1e5. So, when we multiply our 200 USDT amount by 25e3 and then divide by 100_000
, we get the following amount:
200e6 * 25e3 / 100_000 = 50
So the fee is taken as 25% instead of set 2.5%.
The users will pay more fees than expected due to incorrect assumption about decimal places of 100%.
Manual review.
Manual Review
Change 100% value on 1_000_000 instead of 100_000.