fix(token-swap): compute amm math in u128 to avoid I64F64 overflow#609
Conversation
deposit_liquidity, swap_exact_tokens_for_tokens and withdraw_liquidity multiplied two u64 token amounts as I64F64, whose integer part maxes at 2^63-1. checked_mul().unwrap() therefore panics once the product reaches 2^63 (~3 tokens per side at 9 decimals), so larger deposits, swaps and withdrawals fail. Do the multiply/divide/sqrt in u128 instead (two u64s multiply to < 2^128), using u128::isqrt for the liquidity sqrt. Same floor results for valid inputs, overflow-free across the full u64 range. Drops the now-unused fixed dependency.
Greptile SummaryThis PR replaces
Confidence Score: 3/5The overflow fix in the deposit and withdraw paths is correct, but the swap invariant check remains broken in two ways — overflow-prone u64 multiplication and a typo that compares against pool_a² instead of the true post-trade product — leaving the primary safety mechanism for swaps unreliable. The deposit and withdraw changes are solid and solve the stated problem. However, swap_exact_tokens_for_tokens still has two defects in the invariant check: the plain u64 multiply on line 55 can overflow silently in release mode, and line 129 reads pool_account_a.amount * pool_account_a.amount when it should read pool_account_a.amount * pool_account_b.amount. Together these mean the constant-product safety guard can silently pass even when k decreases. tokens/token-swap/anchor/programs/token-swap/src/instructions/swap_exact_tokens_for_tokens.rs — the invariant lines (55 and 129) need to be migrated to u128 and the pool_account_a typo on line 129 must be corrected. Important Files Changed
|
Summary
deposit_liquidity,swap_exact_tokens_for_tokens, andwithdraw_liquiditymultiplied twou64token amounts asI64F64, whose integer part maxes at2^63-1.checked_mul().unwrap()therefore panics once the product reaches2^63— roughly 3 tokens per side at 9 decimals — so larger deposits, swaps and withdrawals fail.u128instead (twou64s multiply to< 2^128), usingu128::isqrtfor the liquidity sqrt. Same floor results for valid inputs, overflow-free across the fullu64range.fixeddependency.Test Plan
anchor buildsucceeds locally (anchor-cli 1.0.2; exit 0, no errors/unused warnings; program + IDL built).I64F64::from_num(a*b).sqrt().to_num::<u64>()==(a*b).isqrt(); theI64F64mul/div(+floor) paths ==u128integer mul/div for non-negative token amounts.token-swap/anchoris listed in.github/.ghaignore("can't test on localnet"), so CI won't exercise it — verified via local build + reasoning.Closes #73