mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-03-25 03:33:06 +00:00
various fixes
This commit is contained in:
parent
3205e69e11
commit
8d5e6a37e6
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -6,11 +6,10 @@
|
||||
//! AMM program accepts [`Instruction`] as input, refer to the corresponding documentation
|
||||
//! for more details.
|
||||
|
||||
use std::num::NonZero;
|
||||
|
||||
use amm_core::Instruction;
|
||||
use nssa_core::program::{
|
||||
AccountPostState, ChainedCall, ProgramInput, read_nssa_inputs,
|
||||
write_nssa_outputs_with_chained_call,
|
||||
};
|
||||
use nssa_core::program::{ProgramInput, read_nssa_inputs, write_nssa_outputs_with_chained_call};
|
||||
|
||||
fn main() {
|
||||
let (
|
||||
@ -23,8 +22,7 @@ fn main() {
|
||||
|
||||
let pre_states_clone = pre_states.clone();
|
||||
|
||||
let (post_states, chained_calls): (Vec<AccountPostState>, Vec<ChainedCall>) = match instruction
|
||||
{
|
||||
let (post_states, chained_calls) = match instruction {
|
||||
Instruction::NewDefinition {
|
||||
token_a_amount,
|
||||
token_b_amount,
|
||||
@ -49,8 +47,8 @@ fn main() {
|
||||
user_holding_a,
|
||||
user_holding_b,
|
||||
user_holding_lp,
|
||||
token_a_amount,
|
||||
token_b_amount,
|
||||
NonZero::new(token_a_amount).expect("Token A should have a nonzero amount"),
|
||||
NonZero::new(token_b_amount).expect("Token B should have a nonzero amount"),
|
||||
amm_program_id,
|
||||
)
|
||||
}
|
||||
@ -78,7 +76,8 @@ fn main() {
|
||||
user_holding_a,
|
||||
user_holding_b,
|
||||
user_holding_lp,
|
||||
min_amount_liquidity,
|
||||
NonZero::new(min_amount_liquidity)
|
||||
.expect("Min amount of liquidity should be nonzero"),
|
||||
max_amount_to_add_token_a,
|
||||
max_amount_to_add_token_b,
|
||||
)
|
||||
@ -107,7 +106,8 @@ fn main() {
|
||||
user_holding_a,
|
||||
user_holding_b,
|
||||
user_holding_lp,
|
||||
remove_liquidity_amount,
|
||||
NonZero::new(remove_liquidity_amount)
|
||||
.expect("Remove liquidity amount must be nonzero"),
|
||||
min_amount_to_remove_token_a,
|
||||
min_amount_to_remove_token_b,
|
||||
)
|
||||
|
||||
@ -6,4 +6,5 @@ edition = "2024"
|
||||
[dependencies]
|
||||
nssa_core.workspace = true
|
||||
serde.workspace = true
|
||||
risc0-zkvm.workspace = true
|
||||
risc0-zkvm.workspace = true
|
||||
borsh.workspace = true
|
||||
@ -1,5 +1,6 @@
|
||||
//! This crate contains core data structures and utilities for the AMM Program.
|
||||
|
||||
use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use nssa_core::{
|
||||
account::{AccountId, Data},
|
||||
program::{PdaSeed, ProgramId},
|
||||
@ -74,9 +75,7 @@ pub enum Instruction {
|
||||
},
|
||||
}
|
||||
|
||||
const POOL_DEFINITION_DATA_SIZE: usize = 225;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
#[derive(Clone, Default, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
|
||||
pub struct PoolDefinition {
|
||||
pub definition_token_a_id: AccountId,
|
||||
pub definition_token_b_id: AccountId,
|
||||
@ -94,73 +93,23 @@ pub struct PoolDefinition {
|
||||
pub active: bool,
|
||||
}
|
||||
|
||||
impl PoolDefinition {
|
||||
pub fn into_data(self) -> Data {
|
||||
let mut bytes = [0; POOL_DEFINITION_DATA_SIZE];
|
||||
bytes[0..32].copy_from_slice(&self.definition_token_a_id.to_bytes());
|
||||
bytes[32..64].copy_from_slice(&self.definition_token_b_id.to_bytes());
|
||||
bytes[64..96].copy_from_slice(&self.vault_a_id.to_bytes());
|
||||
bytes[96..128].copy_from_slice(&self.vault_b_id.to_bytes());
|
||||
bytes[128..160].copy_from_slice(&self.liquidity_pool_id.to_bytes());
|
||||
bytes[160..176].copy_from_slice(&self.liquidity_pool_supply.to_le_bytes());
|
||||
bytes[176..192].copy_from_slice(&self.reserve_a.to_le_bytes());
|
||||
bytes[192..208].copy_from_slice(&self.reserve_b.to_le_bytes());
|
||||
bytes[208..224].copy_from_slice(&self.fees.to_le_bytes());
|
||||
bytes[224] = self.active as u8;
|
||||
impl TryFrom<&Data> for PoolDefinition {
|
||||
type Error = std::io::Error;
|
||||
|
||||
bytes
|
||||
.to_vec()
|
||||
.try_into()
|
||||
.expect("225 bytes should fit into Data")
|
||||
fn try_from(data: &Data) -> Result<Self, Self::Error> {
|
||||
PoolDefinition::try_from_slice(data.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(data: &[u8]) -> Option<Self> {
|
||||
if data.len() != POOL_DEFINITION_DATA_SIZE {
|
||||
None
|
||||
} else {
|
||||
let definition_token_a_id = AccountId::new(data[0..32].try_into().expect("Parse data: The AMM program must be provided a valid AccountId for Token A definition"));
|
||||
let definition_token_b_id = AccountId::new(data[32..64].try_into().expect("Parse data: The AMM program must be provided a valid AccountId for Vault B definition"));
|
||||
let vault_a_id = AccountId::new(data[64..96].try_into().expect(
|
||||
"Parse data: The AMM program must be provided a valid AccountId for Vault A",
|
||||
));
|
||||
let vault_b_id = AccountId::new(data[96..128].try_into().expect(
|
||||
"Parse data: The AMM program must be provided a valid AccountId for Vault B",
|
||||
));
|
||||
let liquidity_pool_id = AccountId::new(data[128..160].try_into().expect("Parse data: The AMM program must be provided a valid AccountId for Token liquidity pool definition"));
|
||||
let liquidity_pool_supply = u128::from_le_bytes(data[160..176].try_into().expect(
|
||||
"Parse data: The AMM program must be provided a valid u128 for liquidity cap",
|
||||
));
|
||||
let reserve_a = u128::from_le_bytes(data[176..192].try_into().expect(
|
||||
"Parse data: The AMM program must be provided a valid u128 for reserve A balance",
|
||||
));
|
||||
let reserve_b = u128::from_le_bytes(data[192..208].try_into().expect(
|
||||
"Parse data: The AMM program must be provided a valid u128 for reserve B balance",
|
||||
));
|
||||
let fees = u128::from_le_bytes(
|
||||
data[208..224]
|
||||
.try_into()
|
||||
.expect("Parse data: The AMM program must be provided a valid u128 for fees"),
|
||||
);
|
||||
impl From<&PoolDefinition> for Data {
|
||||
fn from(definition: &PoolDefinition) -> Self {
|
||||
// Using size_of_val as size hint for Vec allocation
|
||||
let mut data = Vec::with_capacity(std::mem::size_of_val(definition));
|
||||
|
||||
let active = match data[224] {
|
||||
0 => false,
|
||||
1 => true,
|
||||
_ => panic!("Parse data: The AMM program must be provided a valid bool for active"),
|
||||
};
|
||||
BorshSerialize::serialize(definition, &mut data)
|
||||
.expect("Serialization to Vec should not fail");
|
||||
|
||||
Some(Self {
|
||||
definition_token_a_id,
|
||||
definition_token_b_id,
|
||||
vault_a_id,
|
||||
vault_b_id,
|
||||
liquidity_pool_id,
|
||||
liquidity_pool_supply,
|
||||
reserve_a,
|
||||
reserve_b,
|
||||
fees,
|
||||
active,
|
||||
})
|
||||
}
|
||||
Data::try_from(data).expect("Token definition encoded data should fit into Data")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
use std::num::NonZeroU128;
|
||||
|
||||
use amm_core::{PoolDefinition, compute_liquidity_token_pda_seed};
|
||||
use nssa_core::{
|
||||
account::AccountWithMetadata,
|
||||
account::{AccountWithMetadata, Data},
|
||||
program::{AccountPostState, ChainedCall},
|
||||
};
|
||||
|
||||
@ -13,32 +15,33 @@ pub fn add_liquidity(
|
||||
user_holding_a: AccountWithMetadata,
|
||||
user_holding_b: AccountWithMetadata,
|
||||
user_holding_lp: AccountWithMetadata,
|
||||
min_amount_liquidity: u128,
|
||||
min_amount_liquidity: NonZeroU128,
|
||||
max_amount_to_add_token_a: u128,
|
||||
max_amount_to_add_token_b: u128,
|
||||
) -> (Vec<AccountPostState>, Vec<ChainedCall>) {
|
||||
// 1. Fetch Pool state
|
||||
let pool_def_data = PoolDefinition::parse(&pool.account.data)
|
||||
let pool_def_data = PoolDefinition::try_from(&pool.account.data)
|
||||
.expect("Add liquidity: AMM Program expects valid Pool Definition Account");
|
||||
if vault_a.account_id != pool_def_data.vault_a_id {
|
||||
panic!("Vault A was not provided");
|
||||
}
|
||||
|
||||
if pool_def_data.liquidity_pool_id != pool_definition_lp.account_id {
|
||||
panic!("LP definition mismatch");
|
||||
}
|
||||
assert_eq!(
|
||||
vault_a.account_id, pool_def_data.vault_a_id,
|
||||
"Vault A was not provided"
|
||||
);
|
||||
|
||||
if vault_b.account_id != pool_def_data.vault_b_id {
|
||||
panic!("Vault B was not provided");
|
||||
}
|
||||
assert_eq!(
|
||||
pool_def_data.liquidity_pool_id, pool_definition_lp.account_id,
|
||||
"LP definition mismatch"
|
||||
);
|
||||
|
||||
if max_amount_to_add_token_a == 0 || max_amount_to_add_token_b == 0 {
|
||||
panic!("Both max-balances must be nonzero");
|
||||
}
|
||||
assert_eq!(
|
||||
vault_b.account_id, pool_def_data.vault_b_id,
|
||||
"Vault B was not provided"
|
||||
);
|
||||
|
||||
if min_amount_liquidity == 0 {
|
||||
panic!("Min-lp must be nonzero");
|
||||
}
|
||||
assert!(
|
||||
max_amount_to_add_token_a != 0 && max_amount_to_add_token_b != 0,
|
||||
"Both max-balances must be nonzero"
|
||||
);
|
||||
|
||||
// 2. Determine deposit amount
|
||||
let vault_b_token_holding = token_core::TokenHolding::try_from(&vault_b.account.data)
|
||||
@ -65,13 +68,16 @@ pub fn add_liquidity(
|
||||
);
|
||||
};
|
||||
|
||||
if pool_def_data.reserve_a == 0 || pool_def_data.reserve_b == 0 {
|
||||
panic!("Reserves must be nonzero");
|
||||
}
|
||||
|
||||
if vault_a_balance < pool_def_data.reserve_a || vault_b_balance < pool_def_data.reserve_b {
|
||||
panic!("Vaults' balances must be at least the reserve amounts");
|
||||
}
|
||||
assert!(pool_def_data.reserve_a != 0, "Reserves must be nonzero");
|
||||
assert!(pool_def_data.reserve_b != 0, "Reserves must be nonzero");
|
||||
assert!(
|
||||
vault_a_balance >= pool_def_data.reserve_a,
|
||||
"Vaults' balances must be at least the reserve amounts"
|
||||
);
|
||||
assert!(
|
||||
vault_b_balance >= pool_def_data.reserve_b,
|
||||
"Vaults' balances must be at least the reserve amounts"
|
||||
);
|
||||
|
||||
// Calculate actual_amounts
|
||||
let ideal_a: u128 =
|
||||
@ -91,13 +97,17 @@ pub fn add_liquidity(
|
||||
};
|
||||
|
||||
// 3. Validate amounts
|
||||
if max_amount_to_add_token_a < actual_amount_a || max_amount_to_add_token_b < actual_amount_b {
|
||||
panic!("Actual trade amounts cannot exceed max_amounts");
|
||||
}
|
||||
assert!(
|
||||
max_amount_to_add_token_a >= actual_amount_a,
|
||||
"Actual trade amounts cannot exceed max_amounts"
|
||||
);
|
||||
assert!(
|
||||
max_amount_to_add_token_b >= actual_amount_b,
|
||||
"Actual trade amounts cannot exceed max_amounts"
|
||||
);
|
||||
|
||||
if actual_amount_a == 0 || actual_amount_b == 0 {
|
||||
panic!("A trade amount is 0");
|
||||
}
|
||||
assert!(actual_amount_a != 0, "A trade amount is 0");
|
||||
assert!(actual_amount_b != 0, "A trade amount is 0");
|
||||
|
||||
// 4. Calculate LP to mint
|
||||
let delta_lp = std::cmp::min(
|
||||
@ -105,13 +115,12 @@ pub fn add_liquidity(
|
||||
pool_def_data.liquidity_pool_supply * actual_amount_b / pool_def_data.reserve_b,
|
||||
);
|
||||
|
||||
if delta_lp == 0 {
|
||||
panic!("Payable LP must be nonzero");
|
||||
}
|
||||
assert!(delta_lp != 0, "Payable LP must be nonzero");
|
||||
|
||||
if delta_lp < min_amount_liquidity {
|
||||
panic!("Payable LP is less than provided minimum LP amount");
|
||||
}
|
||||
assert!(
|
||||
delta_lp >= min_amount_liquidity.into(),
|
||||
"Payable LP is less than provided minimum LP amount"
|
||||
);
|
||||
|
||||
// 5. Update pool account
|
||||
let mut pool_post = pool.account.clone();
|
||||
@ -122,7 +131,7 @@ pub fn add_liquidity(
|
||||
..pool_def_data
|
||||
};
|
||||
|
||||
pool_post.data = pool_post_definition.into_data();
|
||||
pool_post.data = Data::from(&pool_post_definition);
|
||||
let token_program_id = user_holding_a.account.program_owner;
|
||||
|
||||
// Chain call for Token A (UserHoldingA -> Vault_A)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//! The AMM Program implementation.
|
||||
|
||||
pub use token_core as core;
|
||||
pub use amm_core as core;
|
||||
|
||||
pub mod add;
|
||||
pub mod new_definition;
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use std::num::NonZeroU128;
|
||||
|
||||
use amm_core::{
|
||||
PoolDefinition, compute_liquidity_token_pda, compute_liquidity_token_pda_seed,
|
||||
compute_pool_pda, compute_vault_pda,
|
||||
};
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata},
|
||||
account::{Account, AccountWithMetadata, Data},
|
||||
program::{AccountPostState, ChainedCall, ProgramId},
|
||||
};
|
||||
|
||||
@ -20,11 +22,6 @@ pub fn new_definition(
|
||||
token_b_amount: NonZeroU128,
|
||||
amm_program_id: ProgramId,
|
||||
) -> (Vec<AccountPostState>, Vec<ChainedCall>) {
|
||||
// Prevents pool constant coefficient (k) from being 0.
|
||||
if token_a_amount == 0 || token_b_amount == 0 {
|
||||
panic!("Balances must be nonzero")
|
||||
}
|
||||
|
||||
// Verify token_a and token_b are different
|
||||
let definition_token_a_id = token_core::TokenHolding::try_from(&user_holding_a.account.data)
|
||||
.expect("New definition: AMM Program expects valid Token Holding account for Token A")
|
||||
@ -36,43 +33,48 @@ pub fn new_definition(
|
||||
// both instances of the same token program
|
||||
let token_program = user_holding_a.account.program_owner;
|
||||
|
||||
if user_holding_b.account.program_owner != token_program {
|
||||
panic!("User Token holdings must use the same Token Program");
|
||||
}
|
||||
|
||||
if definition_token_a_id == definition_token_b_id {
|
||||
panic!("Cannot set up a swap for a token with itself")
|
||||
}
|
||||
|
||||
if pool.account_id
|
||||
!= compute_pool_pda(amm_program_id, definition_token_a_id, definition_token_b_id)
|
||||
{
|
||||
panic!("Pool Definition Account ID does not match PDA");
|
||||
}
|
||||
|
||||
if vault_a.account_id
|
||||
!= compute_vault_pda(amm_program_id, pool.account_id, definition_token_a_id)
|
||||
|| vault_b.account_id
|
||||
!= compute_vault_pda(amm_program_id, pool.account_id, definition_token_b_id)
|
||||
{
|
||||
panic!("Vault ID does not match PDA");
|
||||
}
|
||||
|
||||
if pool_definition_lp.account_id != compute_liquidity_token_pda(amm_program_id, pool.account_id)
|
||||
{
|
||||
panic!("Liquidity pool Token Definition Account ID does not match PDA");
|
||||
}
|
||||
assert_eq!(
|
||||
user_holding_b.account.program_owner, token_program,
|
||||
"User Token holdings must use the same Token Program"
|
||||
);
|
||||
assert!(
|
||||
definition_token_a_id != definition_token_b_id,
|
||||
"Cannot set up a swap for a token with itself"
|
||||
);
|
||||
assert_eq!(
|
||||
pool.account_id,
|
||||
compute_pool_pda(amm_program_id, definition_token_a_id, definition_token_b_id),
|
||||
"Pool Definition Account ID does not match PDA"
|
||||
);
|
||||
assert_eq!(
|
||||
vault_a.account_id,
|
||||
compute_vault_pda(amm_program_id, pool.account_id, definition_token_a_id),
|
||||
"Vault ID does not match PDA"
|
||||
);
|
||||
assert_eq!(
|
||||
vault_b.account_id,
|
||||
compute_vault_pda(amm_program_id, pool.account_id, definition_token_b_id),
|
||||
"Vault ID does not match PDA"
|
||||
);
|
||||
assert_eq!(
|
||||
pool_definition_lp.account_id,
|
||||
compute_liquidity_token_pda(amm_program_id, pool.account_id),
|
||||
"Liquidity pool Token Definition Account ID does not match PDA"
|
||||
);
|
||||
|
||||
// TODO: return here
|
||||
// Verify that Pool Account is not active
|
||||
let pool_account_data = if pool.account == Account::default() {
|
||||
PoolDefinition::default()
|
||||
} else {
|
||||
PoolDefinition::parse(&pool.account.data).expect("AMM program expects a valid Pool account")
|
||||
PoolDefinition::try_from(&pool.account.data)
|
||||
.expect("AMM program expects a valid Pool account")
|
||||
};
|
||||
|
||||
if pool_account_data.active {
|
||||
panic!("Cannot initialize an active Pool Definition")
|
||||
}
|
||||
assert!(
|
||||
!pool_account_data.active,
|
||||
"Cannot initialize an active Pool Definition"
|
||||
);
|
||||
|
||||
// LP Token minting calculation
|
||||
// We assume LP is based on the initial deposit amount for Token_A.
|
||||
@ -85,14 +87,14 @@ 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,
|
||||
reserve_a: token_a_amount,
|
||||
reserve_b: token_b_amount,
|
||||
liquidity_pool_supply: token_a_amount.into(),
|
||||
reserve_a: token_a_amount.into(),
|
||||
reserve_b: token_b_amount.into(),
|
||||
fees: 0u128, // TODO: we assume all fees are 0 for now.
|
||||
active: true,
|
||||
};
|
||||
|
||||
pool_post.data = pool_post_definition.into_data();
|
||||
pool_post.data = Data::from(&pool_post_definition);
|
||||
let pool_post: AccountPostState = if pool.account == Account::default() {
|
||||
AccountPostState::new_claimed(pool_post.clone())
|
||||
} else {
|
||||
@ -106,7 +108,7 @@ pub fn new_definition(
|
||||
token_program_id,
|
||||
vec![user_holding_a.clone(), vault_a.clone()],
|
||||
&token_core::Instruction::Transfer {
|
||||
amount_to_transfer: token_a_amount,
|
||||
amount_to_transfer: token_a_amount.into(),
|
||||
},
|
||||
);
|
||||
// Chain call for Token B (user_holding_b -> Vault_B)
|
||||
@ -114,7 +116,7 @@ pub fn new_definition(
|
||||
token_program_id,
|
||||
vec![user_holding_b.clone(), vault_b.clone()],
|
||||
&token_core::Instruction::Transfer {
|
||||
amount_to_transfer: token_b_amount,
|
||||
amount_to_transfer: token_b_amount.into(),
|
||||
},
|
||||
);
|
||||
|
||||
@ -122,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,
|
||||
total_supply: token_a_amount.into(),
|
||||
}
|
||||
} else {
|
||||
token_core::Instruction::Mint {
|
||||
amount_to_mint: token_a_amount,
|
||||
amount_to_mint: token_a_amount.into(),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
use std::num::NonZeroU128;
|
||||
|
||||
use amm_core::{PoolDefinition, compute_liquidity_token_pda_seed, compute_vault_pda_seed};
|
||||
use nssa_core::{
|
||||
account::AccountWithMetadata,
|
||||
account::{AccountWithMetadata, Data},
|
||||
program::{AccountPostState, ChainedCall},
|
||||
};
|
||||
|
||||
@ -13,29 +15,29 @@ pub fn remove_liquidity(
|
||||
user_holding_a: AccountWithMetadata,
|
||||
user_holding_b: AccountWithMetadata,
|
||||
user_holding_lp: AccountWithMetadata,
|
||||
remove_liquidity_amount: u128,
|
||||
remove_liquidity_amount: NonZeroU128,
|
||||
min_amount_to_remove_token_a: u128,
|
||||
min_amount_to_remove_token_b: u128,
|
||||
) -> (Vec<AccountPostState>, Vec<ChainedCall>) {
|
||||
let remove_liquidity_amount: u128 = remove_liquidity_amount.into();
|
||||
|
||||
// 1. Fetch Pool state
|
||||
let pool_def_data = PoolDefinition::parse(&pool.account.data)
|
||||
let pool_def_data = PoolDefinition::try_from(&pool.account.data)
|
||||
.expect("Remove liquidity: AMM Program expects a valid Pool Definition Account");
|
||||
|
||||
if !pool_def_data.active {
|
||||
panic!("Pool is inactive");
|
||||
}
|
||||
|
||||
if pool_def_data.liquidity_pool_id != pool_definition_lp.account_id {
|
||||
panic!("LP definition mismatch");
|
||||
}
|
||||
|
||||
if vault_a.account_id != pool_def_data.vault_a_id {
|
||||
panic!("Vault A was not provided");
|
||||
}
|
||||
|
||||
if vault_b.account_id != pool_def_data.vault_b_id {
|
||||
panic!("Vault B was not provided");
|
||||
}
|
||||
assert!(pool_def_data.active, "Pool is inactive");
|
||||
assert_eq!(
|
||||
pool_def_data.liquidity_pool_id, pool_definition_lp.account_id,
|
||||
"LP definition mismatch"
|
||||
);
|
||||
assert_eq!(
|
||||
vault_a.account_id, pool_def_data.vault_a_id,
|
||||
"Vault A was not provided"
|
||||
);
|
||||
assert_eq!(
|
||||
vault_b.account_id, pool_def_data.vault_b_id,
|
||||
"Vault B was not provided"
|
||||
);
|
||||
|
||||
// Vault addresses do not need to be checked with PDA
|
||||
// calculation for setting authorization since stored
|
||||
@ -45,13 +47,14 @@ pub fn remove_liquidity(
|
||||
running_vault_a.is_authorized = true;
|
||||
running_vault_b.is_authorized = true;
|
||||
|
||||
if min_amount_to_remove_token_a == 0 || min_amount_to_remove_token_b == 0 {
|
||||
panic!("Minimum withdraw amount must be nonzero");
|
||||
}
|
||||
|
||||
if remove_liquidity_amount == 0 {
|
||||
panic!("Liquidity amount must be nonzero");
|
||||
}
|
||||
assert!(
|
||||
min_amount_to_remove_token_a != 0,
|
||||
"Minimum withdraw amount must be nonzero"
|
||||
);
|
||||
assert!(
|
||||
min_amount_to_remove_token_b != 0,
|
||||
"Minimum withdraw amount must be nonzero"
|
||||
);
|
||||
|
||||
// 2. Compute withdrawal amounts
|
||||
let user_holding_lp_data = token_core::TokenHolding::try_from(&user_holding_lp.account.data)
|
||||
@ -66,11 +69,15 @@ pub fn remove_liquidity(
|
||||
);
|
||||
};
|
||||
|
||||
if user_lp_balance > pool_def_data.liquidity_pool_supply
|
||||
|| user_holding_lp_data.definition_id() != pool_def_data.liquidity_pool_id
|
||||
{
|
||||
panic!("Invalid liquidity account provided");
|
||||
}
|
||||
assert!(
|
||||
user_lp_balance <= pool_def_data.liquidity_pool_supply,
|
||||
"Invalid liquidity account provided"
|
||||
);
|
||||
assert_eq!(
|
||||
user_holding_lp_data.definition_id(),
|
||||
pool_def_data.liquidity_pool_id,
|
||||
"Invalid liquidity account provided"
|
||||
);
|
||||
|
||||
let withdraw_amount_a =
|
||||
(pool_def_data.reserve_a * remove_liquidity_amount) / pool_def_data.liquidity_pool_supply;
|
||||
@ -78,12 +85,14 @@ pub fn remove_liquidity(
|
||||
(pool_def_data.reserve_b * remove_liquidity_amount) / pool_def_data.liquidity_pool_supply;
|
||||
|
||||
// 3. Validate and slippage check
|
||||
if withdraw_amount_a < min_amount_to_remove_token_a {
|
||||
panic!("Insufficient minimal withdraw amount (Token A) provided for liquidity amount");
|
||||
}
|
||||
if withdraw_amount_b < min_amount_to_remove_token_b {
|
||||
panic!("Insufficient minimal withdraw amount (Token B) provided for liquidity amount");
|
||||
}
|
||||
assert!(
|
||||
withdraw_amount_a >= min_amount_to_remove_token_a,
|
||||
"Insufficient minimal withdraw amount (Token A) provided for liquidity amount"
|
||||
);
|
||||
assert!(
|
||||
withdraw_amount_b >= min_amount_to_remove_token_b,
|
||||
"Insufficient minimal withdraw amount (Token B) provided for liquidity amount"
|
||||
);
|
||||
|
||||
// 4. Calculate LP to reduce cap by
|
||||
let delta_lp: u128 = (pool_def_data.liquidity_pool_supply * remove_liquidity_amount)
|
||||
@ -101,7 +110,7 @@ pub fn remove_liquidity(
|
||||
..pool_def_data.clone()
|
||||
};
|
||||
|
||||
pool_post.data = pool_post_definition.into_data();
|
||||
pool_post.data = Data::from(&pool_post_definition);
|
||||
|
||||
let token_program_id = user_holding_a.account.program_owner;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
pub use amm_core::{PoolDefinition, compute_liquidity_token_pda_seed, compute_vault_pda_seed};
|
||||
use nssa_core::{
|
||||
account::{AccountId, AccountWithMetadata},
|
||||
account::{AccountId, AccountWithMetadata, Data},
|
||||
program::{AccountPostState, ChainedCall},
|
||||
};
|
||||
|
||||
@ -16,20 +16,18 @@ pub fn swap(
|
||||
token_in_id: AccountId,
|
||||
) -> (Vec<AccountPostState>, Vec<ChainedCall>) {
|
||||
// Verify vaults are in fact vaults
|
||||
let pool_def_data = PoolDefinition::parse(&pool.account.data)
|
||||
let pool_def_data = PoolDefinition::try_from(&pool.account.data)
|
||||
.expect("Swap: AMM Program expects a valid Pool Definition Account");
|
||||
|
||||
if !pool_def_data.active {
|
||||
panic!("Pool is inactive");
|
||||
}
|
||||
|
||||
if vault_a.account_id != pool_def_data.vault_a_id {
|
||||
panic!("Vault A was not provided");
|
||||
}
|
||||
|
||||
if vault_b.account_id != pool_def_data.vault_b_id {
|
||||
panic!("Vault B was not provided");
|
||||
}
|
||||
assert!(pool_def_data.active, "Pool is inactive");
|
||||
assert_eq!(
|
||||
vault_a.account_id, pool_def_data.vault_a_id,
|
||||
"Vault A was not provided"
|
||||
);
|
||||
assert_eq!(
|
||||
vault_b.account_id, pool_def_data.vault_b_id,
|
||||
"Vault B was not provided"
|
||||
);
|
||||
|
||||
// fetch pool reserves
|
||||
// validates reserves is at least the vaults' balances
|
||||
@ -42,9 +40,11 @@ pub fn swap(
|
||||
else {
|
||||
panic!("Swap: AMM Program expects a valid Fungible Token Holding Account for Vault A");
|
||||
};
|
||||
if vault_a_balance < pool_def_data.reserve_a {
|
||||
panic!("Reserve for Token A exceeds vault balance");
|
||||
}
|
||||
|
||||
assert!(
|
||||
vault_a_balance >= pool_def_data.reserve_a,
|
||||
"Reserve for Token A exceeds vault balance"
|
||||
);
|
||||
|
||||
let vault_b_token_holding = token_core::TokenHolding::try_from(&vault_b.account.data)
|
||||
.expect("Swap: AMM Program expects a valid Token Holding Account for Vault B");
|
||||
@ -56,9 +56,10 @@ pub fn swap(
|
||||
panic!("Swap: AMM Program expects a valid Fungible Token Holding Account for Vault B");
|
||||
};
|
||||
|
||||
if vault_b_balance < pool_def_data.reserve_b {
|
||||
panic!("Reserve for Token B exceeds vault balance");
|
||||
}
|
||||
assert!(
|
||||
vault_b_balance >= pool_def_data.reserve_b,
|
||||
"Reserve for Token B exceeds vault balance"
|
||||
);
|
||||
|
||||
let (chained_calls, [deposit_a, withdraw_a], [deposit_b, withdraw_b]) =
|
||||
if token_in_id == pool_def_data.definition_token_a_id {
|
||||
@ -69,7 +70,8 @@ pub fn swap(
|
||||
user_holding_b.clone(),
|
||||
swap_amount_in,
|
||||
min_amount_out,
|
||||
&[pool_def_data.reserve_a, pool_def_data.reserve_b],
|
||||
pool_def_data.reserve_a,
|
||||
pool_def_data.reserve_b,
|
||||
pool.account_id,
|
||||
);
|
||||
|
||||
@ -82,7 +84,8 @@ pub fn swap(
|
||||
user_holding_a.clone(),
|
||||
swap_amount_in,
|
||||
min_amount_out,
|
||||
&[pool_def_data.reserve_b, pool_def_data.reserve_a],
|
||||
pool_def_data.reserve_b,
|
||||
pool_def_data.reserve_a,
|
||||
pool.account_id,
|
||||
);
|
||||
|
||||
@ -99,7 +102,7 @@ pub fn swap(
|
||||
..pool_def_data
|
||||
};
|
||||
|
||||
pool_post.data = pool_post_definition.into_data();
|
||||
pool_post.data = Data::from(&pool_post_definition);
|
||||
|
||||
let post_states = vec![
|
||||
AccountPostState::new(pool_post.clone()),
|
||||
@ -120,12 +123,10 @@ fn swap_logic(
|
||||
user_withdraw: AccountWithMetadata,
|
||||
swap_amount_in: u128,
|
||||
min_amount_out: u128,
|
||||
reserve_amounts: &[u128],
|
||||
reserve_deposit_vault_amount: u128,
|
||||
reserve_withdraw_vault_amount: u128,
|
||||
pool_id: AccountId,
|
||||
) -> (Vec<ChainedCall>, u128, u128) {
|
||||
let reserve_deposit_vault_amount = reserve_amounts[0];
|
||||
let reserve_withdraw_vault_amount = reserve_amounts[1];
|
||||
|
||||
// Compute withdraw amount
|
||||
// Maintains pool constant product
|
||||
// k = pool_def_data.reserve_a * pool_def_data.reserve_b;
|
||||
@ -133,13 +134,11 @@ fn swap_logic(
|
||||
/ (reserve_deposit_vault_amount + swap_amount_in);
|
||||
|
||||
// Slippage check
|
||||
if min_amount_out > withdraw_amount {
|
||||
panic!("Withdraw amount is less than minimal amount out");
|
||||
}
|
||||
|
||||
if withdraw_amount == 0 {
|
||||
panic!("Withdraw amount should be nonzero");
|
||||
}
|
||||
assert!(
|
||||
min_amount_out <= withdraw_amount,
|
||||
"Withdraw amount is less than minimal amount out"
|
||||
);
|
||||
assert!(withdraw_amount != 0, "Withdraw amount should be nonzero");
|
||||
|
||||
let token_program_id = user_deposit.account.program_owner;
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#![cfg(test)]
|
||||
|
||||
use std::num::NonZero;
|
||||
|
||||
use amm_core::{
|
||||
PoolDefinition, compute_liquidity_token_pda, compute_liquidity_token_pda_seed,
|
||||
compute_pool_pda, compute_vault_pda, compute_vault_pda_seed,
|
||||
@ -630,7 +632,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -654,7 +656,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -678,7 +680,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -702,7 +704,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -726,7 +728,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -750,7 +752,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -774,7 +776,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -798,7 +800,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -822,7 +824,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -846,7 +848,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -870,7 +872,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -894,7 +896,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -950,7 +952,7 @@ impl AccountForTests {
|
||||
account: Account {
|
||||
program_owner: ProgramId::default(),
|
||||
balance: 0u128,
|
||||
data: PoolDefinition::into_data(PoolDefinition {
|
||||
data: Data::from(&PoolDefinition {
|
||||
definition_token_a_id: IdForTests::token_a_definition_id(),
|
||||
definition_token_b_id: IdForTests::token_b_definition_id(),
|
||||
vault_a_id: IdForTests::vault_a_id(),
|
||||
@ -996,7 +998,7 @@ fn test_call_add_liquidity_vault_a_omitted() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
|
||||
BalanceForTests::add_max_amount_a(),
|
||||
BalanceForTests::add_max_amount_b(),
|
||||
);
|
||||
@ -1013,7 +1015,7 @@ fn test_call_add_liquidity_vault_b_omitted() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
|
||||
BalanceForTests::add_max_amount_a(),
|
||||
BalanceForTests::add_max_amount_b(),
|
||||
);
|
||||
@ -1030,7 +1032,7 @@ fn test_call_add_liquidity_lp_definition_mismatch() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
|
||||
BalanceForTests::add_max_amount_a(),
|
||||
BalanceForTests::add_max_amount_b(),
|
||||
);
|
||||
@ -1047,7 +1049,7 @@ fn test_call_add_liquidity_zero_balance_1() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
|
||||
0,
|
||||
BalanceForTests::add_max_amount_b(),
|
||||
);
|
||||
@ -1064,29 +1066,12 @@ fn test_call_add_liquidity_zero_balance_2() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
|
||||
0,
|
||||
BalanceForTests::add_max_amount_a(),
|
||||
);
|
||||
}
|
||||
|
||||
#[should_panic(expected = "Min-lp must be nonzero")]
|
||||
#[test]
|
||||
fn test_call_add_liquidity_zero_min_lp() {
|
||||
let _post_states = add_liquidity(
|
||||
AccountForTests::pool_definition_init(),
|
||||
AccountForTests::vault_a_init(),
|
||||
AccountForTests::vault_b_init(),
|
||||
AccountForTests::pool_lp_init(),
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
0,
|
||||
BalanceForTests::add_max_amount_a(),
|
||||
BalanceForTests::add_max_amount_b(),
|
||||
);
|
||||
}
|
||||
|
||||
#[should_panic(expected = "Vaults' balances must be at least the reserve amounts")]
|
||||
#[test]
|
||||
fn test_call_add_liquidity_vault_insufficient_balance_1() {
|
||||
@ -1098,7 +1083,7 @@ fn test_call_add_liquidity_vault_insufficient_balance_1() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_max_amount_a(),
|
||||
NonZero::new(BalanceForTests::add_max_amount_a()).unwrap(),
|
||||
BalanceForTests::add_max_amount_b(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
);
|
||||
@ -1115,7 +1100,7 @@ fn test_call_add_liquidity_vault_insufficient_balance_2() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_max_amount_a(),
|
||||
NonZero::new(BalanceForTests::add_max_amount_a()).unwrap(),
|
||||
BalanceForTests::add_max_amount_b(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
);
|
||||
@ -1132,7 +1117,7 @@ fn test_call_add_liquidity_actual_amount_zero_1() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
|
||||
BalanceForTests::add_max_amount_a(),
|
||||
BalanceForTests::add_max_amount_b(),
|
||||
);
|
||||
@ -1149,7 +1134,7 @@ fn test_call_add_liquidity_actual_amount_zero_2() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
|
||||
BalanceForTests::add_max_amount_a_low(),
|
||||
BalanceForTests::add_max_amount_b_low(),
|
||||
);
|
||||
@ -1166,7 +1151,7 @@ fn test_call_add_liquidity_reserves_zero_1() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
|
||||
BalanceForTests::add_max_amount_a(),
|
||||
BalanceForTests::add_max_amount_b(),
|
||||
);
|
||||
@ -1183,7 +1168,7 @@ fn test_call_add_liquidity_reserves_zero_2() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
|
||||
BalanceForTests::add_max_amount_a(),
|
||||
BalanceForTests::add_max_amount_b(),
|
||||
);
|
||||
@ -1200,7 +1185,7 @@ fn test_call_add_liquidity_payable_lp_zero() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
|
||||
BalanceForTests::add_max_amount_a_low(),
|
||||
BalanceForTests::add_max_amount_b_low(),
|
||||
);
|
||||
@ -1216,7 +1201,7 @@ fn test_call_add_liquidity_chained_call_successsful() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::add_min_amount_lp(),
|
||||
NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(),
|
||||
BalanceForTests::add_max_amount_a(),
|
||||
BalanceForTests::add_max_amount_b(),
|
||||
);
|
||||
@ -1245,7 +1230,7 @@ fn test_call_remove_liquidity_vault_a_omitted() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::remove_amount_lp(),
|
||||
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
|
||||
BalanceForTests::remove_min_amount_a(),
|
||||
BalanceForTests::remove_min_amount_b(),
|
||||
);
|
||||
@ -1262,7 +1247,7 @@ fn test_call_remove_liquidity_vault_b_omitted() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::remove_amount_lp(),
|
||||
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
|
||||
BalanceForTests::remove_min_amount_a(),
|
||||
BalanceForTests::remove_min_amount_b(),
|
||||
);
|
||||
@ -1279,7 +1264,7 @@ fn test_call_remove_liquidity_lp_def_mismatch() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::remove_amount_lp(),
|
||||
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
|
||||
BalanceForTests::remove_min_amount_a(),
|
||||
BalanceForTests::remove_min_amount_b(),
|
||||
);
|
||||
@ -1297,7 +1282,7 @@ fn test_call_remove_liquidity_insufficient_liquidity_amount() {
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_a(), /* different token account than lp to create desired
|
||||
* error */
|
||||
BalanceForTests::remove_amount_lp(),
|
||||
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
|
||||
BalanceForTests::remove_min_amount_a(),
|
||||
BalanceForTests::remove_min_amount_b(),
|
||||
);
|
||||
@ -1316,7 +1301,7 @@ fn test_call_remove_liquidity_insufficient_balance_1() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::remove_amount_lp_1(),
|
||||
NonZero::new(BalanceForTests::remove_amount_lp_1()).unwrap(),
|
||||
BalanceForTests::remove_min_amount_a(),
|
||||
BalanceForTests::remove_min_amount_b(),
|
||||
);
|
||||
@ -1335,7 +1320,7 @@ fn test_call_remove_liquidity_insufficient_balance_2() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::remove_amount_lp(),
|
||||
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
|
||||
BalanceForTests::remove_min_amount_a(),
|
||||
BalanceForTests::remove_min_amount_b(),
|
||||
);
|
||||
@ -1352,7 +1337,7 @@ fn test_call_remove_liquidity_min_bal_zero_1() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::remove_amount_lp(),
|
||||
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
|
||||
0,
|
||||
BalanceForTests::remove_min_amount_b(),
|
||||
);
|
||||
@ -1369,29 +1354,12 @@ fn test_call_remove_liquidity_min_bal_zero_2() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::remove_amount_lp(),
|
||||
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
|
||||
BalanceForTests::remove_min_amount_a(),
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
#[should_panic(expected = "Liquidity amount must be nonzero")]
|
||||
#[test]
|
||||
fn test_call_remove_liquidity_lp_bal_zero() {
|
||||
let _post_states = remove_liquidity(
|
||||
AccountForTests::pool_definition_init(),
|
||||
AccountForTests::vault_a_init(),
|
||||
AccountForTests::vault_b_init(),
|
||||
AccountForTests::pool_lp_init(),
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
0,
|
||||
BalanceForTests::remove_min_amount_a(),
|
||||
BalanceForTests::remove_min_amount_b(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_call_remove_liquidity_chained_call_successful() {
|
||||
let (post_states, chained_calls) = remove_liquidity(
|
||||
@ -1402,7 +1370,7 @@ fn test_call_remove_liquidity_chained_call_successful() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_init(),
|
||||
BalanceForTests::remove_amount_lp(),
|
||||
NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(),
|
||||
BalanceForTests::remove_min_amount_a(),
|
||||
BalanceForTests::remove_min_amount_b_low(),
|
||||
);
|
||||
@ -1431,8 +1399,8 @@ fn test_call_new_definition_with_zero_balance_1() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
0,
|
||||
BalanceForTests::vault_b_reserve_init(),
|
||||
NonZero::new(0).expect("Balances must be nonzero"),
|
||||
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
|
||||
AMM_PROGRAM_ID,
|
||||
);
|
||||
}
|
||||
@ -1448,8 +1416,8 @@ fn test_call_new_definition_with_zero_balance_2() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
BalanceForTests::vault_a_reserve_init(),
|
||||
0,
|
||||
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
|
||||
NonZero::new(0).expect("Balances must be nonzero"),
|
||||
AMM_PROGRAM_ID,
|
||||
);
|
||||
}
|
||||
@ -1465,8 +1433,8 @@ fn test_call_new_definition_same_token_definition() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
BalanceForTests::vault_a_reserve_init(),
|
||||
BalanceForTests::vault_b_reserve_init(),
|
||||
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
|
||||
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
|
||||
AMM_PROGRAM_ID,
|
||||
);
|
||||
}
|
||||
@ -1482,8 +1450,8 @@ fn test_call_new_definition_wrong_liquidity_id() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
BalanceForTests::vault_a_reserve_init(),
|
||||
BalanceForTests::vault_b_reserve_init(),
|
||||
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
|
||||
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
|
||||
AMM_PROGRAM_ID,
|
||||
);
|
||||
}
|
||||
@ -1499,8 +1467,8 @@ fn test_call_new_definition_wrong_pool_id() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
BalanceForTests::vault_a_reserve_init(),
|
||||
BalanceForTests::vault_b_reserve_init(),
|
||||
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
|
||||
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
|
||||
AMM_PROGRAM_ID,
|
||||
);
|
||||
}
|
||||
@ -1516,8 +1484,8 @@ fn test_call_new_definition_wrong_vault_id_1() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
BalanceForTests::vault_a_reserve_init(),
|
||||
BalanceForTests::vault_b_reserve_init(),
|
||||
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
|
||||
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
|
||||
AMM_PROGRAM_ID,
|
||||
);
|
||||
}
|
||||
@ -1533,8 +1501,8 @@ fn test_call_new_definition_wrong_vault_id_2() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
BalanceForTests::vault_a_reserve_init(),
|
||||
BalanceForTests::vault_b_reserve_init(),
|
||||
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
|
||||
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
|
||||
AMM_PROGRAM_ID,
|
||||
);
|
||||
}
|
||||
@ -1550,8 +1518,8 @@ fn test_call_new_definition_cannot_initialize_active_pool() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
BalanceForTests::vault_a_reserve_init(),
|
||||
BalanceForTests::vault_b_reserve_init(),
|
||||
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
|
||||
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
|
||||
AMM_PROGRAM_ID,
|
||||
);
|
||||
}
|
||||
@ -1567,8 +1535,8 @@ fn test_call_new_definition_chained_call_successful() {
|
||||
AccountForTests::user_holding_a(),
|
||||
AccountForTests::user_holding_b(),
|
||||
AccountForTests::user_holding_lp_uninit(),
|
||||
BalanceForTests::vault_a_reserve_init(),
|
||||
BalanceForTests::vault_b_reserve_init(),
|
||||
NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(),
|
||||
NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(),
|
||||
AMM_PROGRAM_ID,
|
||||
);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user