chore(amm): add defensive check for lp token solvency

This check is added to fulfill the program invariant that no more tokens
than owned can be burned. This was not a bug before, because the `token`
program will revert on `Transfer::Burn` when one tries to burn more
tokens than available.

So this change is merely for making the invariant explicit.
This commit is contained in:
r4bbit 2026-05-04 14:47:50 +02:00
parent e69c9107f0
commit 06494e1b14
No known key found for this signature in database
GPG Key ID: E95F1E9447DC91A9
2 changed files with 22 additions and 0 deletions

View File

@ -101,6 +101,10 @@ pub fn remove_liquidity(
pool_def_data.liquidity_pool_supply > MINIMUM_LIQUIDITY,
"Pool only contains locked liquidity"
);
assert!(
remove_liquidity_amount <= user_lp_balance,
"Remove amount exceeds user LP balance"
);
let unlocked_liquidity = pool_def_data.liquidity_pool_supply - MINIMUM_LIQUIDITY;
// The remove instruction never sees the LP lock account directly, so we must still refuse any
// request that would burn through the permanent floor even if ownership is already corrupted.

View File

@ -3411,6 +3411,24 @@ fn test_remove_liquidity_rejects_user_holding_b_wrong_program() {
);
}
#[should_panic(expected = "Remove amount exceeds user LP balance")]
#[test]
fn test_remove_liquidity_rejects_amount_exceeding_user_lp_balance() {
let lp_balance = BalanceForTests::remove_amount_lp() - 1;
let _ = remove_liquidity(
AccountWithMetadataForTests::pool_definition_init(),
AccountWithMetadataForTests::vault_a_init(),
AccountWithMetadataForTests::vault_b_init(),
AccountWithMetadataForTests::pool_lp_init(),
AccountWithMetadataForTests::user_holding_a(),
AccountWithMetadataForTests::user_holding_b(),
AccountWithMetadataForTests::user_holding_lp_with_balance(lp_balance),
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
BalanceForTests::remove_min_amount_a(),
BalanceForTests::remove_min_amount_b_low(),
);
}
#[should_panic(expected = "User Token A holding must be owned by the vault's Token Program")]
#[test]
fn test_swap_exact_input_rejects_user_holding_a_wrong_program() {