SSSwap

First Flight #41
Beginner FriendlyRust
100 EXP
View results
Submission Details
Severity: high
Valid

Incorrect LP Token Calculation in `provide_liquidity` Instruction

Description

The provide_liquidity instruction uses the same liquidity_calculation function as the initialize_pool instruction to calculate the amount of LP tokens to mint based on the amounts of tokens A and B provided:

let lp_to_mint: u64 = liquidity_calculation(amount_a, amount_b)?;

This calculation is only correct during the initial pool creation (when no LP tokens exist yet). For subsequent liquidity additions, the LP token amount must be proportional to the existing LP supply and reserves.

Impact

Using the initial pool creation formula to mint LP tokens on additional liquidity deposits will cause:

  • Incorrect LP token minting: The amount of LP tokens minted will not reflect the depositor’s true share of the pool.

  • Imbalanced LP token distribution: Liquidity providers may receive too many or too few LP tokens, resulting in unfair shares.

  • Economic exploits: Malicious actors could exploit this miscalculation to mint more LP tokens than deserved, diluting other liquidity providers’ holdings.

  • Pool state inconsistency: Pool accounting and invariant assumptions may break, causing downstream issues in swaps or removals.

Correct LP Token Calculation for Adding Liquidity

When liquidity already exists, LP tokens to mint must be proportional to the existing LP supply and token reserves. The correct formula is:

lpA = (amountA * totalSupply) / reserveA;
lpB = (amountB * totalSupply) / reserveB;
lpTokensToMint = min(lpA, lpB);

Where:

  • totalSupply is the current total supply of LP tokens.

  • reserveA and reserveB are the current token balances in the pool vaults.

Recommended Fix

Replace the incorrect call to liquidity_calculation with a function that:

  1. Fetches the current total LP token supply.

  2. Fetches the current vault balances (reserves) of tokens A and B.

  3. Calculates lp_to_mint as the minimum of the proportional LP tokens derived from each token amount relative to reserves and total LP supply.

Fix code:

fn calculate_lp_tokens_to_mint(
amount_a: u64,
amount_b: u64,
reserve_a: u64,
reserve_b: u64,
total_lp_supply: u64,
) -> Result<u64> {
let lp_a = (amount_a as u128)
.checked_mul(total_lp_supply as u128)
.ok_or(AmmError::Overflow)?
.checked_div(reserve_a as u128)
.ok_or(AmmError::DivideByZero)?;
let lp_b = (amount_b as u128)
.checked_mul(total_lp_supply as u128)
.ok_or(AmmError::Overflow)?
.checked_div(reserve_b as u128)
.ok_or(AmmError::DivideByZero)?;
let lp_to_mint = lp_a.min(lp_b);
if lp_to_mint == 0 {
return err!(AmmError::LpAmountCalculation);
}
Ok(lp_to_mint as u64)
}
Updates

Lead Judging Commences

0xtimefliez Lead Judge 3 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Liquidity Provision is prone to JIT

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.