Assessment reports>Liquidswap>Low findings>Implicit precision loss in ,stable_curve::lp_value
Category: Business Logic

Implicit precision loss in stable_curve::lp_value

Low Severity
Low Impact
Low Likelihood

Description

In stable_curve::lp_value, coins with more than eight decimals experience implicit precision loss. The current implementation returns the LP value scaled by (10 ^ 8) ^ 4 in order to maintain precision across division:

public fun lp_value(x_coin: u128, x_scale: u64, y_coin: u128, y_scale: u64): U256 {
    let x_u256 = u256::from_u128(x_coin);
    let y_u256 = u256::from_u128(y_coin);
    let u2561e8 = u256::from_u128(ONE_E_8);

    let x_scale_u256 = u256::from_u64(x_scale);
    let y_scale_u256 = u256::from_u64(y_scale);

    let _x = u256::div(
        u256::mul(x_u256, u2561e8),
        x_scale_u256,
    );

    let _y = u256::div(
        u256::mul(y_u256, u2561e8),
        y_scale_u256,
    );

    let _a = u256::mul(_x, _y);

    // ((_x * _x) / 1e18 + (_y * _y) / 1e18)
    let _b = u256::add(
        u256::mul(_x, _x),
        u256::mul(_y, _y),
    );

    u256::mul(_a, _b)
}

However, this means that stable_curve::lp_value will return inaccurate values when coins have more decimals.

Impact

Loss of precision in LP value calculations can cause fees to be unexpectedly high: Situations where a swap would theoretically increase LP value might fail. This precision loss will also affect the accuracy of router functions.

Recommendations

When coins have more than eight decimals, either rounding should be handled explicitly or they should be disallowed from the protocol.

Another option is to use the numerator max(x_scale, y_scale) instead of 10 ^ 8 to mitigate precision loss. Still, coins with unusually high precision would need to be either disallowed or explicitly considered in order to avoid overflow problems.

Remediation

This issue has been acknowledged by Pontem Network.

Zellic © 2023Back to top ↑