mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-03-02 18:23:08 +00:00
chore(programs/amm): fix initial LP supply calculations
ift-ts:sc:logos:2026q1-amm-core-improvements:fix-initial-lp-calc
This commit is contained in:
parent
67f49697f7
commit
fee1ab30e9
Binary file not shown.
@ -2504,6 +2504,12 @@ pub mod tests {
|
||||
fn user_token_b_holding_new_definition() -> u128 {
|
||||
7_500
|
||||
}
|
||||
|
||||
fn lp_supply_init() -> u128 {
|
||||
// isqrt(vault_a_balance_init * vault_b_balance_init) = isqrt(5_000 * 2_500) = 3535
|
||||
(BalanceForTests::vault_a_balance_init() * BalanceForTests::vault_b_balance_init())
|
||||
.isqrt()
|
||||
}
|
||||
}
|
||||
|
||||
struct IdForTests;
|
||||
@ -3098,7 +3104,7 @@ pub mod tests {
|
||||
balance: 0u128,
|
||||
data: Data::from(&TokenHolding::Fungible {
|
||||
definition_id: IdForTests::token_lp_definition_id(),
|
||||
balance: BalanceForTests::user_token_a_holding_new_definition(),
|
||||
balance: BalanceForTests::lp_supply_init(),
|
||||
}),
|
||||
nonce: 0,
|
||||
}
|
||||
@ -3110,7 +3116,7 @@ pub mod tests {
|
||||
balance: 0u128,
|
||||
data: Data::from(&TokenDefinition::Fungible {
|
||||
name: String::from("LP Token"),
|
||||
total_supply: BalanceForTests::vault_a_balance_init(),
|
||||
total_supply: BalanceForTests::lp_supply_init(),
|
||||
metadata_id: None,
|
||||
}),
|
||||
nonce: 0,
|
||||
@ -3127,7 +3133,7 @@ pub mod tests {
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
vault_b_id: IdForTests::vault_b_id(),
|
||||
liquidity_pool_id: IdForTests::token_lp_definition_id(),
|
||||
liquidity_pool_supply: BalanceForTests::user_token_a_holding_new_definition(),
|
||||
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
|
||||
reserve_a: BalanceForTests::vault_a_balance_init(),
|
||||
reserve_b: BalanceForTests::vault_b_balance_init(),
|
||||
fees: 0u128,
|
||||
@ -3417,7 +3423,7 @@ pub mod tests {
|
||||
let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id());
|
||||
let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id());
|
||||
|
||||
let expected_pool = AccountForTests::pool_definition_init();
|
||||
let expected_pool = AccountForTests::pool_definition_new_init();
|
||||
let expected_vault_a = AccountForTests::vault_a_init();
|
||||
let expected_vault_b = AccountForTests::vault_b_init();
|
||||
let expected_token_lp = AccountForTests::token_lp_definition_new_init();
|
||||
|
||||
@ -77,7 +77,7 @@ pub fn new_definition(
|
||||
);
|
||||
|
||||
// LP Token minting calculation
|
||||
// We assume LP is based on the initial deposit amount for Token_A.
|
||||
let initial_lp = (token_a_amount.get() * token_b_amount.get()).isqrt();
|
||||
|
||||
// Update pool account
|
||||
let mut pool_post = pool.account.clone();
|
||||
@ -87,7 +87,7 @@ pub fn new_definition(
|
||||
vault_a_id: vault_a.account_id,
|
||||
vault_b_id: vault_b.account_id,
|
||||
liquidity_pool_id: pool_definition_lp.account_id,
|
||||
liquidity_pool_supply: token_a_amount.into(),
|
||||
liquidity_pool_supply: initial_lp,
|
||||
reserve_a: token_a_amount.into(),
|
||||
reserve_b: token_b_amount.into(),
|
||||
fees: 0u128, // TODO: we assume all fees are 0 for now.
|
||||
@ -124,11 +124,11 @@ pub fn new_definition(
|
||||
let instruction = if pool.account == Account::default() {
|
||||
token_core::Instruction::NewFungibleDefinition {
|
||||
name: String::from("LP Token"),
|
||||
total_supply: token_a_amount.into(),
|
||||
total_supply: initial_lp,
|
||||
}
|
||||
} else {
|
||||
token_core::Instruction::Mint {
|
||||
amount_to_mint: token_a_amount.into(),
|
||||
amount_to_mint: initial_lp,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -70,7 +70,7 @@ impl BalanceForTests {
|
||||
}
|
||||
|
||||
fn remove_actual_a_successful() -> u128 {
|
||||
100
|
||||
141
|
||||
}
|
||||
|
||||
fn remove_min_amount_b_low() -> u128 {
|
||||
@ -105,6 +105,11 @@ impl BalanceForTests {
|
||||
20
|
||||
}
|
||||
|
||||
fn lp_supply_init() -> u128 {
|
||||
// sqrt(vault_a_reserve_init * vault_b_reserve_init) = sqrt(1000 * 500) = 707
|
||||
(BalanceForTests::vault_a_reserve_init() * BalanceForTests::vault_b_reserve_init()).isqrt()
|
||||
}
|
||||
|
||||
fn vault_a_swap_test_1() -> u128 {
|
||||
1_500
|
||||
}
|
||||
@ -142,11 +147,11 @@ impl BalanceForTests {
|
||||
}
|
||||
|
||||
fn vault_a_remove_successful() -> u128 {
|
||||
900
|
||||
859
|
||||
}
|
||||
|
||||
fn vault_b_remove_successful() -> u128 {
|
||||
450
|
||||
430
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,7 +254,7 @@ impl ChainedCallForTests {
|
||||
TOKEN_PROGRAM_ID,
|
||||
vec![pool_lp_auth, AccountForTests::user_holding_lp_init()],
|
||||
&token_core::Instruction::Mint {
|
||||
amount_to_mint: BalanceForTests::add_successful_amount_a(),
|
||||
amount_to_mint: 282,
|
||||
},
|
||||
)
|
||||
.with_pda_seeds(vec![compute_liquidity_token_pda_seed(
|
||||
@ -282,7 +287,7 @@ impl ChainedCallForTests {
|
||||
TOKEN_PROGRAM_ID,
|
||||
vec![vault_b_auth, AccountForTests::user_holding_b()],
|
||||
&token_core::Instruction::Transfer {
|
||||
amount_to_transfer: BalanceForTests::remove_min_amount_b_low(),
|
||||
amount_to_transfer: 70,
|
||||
},
|
||||
)
|
||||
.with_pda_seeds(vec![compute_vault_pda_seed(
|
||||
@ -341,7 +346,7 @@ impl ChainedCallForTests {
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
],
|
||||
&token_core::Instruction::Mint {
|
||||
amount_to_mint: BalanceForTests::add_successful_amount_a(),
|
||||
amount_to_mint: BalanceForTests::lp_supply_init(),
|
||||
},
|
||||
)
|
||||
.with_pda_seeds(vec![compute_liquidity_token_pda_seed(
|
||||
@ -568,7 +573,7 @@ impl AccountForTests {
|
||||
balance: 0u128,
|
||||
data: Data::from(&TokenDefinition::Fungible {
|
||||
name: String::from("test"),
|
||||
total_supply: BalanceForTests::vault_a_reserve_init(),
|
||||
total_supply: BalanceForTests::lp_supply_init(),
|
||||
metadata_id: None,
|
||||
}),
|
||||
nonce: 0,
|
||||
@ -585,7 +590,7 @@ impl AccountForTests {
|
||||
balance: 0u128,
|
||||
data: Data::from(&TokenDefinition::Fungible {
|
||||
name: String::from("test"),
|
||||
total_supply: BalanceForTests::vault_a_reserve_init(),
|
||||
total_supply: BalanceForTests::lp_supply_init(),
|
||||
metadata_id: None,
|
||||
}),
|
||||
nonce: 0,
|
||||
@ -638,7 +643,7 @@ impl AccountForTests {
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
vault_b_id: IdForTests::vault_b_id(),
|
||||
liquidity_pool_id: IdForTests::token_lp_definition_id(),
|
||||
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
|
||||
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
|
||||
reserve_a: BalanceForTests::vault_a_reserve_init(),
|
||||
reserve_b: BalanceForTests::vault_b_reserve_init(),
|
||||
fees: 0u128,
|
||||
@ -662,7 +667,7 @@ impl AccountForTests {
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
vault_b_id: IdForTests::vault_b_id(),
|
||||
liquidity_pool_id: IdForTests::token_lp_definition_id(),
|
||||
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
|
||||
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
|
||||
reserve_a: 0,
|
||||
reserve_b: BalanceForTests::vault_b_reserve_init(),
|
||||
fees: 0u128,
|
||||
@ -686,7 +691,7 @@ impl AccountForTests {
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
vault_b_id: IdForTests::vault_b_id(),
|
||||
liquidity_pool_id: IdForTests::token_lp_definition_id(),
|
||||
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
|
||||
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
|
||||
reserve_a: BalanceForTests::vault_a_reserve_init(),
|
||||
reserve_b: 0,
|
||||
fees: 0u128,
|
||||
@ -758,7 +763,7 @@ impl AccountForTests {
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
vault_b_id: IdForTests::vault_b_id(),
|
||||
liquidity_pool_id: IdForTests::token_lp_definition_id(),
|
||||
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
|
||||
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
|
||||
reserve_a: BalanceForTests::vault_a_swap_test_1(),
|
||||
reserve_b: BalanceForTests::vault_b_swap_test_1(),
|
||||
fees: 0u128,
|
||||
@ -782,7 +787,7 @@ impl AccountForTests {
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
vault_b_id: IdForTests::vault_b_id(),
|
||||
liquidity_pool_id: IdForTests::token_lp_definition_id(),
|
||||
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
|
||||
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
|
||||
reserve_a: BalanceForTests::vault_a_swap_test_2(),
|
||||
reserve_b: BalanceForTests::vault_b_swap_test_2(),
|
||||
fees: 0u128,
|
||||
@ -830,7 +835,7 @@ impl AccountForTests {
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
vault_b_id: IdForTests::vault_b_id(),
|
||||
liquidity_pool_id: IdForTests::token_lp_definition_id(),
|
||||
liquidity_pool_supply: BalanceForTests::vault_a_add_successful(),
|
||||
liquidity_pool_supply: 989,
|
||||
reserve_a: BalanceForTests::vault_a_add_successful(),
|
||||
reserve_b: BalanceForTests::vault_b_add_successful(),
|
||||
fees: 0u128,
|
||||
@ -854,7 +859,7 @@ impl AccountForTests {
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
vault_b_id: IdForTests::vault_b_id(),
|
||||
liquidity_pool_id: IdForTests::token_lp_definition_id(),
|
||||
liquidity_pool_supply: BalanceForTests::vault_a_remove_successful(),
|
||||
liquidity_pool_supply: 607,
|
||||
reserve_a: BalanceForTests::vault_a_remove_successful(),
|
||||
reserve_b: BalanceForTests::vault_b_remove_successful(),
|
||||
fees: 0u128,
|
||||
@ -878,7 +883,7 @@ impl AccountForTests {
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
vault_b_id: IdForTests::vault_b_id(),
|
||||
liquidity_pool_id: IdForTests::token_lp_definition_id(),
|
||||
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
|
||||
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
|
||||
reserve_a: BalanceForTests::vault_a_reserve_init(),
|
||||
reserve_b: BalanceForTests::vault_b_reserve_init(),
|
||||
fees: 0u128,
|
||||
@ -902,7 +907,7 @@ impl AccountForTests {
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
vault_b_id: IdForTests::vault_b_id(),
|
||||
liquidity_pool_id: IdForTests::token_lp_definition_id(),
|
||||
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
|
||||
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
|
||||
reserve_a: BalanceForTests::vault_a_reserve_init(),
|
||||
reserve_b: BalanceForTests::vault_b_reserve_init(),
|
||||
fees: 0u128,
|
||||
@ -958,7 +963,7 @@ impl AccountForTests {
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
vault_b_id: IdForTests::vault_b_id(),
|
||||
liquidity_pool_id: IdForTests::token_lp_definition_id(),
|
||||
liquidity_pool_supply: BalanceForTests::vault_a_reserve_init(),
|
||||
liquidity_pool_supply: BalanceForTests::lp_supply_init(),
|
||||
reserve_a: BalanceForTests::vault_a_reserve_init(),
|
||||
reserve_b: BalanceForTests::vault_b_reserve_init(),
|
||||
fees: 0u128,
|
||||
@ -1717,3 +1722,73 @@ fn test_call_swap_chained_call_successful_2() {
|
||||
ChainedCallForTests::cc_swap_token_b_test_2()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_definition_lp_asymmetric_amounts() {
|
||||
let (post_states, chained_calls) = new_definition(
|
||||
AccountForTests::pool_definition_inactive(),
|
||||
AccountForTests::vault_a_init(),
|
||||
AccountForTests::vault_b_init(),
|
||||
AccountForTests::pool_lp_init(),
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
|
||||
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
|
||||
AMM_PROGRAM_ID,
|
||||
);
|
||||
|
||||
// check the minted LP amount
|
||||
let pool_post = post_states[0].clone();
|
||||
let pool_def = PoolDefinition::try_from(&pool_post.account().data).unwrap();
|
||||
assert_eq!(
|
||||
pool_def.liquidity_pool_supply,
|
||||
BalanceForTests::lp_supply_init()
|
||||
);
|
||||
|
||||
let chained_call_lp = chained_calls[0].clone();
|
||||
assert!(chained_call_lp == ChainedCallForTests::cc_new_definition_token_lp());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_definition_lp_symmetric_amounts() {
|
||||
// token_a=100, token_b=100 → LP=sqrt(10_000)=100
|
||||
let token_a_amount = 100u128;
|
||||
let token_b_amount = 100u128;
|
||||
let expected_lp = (token_a_amount * token_b_amount).isqrt();
|
||||
assert_eq!(expected_lp, 100);
|
||||
|
||||
let (post_states, chained_calls) = new_definition(
|
||||
AccountForTests::pool_definition_inactive(),
|
||||
AccountForTests::vault_a_init(),
|
||||
AccountForTests::vault_b_init(),
|
||||
AccountForTests::pool_lp_init(),
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
NonZero::new(token_a_amount).unwrap(),
|
||||
NonZero::new(token_b_amount).unwrap(),
|
||||
AMM_PROGRAM_ID,
|
||||
);
|
||||
|
||||
let pool_post = post_states[0].clone();
|
||||
let pool_def = PoolDefinition::try_from(&pool_post.account().data).unwrap();
|
||||
assert_eq!(pool_def.liquidity_pool_supply, expected_lp);
|
||||
|
||||
let chained_call_lp = chained_calls[0].clone();
|
||||
let expected_lp_call = ChainedCall::new(
|
||||
TOKEN_PROGRAM_ID,
|
||||
vec![
|
||||
AccountForTests::pool_lp_init(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
],
|
||||
&token_core::Instruction::Mint {
|
||||
amount_to_mint: expected_lp,
|
||||
},
|
||||
)
|
||||
.with_pda_seeds(vec![compute_liquidity_token_pda_seed(
|
||||
IdForTests::pool_definition_id(),
|
||||
)]);
|
||||
|
||||
assert_eq!(chained_call_lp, expected_lp_call);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user