SSSwap

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

H1-provide_liquidity does not reload vault value

Root + Impact

Description

  • In normal behavior, a liquidity provider deposits amount_a of token A, and the program computes the corresponding amount_b of token B needed to maintain the pool ratio. Then both amounts are transferred to the pool vaults, and the appropriate number of LP tokens is minted to the user.

  • However, the function calculate_token_b_provision_with_a_given depends on reading accurate vault balances. If the vault accounts are not explicitly reloaded (.reload()), the cached state may not reflect recent external token transfers, causing the amount of token B to be miscalculated.

pub fn provide_liquidity(context: Context<ModifyLiquidity>,
amount_a: u64
) -> Result<()> {
let amount_b = calculate_token_b_provision_with_a_given(
&mut context.accounts.vault_a,
&mut context.accounts.vault_b,
amount_a
)?;
transfer_tokens(
&context.accounts.liquidity_provider_token_a,
&mut context.accounts.vault_a,
&amount_a,
&context.accounts.token_a_mint,
&context.accounts.liquidity_provider,
&context.accounts.token_program
)?;


Risk

Likelihood:

  • This will occur when tokens have been transferred into either vault_a or vault_b before the instruction executes, either as part of a batched transaction or as an external manipulation.

  • Programs using cached account state without a fresh .reload() are susceptible to using outdated balances, particularly in multi-instruction transactions.

Impact:

  • The calculated amount_b could be incorrect, leading to an imbalance in the pool and unfair liquidity provision.

  • LP tokens could be minted at an incorrect ratio, diluting other liquidity providers or benefiting manipulators.

Proof of Concept

External actor or same user pre-loads vault_a with extra tokens
send_tokens_to(vault_a, 10_000);

Then provides liquidity based on stale vault_a reserve
provide_liquidity(amount_a = 100_000);

vault_a balance appears lower than reality during calculation, but includes added tokens during transfer
// This creates misalignment between expected and actual pool state

Recommended Mitigation

Always reload token accounts before using them in reserve-sensitive calculations to prevent stale state from impacting logi

context.accounts.vault_a.reload()?;
context.accounts.vault_b.reload()?;
Updates

Lead Judging Commences

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

lack of account reload causes liquidity calculations to be outdated

Support

FAQs

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