From 6f9e5b44243c7aa9db6bcc160333bcde760b88a8 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 3 Jul 2024 01:03:05 +0200 Subject: [PATCH 01/28] wip --- amm/drink-tests/Cargo.lock | 1 + amm/drink-tests/Cargo.toml | 4 + amm/drink-tests/src/lib.rs | 2 - amm/drink-tests/src/stable_swap_tests/mod.rs | 136 +++++ .../tests_rated.rs} | 20 +- .../src/stable_swap_tests/tests_sim.rs | 519 ++++++++++++++++++ .../tests_swap_exact_in.rs} | 160 ++---- .../stable_swap_tests/tests_swap_received.rs | 255 +++++++++ amm/drink-tests/src/utils.rs | 74 ++- 9 files changed, 1045 insertions(+), 126 deletions(-) create mode 100644 amm/drink-tests/src/stable_swap_tests/mod.rs rename amm/drink-tests/src/{rated_swap_tests.rs => stable_swap_tests/tests_rated.rs} (90%) create mode 100644 amm/drink-tests/src/stable_swap_tests/tests_sim.rs rename amm/drink-tests/src/{stable_swap_tests.rs => stable_swap_tests/tests_swap_exact_in.rs} (60%) create mode 100644 amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs diff --git a/amm/drink-tests/Cargo.lock b/amm/drink-tests/Cargo.lock index d7293e8..6fedd43 100644 --- a/amm/drink-tests/Cargo.lock +++ b/amm/drink-tests/Cargo.lock @@ -79,6 +79,7 @@ dependencies = [ "ink-wrapper-types", "ink_primitives", "parity-scale-codec", + "primitive-types", ] [[package]] diff --git a/amm/drink-tests/Cargo.toml b/amm/drink-tests/Cargo.toml index fa53f99..e0ea2e8 100644 --- a/amm/drink-tests/Cargo.toml +++ b/amm/drink-tests/Cargo.toml @@ -16,5 +16,9 @@ scale = { package = "parity-scale-codec", version = "3", default-features = fals "derive", ] } +primitive-types = { version = "0.12.1", default-features = false, features = [ + "codec", +] } + anyhow = "1.0.69" assert2 = "0.3.10" diff --git a/amm/drink-tests/src/lib.rs b/amm/drink-tests/src/lib.rs index 695c6e7..b7e9962 100644 --- a/amm/drink-tests/src/lib.rs +++ b/amm/drink-tests/src/lib.rs @@ -1,8 +1,6 @@ #[cfg(test)] mod psp22; #[cfg(test)] -mod rated_swap_tests; -#[cfg(test)] #[allow(unused_imports)] mod sazero_rate_mock_contract; #[cfg(test)] diff --git a/amm/drink-tests/src/stable_swap_tests/mod.rs b/amm/drink-tests/src/stable_swap_tests/mod.rs new file mode 100644 index 0000000..ee576a1 --- /dev/null +++ b/amm/drink-tests/src/stable_swap_tests/mod.rs @@ -0,0 +1,136 @@ +mod tests_rated; +mod tests_sim; +mod tests_swap_exact_in; +mod tests_swap_received; + +use crate::stable_pool_contract; +pub use crate::utils::*; +use primitive_types::U256; + +pub use stable_pool_contract::StablePool as _; +pub use stable_pool_contract::StablePoolError; +pub use stable_pool_contract::StablePoolView as _; + +use drink::{self, runtime::MinimalRuntime, session::Session, AccountId32}; + +use ink_primitives::AccountId; +use ink_wrapper_types::{Connection, ToAccountId}; + +pub const FEE_BPS_DENOM: u128 = 10_000; + +pub const FEE_RECEIVER: AccountId32 = AccountId32::new([42u8; 32]); + +pub fn fee_receiver() -> ink_primitives::AccountId { + AsRef::<[u8; 32]>::as_ref(&FEE_RECEIVER).clone().into() +} + +pub fn setup_stable_swap_with_tokens( + session: &mut Session, + token_decimals: Vec, + token_supply: Vec, + amp_coef: u128, + fee_bps: u16, + protocol_fee_bps: u16, + caller: AccountId32, +) -> (AccountId, Vec) { + let _ = session.set_actor(caller); + + if token_decimals.len() != token_supply.len() { + panic!("SETUP: Inconsistent number of tokens.") + } + + upload_all(session); + + // instantiate tokens + let tokens: Vec = token_decimals + .iter() + .zip(token_supply.iter()) + .enumerate() + .map(|(id, (&decimals, &supply))| { + psp22_utils::setup_with_amounts( + session, + format!("Test Token {id}").to_string(), + decimals, + supply, + BOB, + ) + .into() + }) + .collect::>(); + + // instantiate stable_swap + let instance = stable_pool_contract::Instance::new_stable( + tokens.clone(), + token_decimals, + amp_coef, + bob(), + fee_bps, + protocol_fee_bps, + Some(fee_receiver()), + ); + + let stable_swap: stable_pool_contract::Instance = session + .instantiate(instance) + .unwrap() + .result + .to_account_id() + .into(); + + // setup max allowance for stable swap contract on both tokens + for token in tokens.clone() { + psp22_utils::increase_allowance(session, token.into(), stable_swap.into(), u128::MAX, BOB) + .unwrap(); + } + + (stable_swap.into(), tokens) +} + +pub fn share_price_and_total_shares( + session: &mut Session, + stable_swap: AccountId, +) -> (u128, u128) { + let total_shares = psp22_utils::total_supply(session, stable_swap); + let reserves = stable_swap::reserves(session, stable_swap); + let sum_token = stable_swap::tokens(session, stable_swap) + .iter() + .zip(reserves.iter()) + .fold(0, |acc, (&token, reserve)| { + acc + reserve * 10u128.pow((18 - psp22_utils::token_decimals(session, token)).into()) + }); + + ( + U256::from(sum_token) + .checked_mul(100000000.into()) + .unwrap() + .checked_div(total_shares.into()) + .unwrap_or(100000000.into()) + .as_u128(), + total_shares, + ) +} + +pub fn transfer_and_increase_allowance( + session: &mut Session, + stable_swap: AccountId, + tokens: Vec, + receiver: AccountId32, + amounts: Vec, + caller: AccountId32, +) { + for (&token, &amount) in tokens.iter().zip(amounts.iter()) { + _ = psp22_utils::transfer( + session, + token, + receiver.to_account_id(), + amount, + caller.clone(), + ); + _ = psp22_utils::increase_allowance( + session, + token, + stable_swap, + u128::MAX, + receiver.clone(), + ); + } +} diff --git a/amm/drink-tests/src/rated_swap_tests.rs b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs similarity index 90% rename from amm/drink-tests/src/rated_swap_tests.rs rename to amm/drink-tests/src/stable_swap_tests/tests_rated.rs index 3ef0023..ba0015b 100644 --- a/amm/drink-tests/src/rated_swap_tests.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs @@ -2,6 +2,8 @@ use crate::sazero_rate_mock_contract; use crate::stable_pool_contract; use crate::utils::*; +use super::*; + use drink::{self, runtime::MinimalRuntime, session::Session}; use ink_primitives::AccountId; use ink_wrapper_types::{Connection, ToAccountId}; @@ -19,7 +21,7 @@ const PROTOCOL_FEE_BPS: u16 = 2000; const AMP_COEF: u128 = 1000; -fn setup_rated_swap( +fn setup_rated_swap_with_tokens( session: &mut Session, sazero: AccountId, wazero: AccountId, @@ -69,6 +71,7 @@ fn setup_rated_swap( fn setup_all( session: &mut Session, + _enable_protocol_fee: bool, ) -> (AccountId, AccountId, AccountId) { upload_all(session); @@ -86,7 +89,7 @@ fn setup_all( INIT_SUPPLY * ONE_SAZERO, BOB, ); - let stable_pool_contract = setup_rated_swap( + let stable_pool_contract = setup_rated_swap_with_tokens( session, sazero.into(), wazero.into(), @@ -113,12 +116,12 @@ fn setup_all( } #[drink::test] -fn test_rated_1(mut session: Session) { +fn test_01(mut session: Session) { let one_minute: u64 = 60000; let now = get_timestamp(&mut session); set_timestamp(&mut session, now); upload_all(&mut session); - let (rated_swap, sazero, wazero) = setup_all(&mut session); + let (rated_swap, sazero, wazero) = setup_all(&mut session, false); _ = stable_swap::add_liquidity( &mut session, rated_swap.into(), @@ -139,7 +142,7 @@ fn test_rated_1(mut session: Session) { .unwrap(); set_timestamp(&mut session, now + 10000 * one_minute); - _ = stable_swap::swap_exact_in( + let (_amount_out, _fee) = handle_ink_error(stable_swap::swap_exact_in( &mut session, rated_swap.into(), BOB, @@ -148,10 +151,9 @@ fn test_rated_1(mut session: Session) { amount, 1, // min_token_out bob(), - ) - .result - .unwrap() - .unwrap_or_else(|_| panic!("Should return valid result")); + )) + .unwrap_or_else(|err| panic!("Should return valid result. Err: {err:?}")); + let reserves = stable_swap::reserves(&mut session, rated_swap.into()); let balance_0 = psp22_utils::balance_of(&mut session, sazero.into(), rated_swap.into()); let balance_1 = psp22_utils::balance_of(&mut session, wazero.into(), rated_swap.into()); diff --git a/amm/drink-tests/src/stable_swap_tests/tests_sim.rs b/amm/drink-tests/src/stable_swap_tests/tests_sim.rs new file mode 100644 index 0000000..ebcbb46 --- /dev/null +++ b/amm/drink-tests/src/stable_swap_tests/tests_sim.rs @@ -0,0 +1,519 @@ +use drink::{self, session::Session}; + +const ONE_LPT: u128 = 1000000000000000000; +const ONE_DAI: u128 = 1000000000000000000; +const ONE_USDT: u128 = 1000000; +const ONE_USDC: u128 = 1000000; + +use super::*; + +#[drink::test] +fn test_01(mut session: Session) { + let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![18, 6, 6], + initial_reserves.iter().map(|amount| amount * 10).collect(), + 10_000, + 25, + 2000, + BOB, + ); + + handle_ink_error(stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + )) + .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + + assert_eq!( + stable_swap::tokens(&mut session, stable_swap), + tokens, + "Incorrect token accounts" + ); + assert_eq!( + stable_swap::reserves(&mut session, stable_swap), + initial_reserves, + "Incorrect reserves" + ); + assert_eq!( + stable_swap::amp_coef(&mut session, stable_swap), + 10_000, + "Incorrect A" + ); + assert_eq!( + stable_swap::fees(&mut session, stable_swap), + (25, 2000), + "Incorrect fees" + ); + assert_eq!( + psp22_utils::total_supply(&mut session, stable_swap), + 300_000 * ONE_LPT, + "Incorrect LP token supply" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, bob()), + 300_000 * ONE_LPT, + "Incorrect Users LP token balance" + ); + + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, bob())) + .collect(); + assert_eq!( + balances, + initial_reserves + .iter() + .map(|amount| amount * 9) + .collect::>(), + "Incorrect Users tokens balances" + ); + + _ = handle_ink_error(stable_swap::swap_exact_in( + &mut session, + stable_swap, + BOB, + tokens[0], // DAI + tokens[2], // USDC + ONE_DAI, // amount_in + 1, // min_token_out + charlie(), + )) + .unwrap_or_else(|err| panic!("Should successfully swap. Err: {err:?}")); + + _ = handle_ink_error(stable_swap::swap_exact_in( + &mut session, + stable_swap, + BOB, + tokens[0], // DAI + tokens[1], // USDC + ONE_DAI, // amount_in + 1, // min_token_out + charlie(), + )) + .unwrap_or_else(|err| panic!("Should successfully swap. Err: {err:?}")); + + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, charlie())) + .collect(); + assert_eq!( + balances, + vec![0, 997499, 997499], + "Incorrect Users tokens balances" + ); + + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, stable_swap)) + .collect(); + assert_eq!( + stable_swap::reserves(&mut session, stable_swap), + balances, + "Pool reserves and token balances mismatch" + ); + + assert_eq!( + stable_swap::reserves(&mut session, stable_swap), + vec![ + 100002 * ONE_DAI, + 99999 * ONE_USDT + 2501, // -- DIFF -- 99999 * ONE_USDT + 2500 + 99999 * ONE_USDC + 2501 // -- DIFF -- 99999 * ONE_USDC + 2500 + ], + "Incorrect reserves" + ); + assert_eq!( + psp22_utils::total_supply(&mut session, stable_swap), + 300000 * ONE_LPT + 498999996725367 + 498999993395420, // -- DIFF -- 300000 * ONE_LPT + 499999996666583 + 499999993277742 + "Incorrect LP token supply" + ); +} + +#[drink::test] +fn test_02(mut session: Session) { + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![18, 6, 6], + initial_reserves + .iter() + .map(|amount| amount * 100_000_000_000) + .collect(), + 10_000, + 25, + 2000, + BOB, + ); + + handle_ink_error(stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + )) + .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + + let (last_share_price, last_total_shares) = + share_price_and_total_shares(&mut session, stable_swap); + + transfer_and_increase_allowance( + &mut session, + stable_swap, + tokens.clone(), + CHARLIE, + vec![500 * ONE_DAI, 500 * ONE_USDT, 500 * ONE_USDC], + BOB, + ); + + handle_ink_error(stable_swap::add_liquidity( + &mut session, + stable_swap, + CHARLIE, + 1, + vec![500 * ONE_DAI, 500 * ONE_USDT, 500 * ONE_USDC], + charlie(), + )) + .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + + assert_eq!( + share_price_and_total_shares(&mut session, stable_swap), + (last_share_price, last_total_shares + 1500 * ONE_LPT) + ); + + let last_total_shares = last_total_shares + 1500 * ONE_LPT; + + handle_ink_error(stable_swap::remove_liquidity_by_shares( + &mut session, + stable_swap, + CHARLIE, + 300 * ONE_LPT, + vec![1 * ONE_DAI, 1 * ONE_USDT, 1 * ONE_USDC], + charlie(), + )) + .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, charlie()), + 1200 * ONE_LPT + ); + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, charlie())) + .collect(); + assert_eq!( + balances, + vec![100 * ONE_DAI, 100 * ONE_USDT, 100 * ONE_USDC], + "Incorrect Users tokens balances" + ); + assert_eq!( + share_price_and_total_shares(&mut session, stable_swap), + (last_share_price, last_total_shares - 300 * ONE_LPT) + ); + let last_total_shares = last_total_shares - 300 * ONE_LPT; + + transfer_and_increase_allowance( + &mut session, + stable_swap, + tokens.clone(), + DAVE, + vec![100 * ONE_DAI, 200 * ONE_USDT, 400 * ONE_USDC], + BOB, + ); + + handle_ink_error(stable_swap::add_liquidity( + &mut session, + stable_swap, + DAVE, + 1, + vec![100 * ONE_DAI, 200 * ONE_USDT, 400 * ONE_USDC], + dave(), + )) + .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + + assert_eq!( + stable_swap::reserves(&mut session, stable_swap), + vec![100500 * ONE_DAI, 100600 * ONE_USDT, 100800 * ONE_USDC], + "Incorrect reserves" + ); + assert_eq!( + psp22_utils::total_supply(&mut session, stable_swap), + 301200 * ONE_LPT + 699699997426210330025 + 59999999669779069, + "Incorrect total shares" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, dave()), + 699699997426210330025, + "Incorrect Users share" + ); + + let (current_share_price, current_total_shares) = + share_price_and_total_shares(&mut session, stable_swap); + assert!( + current_share_price > last_share_price, + "Incorrect share price" + ); + let last_share_price = current_share_price; + + assert_eq!( + current_total_shares, + last_total_shares + 699699997426210330025 + 59999999669779069 + ); + let last_total_shares = current_total_shares; + + handle_ink_error(stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + CHARLIE, + 550 * ONE_LPT, + vec![1 * ONE_DAI, 500 * ONE_USDT, 1 * ONE_USDC], + charlie(), + )) + .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, charlie()), + 1200 * ONE_LPT - 502598511257512352631, + "Incorrect users share" + ); + + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, charlie())) + .collect(); + assert_eq!( + balances, + vec![101 * ONE_DAI, 600 * ONE_USDT, 101 * ONE_USDC], + "Incorrect Users tokens balances" + ); + + assert_eq!( + stable_swap::reserves(&mut session, stable_swap), + vec![100499 * ONE_DAI, 100100 * ONE_USDT, 100799 * ONE_USDC], + "Incorrect reserves" + ); + assert_eq!( + psp22_utils::total_supply(&mut session, stable_swap), + last_total_shares - 502598511257512352631 + 119779860286480103, + "Incorrect total shares" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, charlie()), + 1200 * ONE_LPT - 502598511257512352631, + "Incorrect users share" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, dave()), + 699699997426210330025, + "Incorrect users share" + ); + let (current_share_price, current_total_shares) = + share_price_and_total_shares(&mut session, stable_swap); + assert!( + current_share_price > last_share_price, + "Incorrect share price" + ); + let last_share_price = current_share_price; + let last_total_shares = last_total_shares - 502598511257512352631 + 119779860286480103; + + _ = psp22_utils::transfer(&mut session, stable_swap, dave(), 100 * ONE_LPT, CHARLIE); + + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, charlie()), + 1100 * ONE_LPT - 502598511257512352631, + "Incorrect user balance" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, dave()), + 699699997426210330025 + 100 * ONE_LPT, + "Incorrect user balance" + ); + + assert_eq!( + share_price_and_total_shares(&mut session, stable_swap), + (last_share_price, last_total_shares), + "Incorrect share price and/or total shares" + ); + + let res = handle_ink_error(stable_swap::remove_liquidity_by_shares( + &mut session, + stable_swap, + DAVE, + 300 * ONE_LPT, + vec![1 * ONE_DAI, 298 * ONE_USDT, 1 * ONE_USDC], + dave(), + )); + + assert_eq!( + res, + Err(StablePoolError::InsufficientOutputAmount()), + "Should return correct error" + ); + + assert_eq!( + share_price_and_total_shares(&mut session, stable_swap), + (last_share_price, last_total_shares), + "Incorrect share price and/or total shares" + ); + + let res = handle_ink_error(stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + DAVE, + 300 * ONE_LPT, + vec![1 * ONE_DAI, 298 * ONE_USDT, 1 * ONE_USDC], + dave(), + )); + + assert_eq!( + res, + Err(StablePoolError::InsufficientLiquidityBurned()), + "Should return correct error" + ); + + assert_eq!( + share_price_and_total_shares(&mut session, stable_swap), + (last_share_price, last_total_shares), + "Incorrect share price and/or total shares" + ); + + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, charlie()), + 1100 * ONE_LPT - 502598511257512352631, + "Incorrect user balance" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, dave()), + 699699997426210330025 + 100 * ONE_LPT, + "Incorrect user balance" + ); + + handle_ink_error(stable_swap::remove_liquidity_by_shares( + &mut session, + stable_swap, + DAVE, + 300 * ONE_LPT, + vec![1 * ONE_DAI, 1 * ONE_USDT, 1 * ONE_USDC], + dave(), + )) + .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, charlie()), + 1100 * ONE_LPT - 502598511257512352631, + "Incorrect user balance" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, dave()), + 699699997426210330025 - 200 * ONE_LPT, + "Incorrect user balance" + ); + + let (current_share_price, current_total_shares) = + share_price_and_total_shares(&mut session, stable_swap); + assert_eq!( + current_share_price, last_share_price, + "Incorrect share price" + ); + assert_eq!( + current_total_shares, + last_total_shares - 300 * ONE_LPT, + "Incorrect total shares" + ); + let last_total_shares = last_total_shares - 300 * ONE_LPT; + + handle_ink_error(stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + DAVE, + 499 * ONE_LPT, + vec![498 * ONE_DAI, 0 * ONE_USDT, 0 * ONE_USDC], + dave(), + )) + .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + // "LP user2 removed 498596320225563082252 shares by given tokens, and fee is 597500435701476809 shares", + // "Exchange swap got 119500087140295361 shares, No referral fee, from remove_liquidity_by_tokens", + /* -- DIFF -- + "LP user2 removed 498596320224035614380 shares by given tokens, and fee is 597500435700561479 shares", + "Exchange swap got 119500087140112295 shares, No referral fee (not implemented)", + */ + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, charlie()), + 1100 * ONE_LPT - 502598511257512352631, + "Incorrect user balance" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, dave()), + 699699997426210330025 - 200 * ONE_LPT - 498596320224035614380, + "Incorrect user balance" + ); + + let last_total_shares = last_total_shares - 498596320224035614380 + 119500087140112295; + let (current_share_price, current_total_shares) = + share_price_and_total_shares(&mut session, stable_swap); + assert!( + current_share_price > last_share_price, + "Incorrect share price" + ); + assert_eq!( + current_total_shares, last_total_shares, + "Incorrect total shares" + ); + let last_share_price = current_share_price; + + transfer_and_increase_allowance( + &mut session, + stable_swap, + tokens.clone(), + EVA, + vec![ + 100_000_000_000 * ONE_DAI, + 100_000_000_000 * ONE_USDT, + 100_000_000_000 * ONE_USDC, + ], + BOB, + ); + + + handle_ink_error(stable_swap::add_liquidity( + &mut session, + stable_swap, + EVA, + 1, + vec![ + 100_000_000_000 * ONE_DAI, + 100_000_000_000 * ONE_USDT, + 100_000_000_000 * ONE_USDC, + ], + eva(), + )) + .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + // "Mint 299997911758886758506069372942 shares for user3, fee is 895808190595468286848457 shares", + // "Exchange swap got 179161638119093657369691 shares, No referral fee, from add_liquidity", + /* -- DIFF -- + "Mint 299997911757966485300035937427 shares for user3, fee is 895808191250701043141970 shares", + "Exchange swap got 179161638250140208628394 shares, No referral fee, from add_liquidity", + */ + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, eva()), + 299997911757966485300035937427, + "Incorrect user balance" + ); + + let last_total_shares = + last_total_shares + 299997911757966485300035937427 + 179161638250140208628394; + assert_eq!( + psp22_utils::total_supply(&mut session, stable_swap), + last_total_shares, + "Incorrect total shares" + ); +} diff --git a/amm/drink-tests/src/stable_swap_tests.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs similarity index 60% rename from amm/drink-tests/src/stable_swap_tests.rs rename to amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs index 2b61f7b..51c69f1 100644 --- a/amm/drink-tests/src/stable_swap_tests.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs @@ -1,89 +1,27 @@ -use crate::stable_pool_contract::{self, StablePoolError}; -use crate::utils::*; - use drink::{self, runtime::MinimalRuntime, session::Session}; -use ink_primitives::AccountId; -use ink_wrapper_types::{Connection, ToAccountId}; - -const FEE_BPS_DENOM: u128 = 10_000; - -fn setup_stable_swap( - session: &mut Session, - token_decimals: [u8; 2], - token_supply: [u128; 2], - amp_coef: u128, - fee_bps: u16, - protocol_fee_bps: u16, -) -> (AccountId, AccountId, AccountId) { - // (stable_pool, token_0, token_1) - let _ = session.set_actor(BOB); - upload_all(session); - session - .upload_code(stable_pool_contract::upload()) - .expect("Upload stable_pair_contract code"); - - // instantiate tokens - let token_0 = psp22_utils::setup_with_amounts( - session, - "token_0".to_string(), - token_decimals[0], - token_supply[0], - BOB, - ); - let token_1 = psp22_utils::setup_with_amounts( - session, - "token_1".to_string(), - token_decimals[1], - token_supply[1], - BOB, - ); - - // instantiate stable_swap - let instance = stable_pool_contract::Instance::new_stable( - vec![token_0.into(), token_1.into()], - token_decimals.to_vec(), - amp_coef, - bob(), - fee_bps, - protocol_fee_bps, - Some(charlie()), // fee receiver - ); - - let stable_swap: stable_pool_contract::Instance = session - .instantiate(instance) - .unwrap() - .result - .to_account_id() - .into(); - // setup max allowance for stable swap contract on both tokens - for token in [token_0, token_1] { - psp22_utils::increase_allowance(session, token.into(), stable_swap.into(), u128::MAX, BOB) - .unwrap(); - } - - (stable_swap.into(), token_0.into(), token_1.into()) -} +use super::*; /// Tests swap of token at index 0 to token at index 1. fn setup_test_swap_exact_in( session: &mut Session, - token_decimals: [u8; 2], - initial_reserves: [u128; 2], + token_decimals: Vec, + initial_reserves: Vec, amp_coef: u128, fee_bps: u16, protocol_fee_bps: u16, swap_amount_in: u128, expected_swap_amount_out_total_result: Result, ) { - let initial_supply = [initial_reserves[0] + swap_amount_in, initial_reserves[1]]; - let (stable_swap, token_0, token_1) = setup_stable_swap( + let initial_supply = vec![initial_reserves[0] + swap_amount_in, initial_reserves[1]]; + let (stable_swap, tokens) = setup_stable_swap_with_tokens( session, token_decimals, initial_supply, amp_coef, fee_bps, protocol_fee_bps, + BOB, ); _ = stable_swap::add_liquidity( session, @@ -94,18 +32,16 @@ fn setup_test_swap_exact_in( bob(), ); - let swap_result = stable_swap::swap_exact_in( + let swap_result = handle_ink_error(stable_swap::swap_exact_in( session, - stable_swap.into(), + stable_swap, BOB, - token_0, // in - token_1, // out + tokens[0], // in + tokens[1], // out swap_amount_in, // amount_in 0, // min_token_out bob(), - ) - .result - .unwrap(); + )); if expected_swap_amount_out_total_result.is_err() { match swap_result { @@ -129,9 +65,9 @@ fn setup_test_swap_exact_in( assert_eq!(expected_fee, fee, "Fee mismatch"); // check if reserves are equal the actual balances - let reserves = stable_swap::reserves(session, stable_swap.into()); - let balance_0 = psp22_utils::balance_of(session, token_0.into(), stable_swap.into()); - let balance_1 = psp22_utils::balance_of(session, token_1.into(), stable_swap.into()); + let reserves = stable_swap::reserves(session, stable_swap); + let balance_0 = psp22_utils::balance_of(session, tokens[0], stable_swap); + let balance_1 = psp22_utils::balance_of(session, tokens[1], stable_swap); assert_eq!( reserves, vec![balance_0, balance_1], @@ -139,8 +75,8 @@ fn setup_test_swap_exact_in( ); // check bobs balances - let balance_0 = psp22_utils::balance_of(session, token_0.into(), bob()); - let balance_1 = psp22_utils::balance_of(session, token_1.into(), bob()); + let balance_0 = psp22_utils::balance_of(session, tokens[0], bob()); + let balance_1 = psp22_utils::balance_of(session, tokens[1], bob()); assert_eq!( [0, expected_swap_amount_out], [balance_0, balance_1], @@ -148,10 +84,10 @@ fn setup_test_swap_exact_in( ); // check protocol fee - let protocol_fee_lp = psp22_utils::balance_of(session, stable_swap.into(), charlie()); + let protocol_fee_lp = psp22_utils::balance_of(session, stable_swap, fee_receiver()); let (total_lp_required, lp_fee_part) = stable_swap::remove_liquidity_by_amounts( session, - stable_swap.into(), + stable_swap, BOB, protocol_fee_lp * 2, [0, expected_protocol_fee_part].to_vec(), @@ -169,11 +105,11 @@ fn setup_test_swap_exact_in( // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L744 #[drink::test] -fn test_stable_swap_exact_in_01(mut session: Session) { +fn test_01(mut session: Session) { setup_test_swap_exact_in( &mut session, - [6, 6], // decimals - [100000000000, 100000000000], // initial reserves + vec![6, 6], // decimals + vec![100000000000, 100000000000], // initial reserves 1000, // A 6, // fee BPS 2000, // protocol fee BPS @@ -184,11 +120,11 @@ fn test_stable_swap_exact_in_01(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L763 #[drink::test] -fn test_stable_swap_exact_in_02(mut session: Session) { +fn test_02(mut session: Session) { setup_test_swap_exact_in( &mut session, - [12, 18], - [100000000000000000, 100000000000000000000000], + vec![12, 18], + vec![100000000000000000, 100000000000000000000000], 1000, 6, 2000, @@ -199,11 +135,11 @@ fn test_stable_swap_exact_in_02(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L782 #[drink::test] -fn test_stable_swap_exact_in_03(mut session: Session) { +fn test_03(mut session: Session) { setup_test_swap_exact_in( &mut session, - [6, 6], - [100000000000, 100000000000], + vec![6, 6], + vec![100000000000, 100000000000], 1000, 6, 2000, @@ -214,11 +150,11 @@ fn test_stable_swap_exact_in_03(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L801 #[drink::test] -fn test_stable_swap_exact_in_04(mut session: Session) { +fn test_04(mut session: Session) { setup_test_swap_exact_in( &mut session, - [12, 18], - [100000000000000000, 100000000000000000000000], + vec![12, 18], + vec![100000000000000000, 100000000000000000000000], 1000, 6, 2000, @@ -229,11 +165,11 @@ fn test_stable_swap_exact_in_04(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L820 #[drink::test] -fn test_stable_swap_exact_in_05(mut session: Session) { +fn test_05(mut session: Session) { setup_test_swap_exact_in( &mut session, - [6, 6], - [100000000000, 100000000000], + vec![6, 6], + vec![100000000000, 100000000000], 1000, 6, 2000, @@ -244,11 +180,11 @@ fn test_stable_swap_exact_in_05(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L839 #[drink::test] -fn test_stable_swap_exact_in_06(mut session: Session) { +fn test_06(mut session: Session) { setup_test_swap_exact_in( &mut session, - [18, 12], - [100000000000000000000000, 100000000000000000], + vec![18, 12], + vec![100000000000000000000000, 100000000000000000], 1000, 6, 2000, @@ -259,11 +195,11 @@ fn test_stable_swap_exact_in_06(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L858 #[drink::test] -fn test_stable_swap_exact_in_07(mut session: Session) { +fn test_07(mut session: Session) { setup_test_swap_exact_in( &mut session, - [6, 6], - [100000000000, 100000000000], + vec![6, 6], + vec![100000000000, 100000000000], 1000, 6, 2000, @@ -274,11 +210,11 @@ fn test_stable_swap_exact_in_07(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L877 #[drink::test] -fn test_stable_swap_exact_in_08(mut session: Session) { +fn test_08(mut session: Session) { setup_test_swap_exact_in( &mut session, - [12, 18], - [100000000000000000, 100000000000000000000000], + vec![12, 18], + vec![100000000000000000, 100000000000000000000000], 1000, 6, 2000, @@ -289,11 +225,11 @@ fn test_stable_swap_exact_in_08(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L896 #[drink::test] -fn test_stable_swap_exact_in_09(mut session: Session) { +fn test_09(mut session: Session) { setup_test_swap_exact_in( &mut session, - [6, 6], - [100000000000, 100000000000], + vec![6, 6], + vec![100000000000, 100000000000], 1000, 6, 2000, @@ -304,11 +240,11 @@ fn test_stable_swap_exact_in_09(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L915 #[drink::test] -fn test_stable_swap_exact_in_10(mut session: Session) { +fn test_10(mut session: Session) { setup_test_swap_exact_in( &mut session, - [12, 18], - [100000000000000000, 100000000000000000000000], + vec![12, 18], + vec![100000000000000000, 100000000000000000000000], 1000, 6, 2000, diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs new file mode 100644 index 0000000..226dd1e --- /dev/null +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs @@ -0,0 +1,255 @@ +use drink::{self, runtime::MinimalRuntime, session::Session}; + +use super::*; + +/// Tests swap of token at index 0 to token at index 1. +fn setup_test_swap_received( + session: &mut Session, + token_decimals: Vec, + initial_reserves: Vec, + amp_coef: u128, + fee_bps: u16, + protocol_fee_bps: u16, + swap_amount_in: u128, + expected_swap_amount_out_total_result: Result, +) { + let initial_supply = vec![initial_reserves[0] + swap_amount_in, initial_reserves[1]]; + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + session, + token_decimals, + initial_supply, + amp_coef, + fee_bps, + protocol_fee_bps, + BOB, + ); + _ = stable_swap::add_liquidity( + session, + stable_swap, + BOB, + 1, + initial_reserves.to_vec(), + bob(), + ); + + let _ = psp22_utils::transfer(session, tokens[0], stable_swap, swap_amount_in, BOB); + + let swap_result = handle_ink_error(stable_swap::swap_received( + session, + stable_swap, + BOB, + tokens[0], // in + tokens[1], // out + 0, // min_token_out + bob(), + )); + + if expected_swap_amount_out_total_result.is_err() { + match swap_result { + Err(err) => { + let wrapped_error: Result = Err(err); + assert_eq!(expected_swap_amount_out_total_result, wrapped_error); + return; + } + Ok(val) => panic!("Should return an error. Return val: {val:?}"), + } + } + + let (amount_out, fee) = swap_result.unwrap(); + let expected_swap_amount_out_total = expected_swap_amount_out_total_result.unwrap(); + let expected_fee = expected_swap_amount_out_total * fee_bps as u128 / FEE_BPS_DENOM; + let expected_swap_amount_out = expected_swap_amount_out_total - expected_fee; + let expected_protocol_fee_part = expected_fee * protocol_fee_bps as u128 / FEE_BPS_DENOM; + + // check returned amount swapped and fee + assert_eq!(expected_swap_amount_out, amount_out, "Amount out mismatch"); + assert_eq!(expected_fee, fee, "Fee mismatch"); + + // check if reserves are equal the actual balances + let reserves = stable_swap::reserves(session, stable_swap); + let balance_0 = psp22_utils::balance_of(session, tokens[0], stable_swap); + let balance_1 = psp22_utils::balance_of(session, tokens[1], stable_swap); + assert_eq!( + reserves, + vec![balance_0, balance_1], + "Balances - reserves mismatch" + ); + + // check bobs balances + let balance_0 = psp22_utils::balance_of(session, tokens[0], bob()); + let balance_1 = psp22_utils::balance_of(session, tokens[1], bob()); + assert_eq!( + [0, expected_swap_amount_out], + [balance_0, balance_1], + "Incorrect Bob's balances" + ); + + // check protocol fee + let protocol_fee_lp = psp22_utils::balance_of(session, stable_swap.into(), fee_receiver()); + let (total_lp_required, lp_fee_part) = stable_swap::remove_liquidity_by_amounts( + session, + stable_swap.into(), + BOB, + protocol_fee_lp * 2, + [0, expected_protocol_fee_part].to_vec(), + bob(), + ) + .result + .unwrap() + .unwrap(); + assert_eq!( + total_lp_required - lp_fee_part, + protocol_fee_lp, + "Incorrect protocol fee" + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L744 +#[drink::test] +fn test_01(mut session: Session) { + setup_test_swap_received( + &mut session, + vec![6, 6], // decimals + vec![100000000000, 100000000000], // initial reserves + 1000, // A + 6, // fee BPS + 2000, // protocol fee BPS + 10000000000, // swap_amount_in + Ok(9999495232), // expected out (with fee) + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L763 +#[drink::test] +fn test_02(mut session: Session) { + setup_test_swap_received( + &mut session, + vec![12, 18], + vec![100000000000000000, 100000000000000000000000], + 1000, + 6, + 2000, + 10000000000000000, + Ok(9999495232752197989995), + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L782 +#[drink::test] +fn test_03(mut session: Session) { + setup_test_swap_received( + &mut session, + vec![6, 6], + vec![100000000000, 100000000000], + 1000, + 6, + 2000, + 0, + Err(StablePoolError::InsufficientInputAmount()), + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L801 +#[drink::test] +fn test_04(mut session: Session) { + setup_test_swap_received( + &mut session, + vec![12, 18], + vec![100000000000000000, 100000000000000000000000], + 1000, + 6, + 2000, + 0, + Err(StablePoolError::InsufficientInputAmount()), + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L820 +#[drink::test] +fn test_05(mut session: Session) { + setup_test_swap_received( + &mut session, + vec![6, 6], + vec![100000000000, 100000000000], + 1000, + 6, + 2000, + 1, + Ok(0), + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L839 +#[drink::test] +fn test_06(mut session: Session) { + setup_test_swap_received( + &mut session, + vec![18, 12], + vec![100000000000000000000000, 100000000000000000], + 1000, + 6, + 2000, + 1000000, + Ok(0), + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L858 +#[drink::test] +fn test_07(mut session: Session) { + setup_test_swap_received( + &mut session, + vec![6, 6], + vec![100000000000, 100000000000], + 1000, + 6, + 2000, + 100000000000, + Ok(98443663539), + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L877 +#[drink::test] +fn test_08(mut session: Session) { + setup_test_swap_received( + &mut session, + vec![12, 18], + vec![100000000000000000, 100000000000000000000000], + 1000, + 6, + 2000, + 100000000000000000, + Ok(98443663539913153080656), + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L896 +#[drink::test] +fn test_09(mut session: Session) { + setup_test_swap_received( + &mut session, + vec![6, 6], + vec![100000000000, 100000000000], + 1000, + 6, + 2000, + 99999000000 + 1, // +1 because of accounting for fee rounding + Ok(98443167413), + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L915 +#[drink::test] +fn test_10(mut session: Session) { + setup_test_swap_received( + &mut session, + vec![12, 18], + vec![100000000000000000, 100000000000000000000000], + 1000, + 6, + 2000, + 99999000000000000, + Ok(98443167413204135506296), + ); +} diff --git a/amm/drink-tests/src/utils.rs b/amm/drink-tests/src/utils.rs index 46414d4..2b1fc50 100644 --- a/amm/drink-tests/src/utils.rs +++ b/amm/drink-tests/src/utils.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] -#![allow(unused_variables)] use crate::*; use anyhow::Result; @@ -9,6 +7,8 @@ use ink_wrapper_types::{Connection, ContractResult, InkLangError, ToAccountId}; pub const BOB: drink::AccountId32 = AccountId32::new([1u8; 32]); pub const CHARLIE: drink::AccountId32 = AccountId32::new([3u8; 32]); +pub const DAVE: drink::AccountId32 = AccountId32::new([4u8; 32]); +pub const EVA: drink::AccountId32 = AccountId32::new([5u8; 32]); pub const TOKEN: u128 = 10u128.pow(18); @@ -20,6 +20,21 @@ pub fn charlie() -> ink_primitives::AccountId { AsRef::<[u8; 32]>::as_ref(&CHARLIE).clone().into() } +pub fn dave() -> ink_primitives::AccountId { + AsRef::<[u8; 32]>::as_ref(&DAVE).clone().into() +} + +pub fn eva() -> ink_primitives::AccountId { + AsRef::<[u8; 32]>::as_ref(&EVA).clone().into() +} + +pub fn seed_account(session: &mut Session, account: AccountId32) { + session + .sandbox() + .mint_into(account, 1_000_000_000u128) + .unwrap(); +} + pub fn upload_all(session: &mut Session) { session .upload_code(stable_pool_contract::upload()) @@ -171,6 +186,30 @@ pub mod stable_swap { .unwrap() } + pub fn swap_received( + session: &mut Session, + stable_pool: AccountId, + caller: drink::AccountId32, + token_in: AccountId, + token_out: AccountId, + min_token_out_amount: u128, + to: AccountId, + ) -> ContractResult< + Result, ink_wrapper_types::InkLangError>, + > { + let _ = session.set_actor(caller); + session + .execute( + stable_pool_contract::Instance::from(stable_pool).swap_received( + token_in, + token_out, + min_token_out_amount, + to, + ), + ) + .unwrap() + } + pub fn reserves(session: &mut Session, stable_pool: AccountId) -> Vec { session .query(stable_pool_contract::Instance::from(stable_pool).reserves()) @@ -178,11 +217,36 @@ pub mod stable_swap { .result .unwrap() } + + pub fn amp_coef(session: &mut Session, stable_pool: AccountId) -> u128 { + session + .query(stable_pool_contract::Instance::from(stable_pool).amp_coef()) + .unwrap() + .result + .unwrap() + } + + pub fn fees(session: &mut Session, stable_pool: AccountId) -> (u16, u16) { + session + .query(stable_pool_contract::Instance::from(stable_pool).fees()) + .unwrap() + .result + .unwrap() + } + + pub fn tokens(session: &mut Session, stable_pool: AccountId) -> Vec { + session + .query(stable_pool_contract::Instance::from(stable_pool).tokens()) + .unwrap() + .result + .unwrap() + } } pub mod psp22_utils { use super::*; - use psp22::{Instance as PSP22, PSP22 as _}; + use psp22::{Instance as PSP22, PSP22 as _, PSP22Metadata as _}; + /// Uploads and creates a PSP22 instance with 1B*10^18 issuance and given names. /// Returns its AccountId casted to PSP22 interface. @@ -282,6 +346,10 @@ pub mod psp22_utils { pub fn total_supply(session: &mut Session, token: AccountId) -> u128 { handle_ink_error(session.query(PSP22::total_supply(&token.into())).unwrap()) } + + pub fn token_decimals(session: &mut Session, token: AccountId) -> u8 { + handle_ink_error(session.query(PSP22::token_decimals(&token.into())).unwrap()) + } } pub fn get_timestamp(session: &mut Session) -> u64 { From 9c43c4bebfd554a0d5a21231c7847fd4de1efa15 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 3 Jul 2024 01:14:49 +0200 Subject: [PATCH 02/28] add ref to tests --- amm/drink-tests/src/stable_swap_tests/tests_sim.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_sim.rs b/amm/drink-tests/src/stable_swap_tests/tests_sim.rs index ebcbb46..e6a2328 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_sim.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_sim.rs @@ -7,6 +7,7 @@ const ONE_USDC: u128 = 1000000; use super::*; +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/tests/test_stable_pool.rs#L23 #[drink::test] fn test_01(mut session: Session) { let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; @@ -122,18 +123,19 @@ fn test_01(mut session: Session) { stable_swap::reserves(&mut session, stable_swap), vec![ 100002 * ONE_DAI, - 99999 * ONE_USDT + 2501, // -- DIFF -- 99999 * ONE_USDT + 2500 - 99999 * ONE_USDC + 2501 // -- DIFF -- 99999 * ONE_USDC + 2500 + 99999 * ONE_USDT + 2501, // -- DIFF -- 99999 * ONE_USDT + 2500 + 99999 * ONE_USDC + 2501 // -- DIFF -- 99999 * ONE_USDC + 2500 ], "Incorrect reserves" ); assert_eq!( psp22_utils::total_supply(&mut session, stable_swap), - 300000 * ONE_LPT + 498999996725367 + 498999993395420, // -- DIFF -- 300000 * ONE_LPT + 499999996666583 + 499999993277742 + 300000 * ONE_LPT + 498999996725367 + 498999993395420, // -- DIFF -- 300000 * ONE_LPT + 499999996666583 + 499999993277742 "Incorrect LP token supply" ); } +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/tests/test_stable_pool.rs#L123 #[drink::test] fn test_02(mut session: Session) { seed_account(&mut session, CHARLIE); @@ -483,7 +485,6 @@ fn test_02(mut session: Session) { BOB, ); - handle_ink_error(stable_swap::add_liquidity( &mut session, stable_swap, From 8dc698944d485843686be616f272dabc743eceb3 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 3 Jul 2024 11:42:47 +0200 Subject: [PATCH 03/28] add comments on differences --- .../src/stable_swap_tests/tests_sim.rs | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_sim.rs b/amm/drink-tests/src/stable_swap_tests/tests_sim.rs index e6a2328..30b73b5 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_sim.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_sim.rs @@ -177,6 +177,7 @@ fn test_02(mut session: Session) { BOB, ); + // add more liquidity with balanced tokens (charlie) handle_ink_error(stable_swap::add_liquidity( &mut session, stable_swap, @@ -194,6 +195,7 @@ fn test_02(mut session: Session) { let last_total_shares = last_total_shares + 1500 * ONE_LPT; + // remove by shares (charlie) handle_ink_error(stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, @@ -232,6 +234,7 @@ fn test_02(mut session: Session) { BOB, ); + // add more liquidity with imbalanced tokens (dave) handle_ink_error(stable_swap::add_liquidity( &mut session, stable_swap, @@ -241,6 +244,8 @@ fn test_02(mut session: Session) { dave(), )) .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + // "Mint 699699997426210330025 shares for user2, fee is 299999998348895348 shares", + // "Exchange swap got 59999999669779069 shares", assert_eq!( stable_swap::reserves(&mut session, stable_swap), @@ -272,6 +277,7 @@ fn test_02(mut session: Session) { ); let last_total_shares = current_total_shares; + // remove by tokens (charlie) handle_ink_error(stable_swap::remove_liquidity_by_amounts( &mut session, stable_swap, @@ -281,7 +287,8 @@ fn test_02(mut session: Session) { charlie(), )) .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); - + // "LP charlie removed 502598511257512352631 shares by given tokens, and fee is 598899301432400519 shares", + // "Exchange swap got 119779860286480103 shares", assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), 1200 * ONE_LPT - 502598511257512352631, @@ -318,8 +325,7 @@ fn test_02(mut session: Session) { 699699997426210330025, "Incorrect users share" ); - let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap); + let (current_share_price, _) = share_price_and_total_shares(&mut session, stable_swap); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -327,6 +333,7 @@ fn test_02(mut session: Session) { let last_share_price = current_share_price; let last_total_shares = last_total_shares - 502598511257512352631 + 119779860286480103; + // tansfer some LPT to from charlie to dave _ = psp22_utils::transfer(&mut session, stable_swap, dave(), 100 * ONE_LPT, CHARLIE); assert_eq!( @@ -346,6 +353,7 @@ fn test_02(mut session: Session) { "Incorrect share price and/or total shares" ); + // dave remove by shares trigger slippage let res = handle_ink_error(stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, @@ -367,6 +375,7 @@ fn test_02(mut session: Session) { "Incorrect share price and/or total shares" ); + // dave remove by tokens trigger slippage let res = handle_ink_error(stable_swap::remove_liquidity_by_amounts( &mut session, stable_swap, @@ -399,6 +408,7 @@ fn test_02(mut session: Session) { "Incorrect user balance" ); + // dave remove by share handle_ink_error(stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, @@ -408,6 +418,8 @@ fn test_02(mut session: Session) { dave(), )) .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + // "LP dave removed 498596320225563082252 shares by given tokens, and fee is 597500435701476809 shares", + // "Exchange swap got 119500087140295361 shares", assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), @@ -444,10 +456,10 @@ fn test_02(mut session: Session) { .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); // "LP user2 removed 498596320225563082252 shares by given tokens, and fee is 597500435701476809 shares", // "Exchange swap got 119500087140295361 shares, No referral fee, from remove_liquidity_by_tokens", - /* -- DIFF -- - "LP user2 removed 498596320224035614380 shares by given tokens, and fee is 597500435700561479 shares", - "Exchange swap got 119500087140112295 shares, No referral fee (not implemented)", - */ + // -- DIFF -- + // "LP dave removed 498596320224035614380 shares by given tokens, and fee is 597500435700561479 shares", + // "Exchange swap got 119500087140112295 shares, No referral fee (not implemented)", + // assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), 1100 * ONE_LPT - 502598511257512352631, @@ -470,7 +482,6 @@ fn test_02(mut session: Session) { current_total_shares, last_total_shares, "Incorrect total shares" ); - let last_share_price = current_share_price; transfer_and_increase_allowance( &mut session, @@ -500,10 +511,10 @@ fn test_02(mut session: Session) { .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); // "Mint 299997911758886758506069372942 shares for user3, fee is 895808190595468286848457 shares", // "Exchange swap got 179161638119093657369691 shares, No referral fee, from add_liquidity", - /* -- DIFF -- - "Mint 299997911757966485300035937427 shares for user3, fee is 895808191250701043141970 shares", - "Exchange swap got 179161638250140208628394 shares, No referral fee, from add_liquidity", - */ + // -- DIFF -- + // "Mint 299997911757966485300035937427 shares for eva, fee is 895808191250701043141970 shares", + // "Exchange swap got 179161638250140208628394 shares, No referral fee (not implemented)", + // assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, eva()), 299997911757966485300035937427, From 110128a386ea9d63c0764c7b4afe97e673d7f166 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 3 Jul 2024 11:50:34 +0200 Subject: [PATCH 04/28] rename tests --- amm/drink-tests/src/stable_swap_tests/mod.rs | 2 +- .../stable_swap_tests/{tests_sim.rs => tests_add_remove_lp.rs} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename amm/drink-tests/src/stable_swap_tests/{tests_sim.rs => tests_add_remove_lp.rs} (100%) diff --git a/amm/drink-tests/src/stable_swap_tests/mod.rs b/amm/drink-tests/src/stable_swap_tests/mod.rs index ee576a1..2842457 100644 --- a/amm/drink-tests/src/stable_swap_tests/mod.rs +++ b/amm/drink-tests/src/stable_swap_tests/mod.rs @@ -1,5 +1,5 @@ mod tests_rated; -mod tests_sim; +mod tests_add_remove_lp; mod tests_swap_exact_in; mod tests_swap_received; diff --git a/amm/drink-tests/src/stable_swap_tests/tests_sim.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs similarity index 100% rename from amm/drink-tests/src/stable_swap_tests/tests_sim.rs rename to amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs From 4559499877e78087335e29ea355acf962ab975af Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 3 Jul 2024 17:52:31 +0200 Subject: [PATCH 05/28] mock rate contract refactor --- Cargo.lock | 23 +- amm/Makefile | 2 +- .../Cargo.toml | 10 +- amm/contracts/mock_sazero_rate/lib.rs | 29 +++ amm/contracts/sazero_rate_mock/lib.rs | 45 ---- amm/drink-tests/src/lib.rs | 2 +- amm/drink-tests/src/stable_swap_tests/mod.rs | 18 +- .../stable_swap_tests/tests_add_remove_lp.rs | 100 ++++---- .../src/stable_swap_tests/tests_rated.rs | 233 ++++++++++++------ .../stable_swap_tests/tests_swap_exact_in.rs | 22 +- .../stable_swap_tests/tests_swap_received.rs | 20 +- amm/drink-tests/src/utils.rs | 172 ++++++------- amm/scripts/prepare_rust_wrappers.sh | 2 +- 13 files changed, 368 insertions(+), 310 deletions(-) rename amm/contracts/{sazero_rate_mock => mock_sazero_rate}/Cargo.toml (65%) create mode 100644 amm/contracts/mock_sazero_rate/lib.rs delete mode 100644 amm/contracts/sazero_rate_mock/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b4f9565..ab96658 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -605,6 +605,16 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "mock_sazero_rate_contract" +version = "0.1.0" +dependencies = [ + "ink", + "parity-scale-codec", + "scale-info", + "traits", +] + [[package]] name = "num-traits" version = "0.2.17" @@ -815,19 +825,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" -[[package]] -name = "sazero_rate_mock_contract" -version = "0.1.0" -dependencies = [ - "amm-helpers", - "ink", - "parity-scale-codec", - "primitive-types", - "scale-info", - "sp-arithmetic", - "traits", -] - [[package]] name = "scale-bits" version = "0.4.0" diff --git a/amm/Makefile b/amm/Makefile index 323d62b..090e657 100644 --- a/amm/Makefile +++ b/amm/Makefile @@ -7,7 +7,7 @@ help: # Show help for each of the Makefile recipes. AMM_CONTRACTS = ./contracts AMM_CONTRACTS_PATHS := $(shell find $(AMM_CONTRACTS) -mindepth 1 -maxdepth 1 -type d) -CONTRACTS := stable_pool_contract sazero_rate_mock_contract +CONTRACTS := stable_pool_contract mock_sazero_rate_contract INK_DEV_IMAGE := "public.ecr.aws/p6e8q1z1/ink-dev:2.1.0" SCRIPT_DIR := $(shell cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) diff --git a/amm/contracts/sazero_rate_mock/Cargo.toml b/amm/contracts/mock_sazero_rate/Cargo.toml similarity index 65% rename from amm/contracts/sazero_rate_mock/Cargo.toml rename to amm/contracts/mock_sazero_rate/Cargo.toml index fc92fce..c79cb16 100644 --- a/amm/contracts/sazero_rate_mock/Cargo.toml +++ b/amm/contracts/mock_sazero_rate/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sazero_rate_mock_contract" +name = "mock_sazero_rate_contract" version = "0.1.0" authors = ["Cardinal Cryptography"] edition = "2021" @@ -16,14 +16,9 @@ scale-info = { version = "2.9", default-features = false, features = [ traits = { path = "../../traits", default-features = false } -amm-helpers = { path = "../../../helpers", default-features = false } -primitive-types = { version = "0.12.1", default-features = false, features = [ - "codec", -] } -sp-arithmetic = { version = "18.0.0", default-features = false } [lib] -name = "sazero_rate_mock_contract" +name = "mock_sazero_rate_contract" path = "lib.rs" doctest = false @@ -34,6 +29,5 @@ std = [ "scale/std", "scale-info/std", "traits/std", - "amm-helpers/std", ] ink-as-dependency = [] diff --git a/amm/contracts/mock_sazero_rate/lib.rs b/amm/contracts/mock_sazero_rate/lib.rs new file mode 100644 index 0000000..c8ed0c2 --- /dev/null +++ b/amm/contracts/mock_sazero_rate/lib.rs @@ -0,0 +1,29 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +#[ink::contract] +mod mock_sazero_rate { + #[ink(storage)] + pub struct MockSazeroRateMockContract { + rate: u128, + } + + impl MockSazeroRateMockContract { + #[ink(constructor)] + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self { rate: 10u128.pow(12u32) } + } + + #[ink(message)] + pub fn set_rate(&mut self, rate: u128) { + self.rate = rate; + } + } + + impl traits::RateProvider for MockSazeroRateMockContract { + #[ink(message)] + fn get_rate(&mut self) -> u128 { + self.rate + } + } +} diff --git a/amm/contracts/sazero_rate_mock/lib.rs b/amm/contracts/sazero_rate_mock/lib.rs deleted file mode 100644 index 26c7801..0000000 --- a/amm/contracts/sazero_rate_mock/lib.rs +++ /dev/null @@ -1,45 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -#[ink::contract] -mod sazero_rate_mock { - use amm_helpers::constants::stable_pool::RATE_PRECISION; - #[ink(storage)] - pub struct SazeroMockContract { - initial_ts: u64, - } - - impl SazeroMockContract { - #[ink(constructor)] - #[allow(clippy::new_without_default)] - pub fn new() -> Self { - Self { - initial_ts: Self::env().block_timestamp(), - } - } - } - - impl traits::RateProvider for SazeroMockContract { - /// Calculate the value of sAZERO in terms of AZERO with TARGET_DECIMALS precision - #[ink(message)] - fn get_rate(&mut self) -> u128 { - // mock increasing rate (0.01% every 1 minute) - let now = self.env().block_timestamp(); - let time_d = (now - self.initial_ts) as u128; // ms elapsed - RATE_PRECISION + RATE_PRECISION * time_d / 600000000 - } - } - - #[cfg(test)] - mod test { - use super::*; - use ink::env::{test::set_block_timestamp, DefaultEnvironment}; - use traits::RateProvider; - #[test] - fn test_1() { - let minute: u64 = 60 * 1000; - let mut rate_contract = SazeroMockContract::new(); - set_block_timestamp::(minute * 10000); // after 10000 minutes should be doubled - assert_eq!(rate_contract.get_rate(), super::RATE_PRECISION * 2); - } - } -} diff --git a/amm/drink-tests/src/lib.rs b/amm/drink-tests/src/lib.rs index b7e9962..0681550 100644 --- a/amm/drink-tests/src/lib.rs +++ b/amm/drink-tests/src/lib.rs @@ -2,7 +2,7 @@ mod psp22; #[cfg(test)] #[allow(unused_imports)] -mod sazero_rate_mock_contract; +mod mock_sazero_rate_contract; #[cfg(test)] mod stable_pool_contract; #[cfg(test)] diff --git a/amm/drink-tests/src/stable_swap_tests/mod.rs b/amm/drink-tests/src/stable_swap_tests/mod.rs index 2842457..0cc1f95 100644 --- a/amm/drink-tests/src/stable_swap_tests/mod.rs +++ b/amm/drink-tests/src/stable_swap_tests/mod.rs @@ -1,5 +1,5 @@ -mod tests_rated; mod tests_add_remove_lp; +mod tests_rated; mod tests_swap_exact_in; mod tests_swap_received; @@ -20,6 +20,8 @@ pub const FEE_BPS_DENOM: u128 = 10_000; pub const FEE_RECEIVER: AccountId32 = AccountId32::new([42u8; 32]); +const RATE_PRECISION: u128 = 10u128.pow(12); + pub fn fee_receiver() -> ink_primitives::AccountId { AsRef::<[u8; 32]>::as_ref(&FEE_RECEIVER).clone().into() } @@ -88,14 +90,24 @@ pub fn setup_stable_swap_with_tokens( pub fn share_price_and_total_shares( session: &mut Session, stable_swap: AccountId, + token_rates: Option>, ) -> (u128, u128) { let total_shares = psp22_utils::total_supply(session, stable_swap); let reserves = stable_swap::reserves(session, stable_swap); + let token_rates: Vec = if let Some(rates) = token_rates { + rates + } else { + reserves.iter().map(|_| RATE_PRECISION).collect() + }; let sum_token = stable_swap::tokens(session, stable_swap) .iter() .zip(reserves.iter()) - .fold(0, |acc, (&token, reserve)| { - acc + reserve * 10u128.pow((18 - psp22_utils::token_decimals(session, token)).into()) + .zip(token_rates.iter()) + .fold(0, |acc, ((&token, reserve), rate)| { + acc + reserve + * 10u128.pow((18 - psp22_utils::token_decimals(session, token)).into()) + * rate + / RATE_PRECISION }); ( diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index 30b73b5..72e28c7 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -21,15 +21,15 @@ fn test_01(mut session: Session) { BOB, ); - handle_ink_error(stable_swap::add_liquidity( + _ = stable_swap::add_liquidity( &mut session, stable_swap, BOB, 1, initial_reserves.clone(), bob(), - )) - .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + ) + .expect("Should successfully add liquidity"); assert_eq!( stable_swap::tokens(&mut session, stable_swap), @@ -75,7 +75,7 @@ fn test_01(mut session: Session) { "Incorrect Users tokens balances" ); - _ = handle_ink_error(stable_swap::swap_exact_in( + _ = stable_swap::swap_exact_in( &mut session, stable_swap, BOB, @@ -84,10 +84,10 @@ fn test_01(mut session: Session) { ONE_DAI, // amount_in 1, // min_token_out charlie(), - )) - .unwrap_or_else(|err| panic!("Should successfully swap. Err: {err:?}")); + ) + .expect("Should successfully swap"); - _ = handle_ink_error(stable_swap::swap_exact_in( + _ = stable_swap::swap_exact_in( &mut session, stable_swap, BOB, @@ -96,8 +96,8 @@ fn test_01(mut session: Session) { ONE_DAI, // amount_in 1, // min_token_out charlie(), - )) - .unwrap_or_else(|err| panic!("Should successfully swap. Err: {err:?}")); + ) + .expect("Should successfully swap. "); let balances: Vec = tokens .iter() @@ -155,18 +155,18 @@ fn test_02(mut session: Session) { BOB, ); - handle_ink_error(stable_swap::add_liquidity( + _ = stable_swap::add_liquidity( &mut session, stable_swap, BOB, 1, initial_reserves.clone(), bob(), - )) - .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + ) + .expect("Should successfully add liquidity"); let (last_share_price, last_total_shares) = - share_price_and_total_shares(&mut session, stable_swap); + share_price_and_total_shares(&mut session, stable_swap, None); transfer_and_increase_allowance( &mut session, @@ -178,33 +178,33 @@ fn test_02(mut session: Session) { ); // add more liquidity with balanced tokens (charlie) - handle_ink_error(stable_swap::add_liquidity( + _ = stable_swap::add_liquidity( &mut session, stable_swap, CHARLIE, 1, vec![500 * ONE_DAI, 500 * ONE_USDT, 500 * ONE_USDC], charlie(), - )) - .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + ) + .expect("Should successfully add liquidity"); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap), + share_price_and_total_shares(&mut session, stable_swap, None), (last_share_price, last_total_shares + 1500 * ONE_LPT) ); let last_total_shares = last_total_shares + 1500 * ONE_LPT; // remove by shares (charlie) - handle_ink_error(stable_swap::remove_liquidity_by_shares( + _ = stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, CHARLIE, 300 * ONE_LPT, vec![1 * ONE_DAI, 1 * ONE_USDT, 1 * ONE_USDC], charlie(), - )) - .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + ) + .expect("Should successfully remove liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), @@ -220,7 +220,7 @@ fn test_02(mut session: Session) { "Incorrect Users tokens balances" ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap), + share_price_and_total_shares(&mut session, stable_swap, None), (last_share_price, last_total_shares - 300 * ONE_LPT) ); let last_total_shares = last_total_shares - 300 * ONE_LPT; @@ -235,15 +235,15 @@ fn test_02(mut session: Session) { ); // add more liquidity with imbalanced tokens (dave) - handle_ink_error(stable_swap::add_liquidity( + _ = stable_swap::add_liquidity( &mut session, stable_swap, DAVE, 1, vec![100 * ONE_DAI, 200 * ONE_USDT, 400 * ONE_USDC], dave(), - )) - .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + ) + .expect("Should successfully add liquidity"); // "Mint 699699997426210330025 shares for user2, fee is 299999998348895348 shares", // "Exchange swap got 59999999669779069 shares", @@ -264,7 +264,7 @@ fn test_02(mut session: Session) { ); let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap); + share_price_and_total_shares(&mut session, stable_swap, None); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -278,15 +278,15 @@ fn test_02(mut session: Session) { let last_total_shares = current_total_shares; // remove by tokens (charlie) - handle_ink_error(stable_swap::remove_liquidity_by_amounts( + _ = stable_swap::remove_liquidity_by_amounts( &mut session, stable_swap, CHARLIE, 550 * ONE_LPT, vec![1 * ONE_DAI, 500 * ONE_USDT, 1 * ONE_USDC], charlie(), - )) - .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + ) + .expect("Should successfully remove liquidity. Err: {err:?}"); // "LP charlie removed 502598511257512352631 shares by given tokens, and fee is 598899301432400519 shares", // "Exchange swap got 119779860286480103 shares", assert_eq!( @@ -325,7 +325,7 @@ fn test_02(mut session: Session) { 699699997426210330025, "Incorrect users share" ); - let (current_share_price, _) = share_price_and_total_shares(&mut session, stable_swap); + let (current_share_price, _) = share_price_and_total_shares(&mut session, stable_swap, None); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -348,51 +348,53 @@ fn test_02(mut session: Session) { ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap), + share_price_and_total_shares(&mut session, stable_swap, None), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); // dave remove by shares trigger slippage - let res = handle_ink_error(stable_swap::remove_liquidity_by_shares( + let res = stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, DAVE, 300 * ONE_LPT, vec![1 * ONE_DAI, 298 * ONE_USDT, 1 * ONE_USDC], dave(), - )); + ) + .expect_err("Should return an error"); assert_eq!( res, - Err(StablePoolError::InsufficientOutputAmount()), + StablePoolError::InsufficientOutputAmount(), "Should return correct error" ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap), + share_price_and_total_shares(&mut session, stable_swap, None), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); // dave remove by tokens trigger slippage - let res = handle_ink_error(stable_swap::remove_liquidity_by_amounts( + let res = stable_swap::remove_liquidity_by_amounts( &mut session, stable_swap, DAVE, 300 * ONE_LPT, vec![1 * ONE_DAI, 298 * ONE_USDT, 1 * ONE_USDC], dave(), - )); + ) + .expect_err("Shoulf return an error"); assert_eq!( res, - Err(StablePoolError::InsufficientLiquidityBurned()), + StablePoolError::InsufficientLiquidityBurned(), "Should return correct error" ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap), + share_price_and_total_shares(&mut session, stable_swap, None), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); @@ -409,15 +411,15 @@ fn test_02(mut session: Session) { ); // dave remove by share - handle_ink_error(stable_swap::remove_liquidity_by_shares( + _ = stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, DAVE, 300 * ONE_LPT, vec![1 * ONE_DAI, 1 * ONE_USDT, 1 * ONE_USDC], dave(), - )) - .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + ) + .expect("Should successfully remove liquidity"); // "LP dave removed 498596320225563082252 shares by given tokens, and fee is 597500435701476809 shares", // "Exchange swap got 119500087140295361 shares", @@ -433,7 +435,7 @@ fn test_02(mut session: Session) { ); let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap); + share_price_and_total_shares(&mut session, stable_swap, None); assert_eq!( current_share_price, last_share_price, "Incorrect share price" @@ -445,15 +447,15 @@ fn test_02(mut session: Session) { ); let last_total_shares = last_total_shares - 300 * ONE_LPT; - handle_ink_error(stable_swap::remove_liquidity_by_amounts( + _ = stable_swap::remove_liquidity_by_amounts( &mut session, stable_swap, DAVE, 499 * ONE_LPT, vec![498 * ONE_DAI, 0 * ONE_USDT, 0 * ONE_USDC], dave(), - )) - .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + ) + .expect("Should successfully remove liquidity"); // "LP user2 removed 498596320225563082252 shares by given tokens, and fee is 597500435701476809 shares", // "Exchange swap got 119500087140295361 shares, No referral fee, from remove_liquidity_by_tokens", // -- DIFF -- @@ -473,7 +475,7 @@ fn test_02(mut session: Session) { let last_total_shares = last_total_shares - 498596320224035614380 + 119500087140112295; let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap); + share_price_and_total_shares(&mut session, stable_swap, None); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -496,7 +498,7 @@ fn test_02(mut session: Session) { BOB, ); - handle_ink_error(stable_swap::add_liquidity( + stable_swap::add_liquidity( &mut session, stable_swap, EVA, @@ -507,8 +509,8 @@ fn test_02(mut session: Session) { 100_000_000_000 * ONE_USDC, ], eva(), - )) - .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + ) + .expect("Should successfully add liquidity"); // "Mint 299997911758886758506069372942 shares for user3, fee is 895808190595468286848457 shares", // "Exchange swap got 179161638119093657369691 shares, No referral fee, from add_liquidity", // -- DIFF -- diff --git a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs index ba0015b..331c95d 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs @@ -1,4 +1,4 @@ -use crate::sazero_rate_mock_contract; +use crate::mock_sazero_rate_contract; use crate::stable_pool_contract; use crate::utils::*; @@ -8,40 +8,49 @@ use drink::{self, runtime::MinimalRuntime, session::Session}; use ink_primitives::AccountId; use ink_wrapper_types::{Connection, ToAccountId}; -const SAZERO_DEC: u8 = 12; const WAZERO_DEC: u8 = 12; +const SAZERO_DEC: u8 = 12; +const ONE_LPT: u128 = 10u128.pow(18); +const ONE_WAZERO: u128 = 10u128.pow(WAZERO_DEC as u32); const ONE_SAZERO: u128 = 10u128.pow(SAZERO_DEC as u32); -const ONE_AZERO: u128 = 10u128.pow(WAZERO_DEC as u32); - -const INIT_SUPPLY: u128 = 1_000_000; // 1M -const TRADE_FEE_BPS: u16 = 6; -const PROTOCOL_FEE_BPS: u16 = 2000; - -const AMP_COEF: u128 = 1000; +const EXPIRE_TS: u64 = 24 * 3600 * 1000; // 24h fn setup_rated_swap_with_tokens( session: &mut Session, - sazero: AccountId, - wazero: AccountId, + caller: drink::AccountId32, + initial_token_supply: u128, init_amp_coef: u128, rate_expiration_duration_ms: u64, - caller: drink::AccountId32, trade_fee: u16, protocol_fee: u16, - fee_receiver: Option, -) -> stable_pool_contract::Instance { +) -> (AccountId, AccountId, AccountId, AccountId) { //upload and deploy rate mock session .upload_code(stable_pool_contract::upload()) .expect("Upload stable_stable_pair_contract code"); session - .upload_code(sazero_rate_mock_contract::upload()) + .upload_code(mock_sazero_rate_contract::upload()) .expect("Upload sazero_rate_mock_contract code"); let _ = session.set_actor(caller.clone()); - let instance = sazero_rate_mock_contract::Instance::new(); + let instance = mock_sazero_rate_contract::Instance::new(); + + let wazero = psp22_utils::setup_with_amounts( + session, + "wAZERO".to_string(), + WAZERO_DEC, + initial_token_supply * ONE_WAZERO, + caller.clone(), + ); + let sazero = psp22_utils::setup_with_amounts( + session, + "SAZERO".to_string(), + SAZERO_DEC, + initial_token_supply * ONE_SAZERO, + caller.clone(), + ); let rate_mock_address = session .instantiate(instance) @@ -50,7 +59,7 @@ fn setup_rated_swap_with_tokens( .to_account_id() .into(); let instance = stable_pool_contract::Instance::new_rated( - vec![sazero, wazero], + vec![sazero.into(), wazero.into()], vec![SAZERO_DEC, WAZERO_DEC], vec![Some(rate_mock_address), None], rate_expiration_duration_ms, @@ -58,104 +67,166 @@ fn setup_rated_swap_with_tokens( caller.to_account_id(), trade_fee, protocol_fee, - fee_receiver, + Some(fee_receiver()), ); - session + let rated_swap = session .instantiate(instance) .unwrap() .result .to_account_id() - .into() -} - -fn setup_all( - session: &mut Session, - _enable_protocol_fee: bool, -) -> (AccountId, AccountId, AccountId) { - upload_all(session); - - let wazero = psp22_utils::setup_with_amounts( - session, - "wAZERO".to_string(), - WAZERO_DEC, - INIT_SUPPLY * ONE_AZERO, - BOB, - ); - let sazero = psp22_utils::setup_with_amounts( - session, - "SAZERO".to_string(), - SAZERO_DEC, - INIT_SUPPLY * ONE_SAZERO, - BOB, - ); - let stable_pool_contract = setup_rated_swap_with_tokens( - session, - sazero.into(), - wazero.into(), - AMP_COEF, - 10000, //10 seconds rate cache expiration - BOB, - TRADE_FEE_BPS, - PROTOCOL_FEE_BPS, - Some(bob()), - ); + .into(); for token in [sazero, wazero] { psp22_utils::increase_allowance( session, token.into(), - stable_pool_contract.into(), + rated_swap, u128::MAX, - BOB, + caller.clone(), ) .unwrap(); } - (stable_pool_contract.into(), sazero.into(), wazero.into()) + (rated_swap, sazero.into(), wazero.into(), rate_mock_address) } +fn set_sazero_rate( + session: &mut Session, + mock_sazero_rate_contract: AccountId, + rate: u128, +) { + _ = handle_ink_error( + session + .execute( + mock_sazero_rate_contract::Instance::from(mock_sazero_rate_contract).set_rate(rate), + ) + .unwrap(), + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/tests/test_rated_pool.rs#L27 #[drink::test] fn test_01(mut session: Session) { - let one_minute: u64 = 60000; + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + let now = get_timestamp(&mut session); set_timestamp(&mut session, now); - upload_all(&mut session); - let (rated_swap, sazero, wazero) = setup_all(&mut session, false); + let initial_token_supply: u128 = 1_000_000_000; + let (rated_swap, sazero, wazero, mock_sazero_rate) = setup_rated_swap_with_tokens( + &mut session, + BOB, + initial_token_supply, + 10000, + EXPIRE_TS, + 25, + 2000, + ); + + set_timestamp(&mut session, now * EXPIRE_TS); + set_sazero_rate(&mut session, mock_sazero_rate, 2 * RATE_PRECISION); + _ = stable_swap::add_liquidity( &mut session, rated_swap.into(), BOB, 1, - vec![INIT_SUPPLY * ONE_SAZERO / 10, INIT_SUPPLY * ONE_AZERO / 10], + vec![50000 * ONE_SAZERO, 100000 * ONE_WAZERO], bob(), + ) + .expect("Should successfully swap. Err: {err:?}"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, bob()), + 200000 * ONE_LPT, + "Incorrect user share" ); - let amount = 10_000 * ONE_SAZERO; // 10k + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 200000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); - psp22_utils::increase_allowance( + transfer_and_increase_allowance( &mut session, - sazero.into(), - rated_swap.into(), - u128::MAX, + rated_swap, + vec![sazero, wazero], + CHARLIE, + vec![100000 * ONE_SAZERO, 100000 * ONE_WAZERO], BOB, + ); + _ = stable_swap::add_liquidity( + &mut session, + rated_swap.into(), + CHARLIE, + 1, + vec![50000 * ONE_SAZERO, 100000 * ONE_WAZERO], + charlie(), ) - .unwrap(); + .expect("Should successfully swap"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, charlie()), + 200000 * ONE_LPT, + "Incorrect user share" + ); + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 400000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); - set_timestamp(&mut session, now + 10000 * one_minute); - let (_amount_out, _fee) = handle_ink_error(stable_swap::swap_exact_in( + _ = stable_swap::remove_liquidity_by_shares( &mut session, rated_swap.into(), - BOB, - sazero.into(), - wazero.into(), - amount, - 1, // min_token_out - bob(), - )) - .unwrap_or_else(|err| panic!("Should return valid result. Err: {err:?}")); - - let reserves = stable_swap::reserves(&mut session, rated_swap.into()); - let balance_0 = psp22_utils::balance_of(&mut session, sazero.into(), rated_swap.into()); - let balance_1 = psp22_utils::balance_of(&mut session, wazero.into(), rated_swap.into()); - assert_eq!(reserves, vec![balance_0, balance_1]); + CHARLIE, + 200000 * ONE_LPT, + vec![1 * ONE_SAZERO, 1 * ONE_WAZERO], + charlie(), + ) + .expect("Should successfully swap"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, charlie()), + 0, + "Incorrect user share" + ); + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 200000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); + + // let err = stable_swap::remove_liquidity_by_shares( + // &mut session, + // rated_swap.into(), + // BOB, + // 200000 * ONE_LPT, + // vec![1 * ONE_SAZERO, 1 * ONE_WAZERO], + // bob(), + // ) + // .expect_err("Should return an error"); + + // assert_eq!( + // err, + // StablePoolError::MinReserve(), + // "Should return correct error" + // ) } diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs index 51c69f1..6516126 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs @@ -32,16 +32,16 @@ fn setup_test_swap_exact_in( bob(), ); - let swap_result = handle_ink_error(stable_swap::swap_exact_in( + let swap_result = stable_swap::swap_exact_in( session, stable_swap, BOB, - tokens[0], // in - tokens[1], // out + tokens[0], // in + tokens[1], // out swap_amount_in, // amount_in 0, // min_token_out bob(), - )); + ); if expected_swap_amount_out_total_result.is_err() { match swap_result { @@ -93,9 +93,7 @@ fn setup_test_swap_exact_in( [0, expected_protocol_fee_part].to_vec(), bob(), ) - .result - .unwrap() - .unwrap(); + .expect("Should remove lp"); assert_eq!( total_lp_required - lp_fee_part, protocol_fee_lp, @@ -110,11 +108,11 @@ fn test_01(mut session: Session) { &mut session, vec![6, 6], // decimals vec![100000000000, 100000000000], // initial reserves - 1000, // A - 6, // fee BPS - 2000, // protocol fee BPS - 10000000000, // swap_amount_in - Ok(9999495232), // expected out (with fee) + 1000, // A + 6, // fee BPS + 2000, // protocol fee BPS + 10000000000, // swap_amount_in + Ok(9999495232), // expected out (with fee) ); } diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs index 226dd1e..7350a26 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs @@ -34,15 +34,15 @@ fn setup_test_swap_received( let _ = psp22_utils::transfer(session, tokens[0], stable_swap, swap_amount_in, BOB); - let swap_result = handle_ink_error(stable_swap::swap_received( + let swap_result = stable_swap::swap_received( session, stable_swap, BOB, tokens[0], // in tokens[1], // out - 0, // min_token_out + 0, // min_token_out bob(), - )); + ); if expected_swap_amount_out_total_result.is_err() { match swap_result { @@ -94,9 +94,7 @@ fn setup_test_swap_received( [0, expected_protocol_fee_part].to_vec(), bob(), ) - .result - .unwrap() - .unwrap(); + .expect("Should remove lp"); assert_eq!( total_lp_required - lp_fee_part, protocol_fee_lp, @@ -111,11 +109,11 @@ fn test_01(mut session: Session) { &mut session, vec![6, 6], // decimals vec![100000000000, 100000000000], // initial reserves - 1000, // A - 6, // fee BPS - 2000, // protocol fee BPS - 10000000000, // swap_amount_in - Ok(9999495232), // expected out (with fee) + 1000, // A + 6, // fee BPS + 2000, // protocol fee BPS + 10000000000, // swap_amount_in + Ok(9999495232), // expected out (with fee) ); } diff --git a/amm/drink-tests/src/utils.rs b/amm/drink-tests/src/utils.rs index 2b1fc50..166ed95 100644 --- a/amm/drink-tests/src/utils.rs +++ b/amm/drink-tests/src/utils.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use crate::*; use anyhow::Result; @@ -81,9 +82,9 @@ pub mod stable_swap { min_share_amount: u128, amounts: Vec, to: AccountId, - ) -> ContractResult, InkLangError>> { - let _ = session.set_actor(caller); - session + ) -> Result<(u128, u128), StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error(session .execute( stable_pool_contract::Instance::from(stable_pool).add_liquidity( min_share_amount, @@ -91,7 +92,7 @@ pub mod stable_swap { to, ), ) - .unwrap() + .unwrap()) } pub fn remove_liquidity_by_amounts( @@ -101,9 +102,9 @@ pub mod stable_swap { max_share_amount: u128, amounts: Vec, to: AccountId, - ) -> ContractResult, InkLangError>> { - let _ = session.set_actor(caller); - session + ) -> Result<(u128, u128), StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error(session .execute( stable_pool_contract::Instance::from(stable_pool).remove_liquidity_by_amounts( max_share_amount, @@ -111,7 +112,7 @@ pub mod stable_swap { to, ), ) - .unwrap() + .unwrap()) } pub fn remove_liquidity_by_shares( @@ -121,17 +122,19 @@ pub mod stable_swap { shares_amount: u128, min_amounts: Vec, to: AccountId, - ) -> ContractResult, StablePoolError>, InkLangError>> { - let _ = session.set_actor(caller); - session - .execute( - stable_pool_contract::Instance::from(stable_pool).remove_liquidity_by_shares( - shares_amount, - min_amounts, - to, - ), - ) - .unwrap() + ) -> Result, StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error( + session + .execute( + stable_pool_contract::Instance::from(stable_pool).remove_liquidity_by_shares( + shares_amount, + min_amounts, + to, + ), + ) + .unwrap(), + ) } pub fn swap_exact_in( @@ -143,21 +146,21 @@ pub mod stable_swap { token_in_amount: u128, min_token_out_amount: u128, to: AccountId, - ) -> ContractResult< - Result, ink_wrapper_types::InkLangError>, - > { - let _ = session.set_actor(caller); - session - .execute( - stable_pool_contract::Instance::from(stable_pool).swap_exact_in( - token_in, - token_out, - token_in_amount, - min_token_out_amount, - to, - ), - ) - .unwrap() + ) -> Result<(u128, u128), StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error( + session + .execute( + stable_pool_contract::Instance::from(stable_pool).swap_exact_in( + token_in, + token_out, + token_in_amount, + min_token_out_amount, + to, + ), + ) + .unwrap(), + ) } pub fn swap_exact_out( @@ -169,21 +172,21 @@ pub mod stable_swap { token_out_amount: u128, max_token_in_amount: u128, to: AccountId, - ) -> ContractResult< - Result, ink_wrapper_types::InkLangError>, - > { - let _ = session.set_actor(caller); - session - .execute( - stable_pool_contract::Instance::from(stable_pool).swap_exact_out( - token_in, - token_out, - token_out_amount, - max_token_in_amount, - to, - ), - ) - .unwrap() + ) -> Result<(u128, u128), StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error( + session + .execute( + stable_pool_contract::Instance::from(stable_pool).swap_exact_out( + token_in, + token_out, + token_out_amount, + max_token_in_amount, + to, + ), + ) + .unwrap(), + ) } pub fn swap_received( @@ -194,59 +197,58 @@ pub mod stable_swap { token_out: AccountId, min_token_out_amount: u128, to: AccountId, - ) -> ContractResult< - Result, ink_wrapper_types::InkLangError>, - > { - let _ = session.set_actor(caller); - session - .execute( - stable_pool_contract::Instance::from(stable_pool).swap_received( - token_in, - token_out, - min_token_out_amount, - to, - ), - ) - .unwrap() + ) -> Result<(u128, u128), StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error( + session + .execute( + stable_pool_contract::Instance::from(stable_pool).swap_received( + token_in, + token_out, + min_token_out_amount, + to, + ), + ) + .unwrap(), + ) } pub fn reserves(session: &mut Session, stable_pool: AccountId) -> Vec { - session - .query(stable_pool_contract::Instance::from(stable_pool).reserves()) - .unwrap() - .result - .unwrap() + handle_ink_error( + session + .query(stable_pool_contract::Instance::from(stable_pool).reserves()) + .unwrap(), + ) } pub fn amp_coef(session: &mut Session, stable_pool: AccountId) -> u128 { - session - .query(stable_pool_contract::Instance::from(stable_pool).amp_coef()) - .unwrap() - .result - .unwrap() + handle_ink_error( + session + .query(stable_pool_contract::Instance::from(stable_pool).amp_coef()) + .unwrap(), + ) } pub fn fees(session: &mut Session, stable_pool: AccountId) -> (u16, u16) { - session - .query(stable_pool_contract::Instance::from(stable_pool).fees()) - .unwrap() - .result - .unwrap() + handle_ink_error( + session + .query(stable_pool_contract::Instance::from(stable_pool).fees()) + .unwrap(), + ) } pub fn tokens(session: &mut Session, stable_pool: AccountId) -> Vec { - session - .query(stable_pool_contract::Instance::from(stable_pool).tokens()) - .unwrap() - .result - .unwrap() + handle_ink_error( + session + .query(stable_pool_contract::Instance::from(stable_pool).tokens()) + .unwrap(), + ) } } pub mod psp22_utils { use super::*; - use psp22::{Instance as PSP22, PSP22 as _, PSP22Metadata as _}; - + use psp22::{Instance as PSP22, PSP22Metadata as _, PSP22 as _}; /// Uploads and creates a PSP22 instance with 1B*10^18 issuance and given names. /// Returns its AccountId casted to PSP22 interface. diff --git a/amm/scripts/prepare_rust_wrappers.sh b/amm/scripts/prepare_rust_wrappers.sh index 88e8443..037df52 100755 --- a/amm/scripts/prepare_rust_wrappers.sh +++ b/amm/scripts/prepare_rust_wrappers.sh @@ -9,7 +9,7 @@ readonly SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null declare -a CONTRACTS=( "stable_pool_contract" "psp22" - "sazero_rate_mock_contract" + "mock_sazero_rate_contract" ) function wrap_contracts() { From ee0bfb2173ba3e68c227b987005565717be39924 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 3 Jul 2024 18:18:52 +0200 Subject: [PATCH 06/28] Revert "mock rate contract refactor" This reverts commit 4559499877e78087335e29ea355acf962ab975af. --- Cargo.lock | 23 +- amm/Makefile | 2 +- amm/contracts/mock_sazero_rate/lib.rs | 29 --- .../Cargo.toml | 10 +- amm/contracts/sazero_rate_mock/lib.rs | 45 ++++ amm/drink-tests/src/lib.rs | 2 +- amm/drink-tests/src/stable_swap_tests/mod.rs | 18 +- .../stable_swap_tests/tests_add_remove_lp.rs | 100 ++++---- .../src/stable_swap_tests/tests_rated.rs | 233 ++++++------------ .../stable_swap_tests/tests_swap_exact_in.rs | 22 +- .../stable_swap_tests/tests_swap_received.rs | 20 +- amm/drink-tests/src/utils.rs | 172 +++++++------ amm/scripts/prepare_rust_wrappers.sh | 2 +- 13 files changed, 310 insertions(+), 368 deletions(-) delete mode 100644 amm/contracts/mock_sazero_rate/lib.rs rename amm/contracts/{mock_sazero_rate => sazero_rate_mock}/Cargo.toml (65%) create mode 100644 amm/contracts/sazero_rate_mock/lib.rs diff --git a/Cargo.lock b/Cargo.lock index ab96658..b4f9565 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -605,16 +605,6 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" -[[package]] -name = "mock_sazero_rate_contract" -version = "0.1.0" -dependencies = [ - "ink", - "parity-scale-codec", - "scale-info", - "traits", -] - [[package]] name = "num-traits" version = "0.2.17" @@ -825,6 +815,19 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "sazero_rate_mock_contract" +version = "0.1.0" +dependencies = [ + "amm-helpers", + "ink", + "parity-scale-codec", + "primitive-types", + "scale-info", + "sp-arithmetic", + "traits", +] + [[package]] name = "scale-bits" version = "0.4.0" diff --git a/amm/Makefile b/amm/Makefile index 090e657..323d62b 100644 --- a/amm/Makefile +++ b/amm/Makefile @@ -7,7 +7,7 @@ help: # Show help for each of the Makefile recipes. AMM_CONTRACTS = ./contracts AMM_CONTRACTS_PATHS := $(shell find $(AMM_CONTRACTS) -mindepth 1 -maxdepth 1 -type d) -CONTRACTS := stable_pool_contract mock_sazero_rate_contract +CONTRACTS := stable_pool_contract sazero_rate_mock_contract INK_DEV_IMAGE := "public.ecr.aws/p6e8q1z1/ink-dev:2.1.0" SCRIPT_DIR := $(shell cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) diff --git a/amm/contracts/mock_sazero_rate/lib.rs b/amm/contracts/mock_sazero_rate/lib.rs deleted file mode 100644 index c8ed0c2..0000000 --- a/amm/contracts/mock_sazero_rate/lib.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std, no_main)] - -#[ink::contract] -mod mock_sazero_rate { - #[ink(storage)] - pub struct MockSazeroRateMockContract { - rate: u128, - } - - impl MockSazeroRateMockContract { - #[ink(constructor)] - #[allow(clippy::new_without_default)] - pub fn new() -> Self { - Self { rate: 10u128.pow(12u32) } - } - - #[ink(message)] - pub fn set_rate(&mut self, rate: u128) { - self.rate = rate; - } - } - - impl traits::RateProvider for MockSazeroRateMockContract { - #[ink(message)] - fn get_rate(&mut self) -> u128 { - self.rate - } - } -} diff --git a/amm/contracts/mock_sazero_rate/Cargo.toml b/amm/contracts/sazero_rate_mock/Cargo.toml similarity index 65% rename from amm/contracts/mock_sazero_rate/Cargo.toml rename to amm/contracts/sazero_rate_mock/Cargo.toml index c79cb16..fc92fce 100644 --- a/amm/contracts/mock_sazero_rate/Cargo.toml +++ b/amm/contracts/sazero_rate_mock/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "mock_sazero_rate_contract" +name = "sazero_rate_mock_contract" version = "0.1.0" authors = ["Cardinal Cryptography"] edition = "2021" @@ -16,9 +16,14 @@ scale-info = { version = "2.9", default-features = false, features = [ traits = { path = "../../traits", default-features = false } +amm-helpers = { path = "../../../helpers", default-features = false } +primitive-types = { version = "0.12.1", default-features = false, features = [ + "codec", +] } +sp-arithmetic = { version = "18.0.0", default-features = false } [lib] -name = "mock_sazero_rate_contract" +name = "sazero_rate_mock_contract" path = "lib.rs" doctest = false @@ -29,5 +34,6 @@ std = [ "scale/std", "scale-info/std", "traits/std", + "amm-helpers/std", ] ink-as-dependency = [] diff --git a/amm/contracts/sazero_rate_mock/lib.rs b/amm/contracts/sazero_rate_mock/lib.rs new file mode 100644 index 0000000..26c7801 --- /dev/null +++ b/amm/contracts/sazero_rate_mock/lib.rs @@ -0,0 +1,45 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +#[ink::contract] +mod sazero_rate_mock { + use amm_helpers::constants::stable_pool::RATE_PRECISION; + #[ink(storage)] + pub struct SazeroMockContract { + initial_ts: u64, + } + + impl SazeroMockContract { + #[ink(constructor)] + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self { + initial_ts: Self::env().block_timestamp(), + } + } + } + + impl traits::RateProvider for SazeroMockContract { + /// Calculate the value of sAZERO in terms of AZERO with TARGET_DECIMALS precision + #[ink(message)] + fn get_rate(&mut self) -> u128 { + // mock increasing rate (0.01% every 1 minute) + let now = self.env().block_timestamp(); + let time_d = (now - self.initial_ts) as u128; // ms elapsed + RATE_PRECISION + RATE_PRECISION * time_d / 600000000 + } + } + + #[cfg(test)] + mod test { + use super::*; + use ink::env::{test::set_block_timestamp, DefaultEnvironment}; + use traits::RateProvider; + #[test] + fn test_1() { + let minute: u64 = 60 * 1000; + let mut rate_contract = SazeroMockContract::new(); + set_block_timestamp::(minute * 10000); // after 10000 minutes should be doubled + assert_eq!(rate_contract.get_rate(), super::RATE_PRECISION * 2); + } + } +} diff --git a/amm/drink-tests/src/lib.rs b/amm/drink-tests/src/lib.rs index 0681550..b7e9962 100644 --- a/amm/drink-tests/src/lib.rs +++ b/amm/drink-tests/src/lib.rs @@ -2,7 +2,7 @@ mod psp22; #[cfg(test)] #[allow(unused_imports)] -mod mock_sazero_rate_contract; +mod sazero_rate_mock_contract; #[cfg(test)] mod stable_pool_contract; #[cfg(test)] diff --git a/amm/drink-tests/src/stable_swap_tests/mod.rs b/amm/drink-tests/src/stable_swap_tests/mod.rs index 0cc1f95..2842457 100644 --- a/amm/drink-tests/src/stable_swap_tests/mod.rs +++ b/amm/drink-tests/src/stable_swap_tests/mod.rs @@ -1,5 +1,5 @@ -mod tests_add_remove_lp; mod tests_rated; +mod tests_add_remove_lp; mod tests_swap_exact_in; mod tests_swap_received; @@ -20,8 +20,6 @@ pub const FEE_BPS_DENOM: u128 = 10_000; pub const FEE_RECEIVER: AccountId32 = AccountId32::new([42u8; 32]); -const RATE_PRECISION: u128 = 10u128.pow(12); - pub fn fee_receiver() -> ink_primitives::AccountId { AsRef::<[u8; 32]>::as_ref(&FEE_RECEIVER).clone().into() } @@ -90,24 +88,14 @@ pub fn setup_stable_swap_with_tokens( pub fn share_price_and_total_shares( session: &mut Session, stable_swap: AccountId, - token_rates: Option>, ) -> (u128, u128) { let total_shares = psp22_utils::total_supply(session, stable_swap); let reserves = stable_swap::reserves(session, stable_swap); - let token_rates: Vec = if let Some(rates) = token_rates { - rates - } else { - reserves.iter().map(|_| RATE_PRECISION).collect() - }; let sum_token = stable_swap::tokens(session, stable_swap) .iter() .zip(reserves.iter()) - .zip(token_rates.iter()) - .fold(0, |acc, ((&token, reserve), rate)| { - acc + reserve - * 10u128.pow((18 - psp22_utils::token_decimals(session, token)).into()) - * rate - / RATE_PRECISION + .fold(0, |acc, (&token, reserve)| { + acc + reserve * 10u128.pow((18 - psp22_utils::token_decimals(session, token)).into()) }); ( diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index 72e28c7..30b73b5 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -21,15 +21,15 @@ fn test_01(mut session: Session) { BOB, ); - _ = stable_swap::add_liquidity( + handle_ink_error(stable_swap::add_liquidity( &mut session, stable_swap, BOB, 1, initial_reserves.clone(), bob(), - ) - .expect("Should successfully add liquidity"); + )) + .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); assert_eq!( stable_swap::tokens(&mut session, stable_swap), @@ -75,7 +75,7 @@ fn test_01(mut session: Session) { "Incorrect Users tokens balances" ); - _ = stable_swap::swap_exact_in( + _ = handle_ink_error(stable_swap::swap_exact_in( &mut session, stable_swap, BOB, @@ -84,10 +84,10 @@ fn test_01(mut session: Session) { ONE_DAI, // amount_in 1, // min_token_out charlie(), - ) - .expect("Should successfully swap"); + )) + .unwrap_or_else(|err| panic!("Should successfully swap. Err: {err:?}")); - _ = stable_swap::swap_exact_in( + _ = handle_ink_error(stable_swap::swap_exact_in( &mut session, stable_swap, BOB, @@ -96,8 +96,8 @@ fn test_01(mut session: Session) { ONE_DAI, // amount_in 1, // min_token_out charlie(), - ) - .expect("Should successfully swap. "); + )) + .unwrap_or_else(|err| panic!("Should successfully swap. Err: {err:?}")); let balances: Vec = tokens .iter() @@ -155,18 +155,18 @@ fn test_02(mut session: Session) { BOB, ); - _ = stable_swap::add_liquidity( + handle_ink_error(stable_swap::add_liquidity( &mut session, stable_swap, BOB, 1, initial_reserves.clone(), bob(), - ) - .expect("Should successfully add liquidity"); + )) + .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); let (last_share_price, last_total_shares) = - share_price_and_total_shares(&mut session, stable_swap, None); + share_price_and_total_shares(&mut session, stable_swap); transfer_and_increase_allowance( &mut session, @@ -178,33 +178,33 @@ fn test_02(mut session: Session) { ); // add more liquidity with balanced tokens (charlie) - _ = stable_swap::add_liquidity( + handle_ink_error(stable_swap::add_liquidity( &mut session, stable_swap, CHARLIE, 1, vec![500 * ONE_DAI, 500 * ONE_USDT, 500 * ONE_USDC], charlie(), - ) - .expect("Should successfully add liquidity"); + )) + .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap, None), + share_price_and_total_shares(&mut session, stable_swap), (last_share_price, last_total_shares + 1500 * ONE_LPT) ); let last_total_shares = last_total_shares + 1500 * ONE_LPT; // remove by shares (charlie) - _ = stable_swap::remove_liquidity_by_shares( + handle_ink_error(stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, CHARLIE, 300 * ONE_LPT, vec![1 * ONE_DAI, 1 * ONE_USDT, 1 * ONE_USDC], charlie(), - ) - .expect("Should successfully remove liquidity"); + )) + .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), @@ -220,7 +220,7 @@ fn test_02(mut session: Session) { "Incorrect Users tokens balances" ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap, None), + share_price_and_total_shares(&mut session, stable_swap), (last_share_price, last_total_shares - 300 * ONE_LPT) ); let last_total_shares = last_total_shares - 300 * ONE_LPT; @@ -235,15 +235,15 @@ fn test_02(mut session: Session) { ); // add more liquidity with imbalanced tokens (dave) - _ = stable_swap::add_liquidity( + handle_ink_error(stable_swap::add_liquidity( &mut session, stable_swap, DAVE, 1, vec![100 * ONE_DAI, 200 * ONE_USDT, 400 * ONE_USDC], dave(), - ) - .expect("Should successfully add liquidity"); + )) + .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); // "Mint 699699997426210330025 shares for user2, fee is 299999998348895348 shares", // "Exchange swap got 59999999669779069 shares", @@ -264,7 +264,7 @@ fn test_02(mut session: Session) { ); let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap, None); + share_price_and_total_shares(&mut session, stable_swap); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -278,15 +278,15 @@ fn test_02(mut session: Session) { let last_total_shares = current_total_shares; // remove by tokens (charlie) - _ = stable_swap::remove_liquidity_by_amounts( + handle_ink_error(stable_swap::remove_liquidity_by_amounts( &mut session, stable_swap, CHARLIE, 550 * ONE_LPT, vec![1 * ONE_DAI, 500 * ONE_USDT, 1 * ONE_USDC], charlie(), - ) - .expect("Should successfully remove liquidity. Err: {err:?}"); + )) + .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); // "LP charlie removed 502598511257512352631 shares by given tokens, and fee is 598899301432400519 shares", // "Exchange swap got 119779860286480103 shares", assert_eq!( @@ -325,7 +325,7 @@ fn test_02(mut session: Session) { 699699997426210330025, "Incorrect users share" ); - let (current_share_price, _) = share_price_and_total_shares(&mut session, stable_swap, None); + let (current_share_price, _) = share_price_and_total_shares(&mut session, stable_swap); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -348,53 +348,51 @@ fn test_02(mut session: Session) { ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap, None), + share_price_and_total_shares(&mut session, stable_swap), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); // dave remove by shares trigger slippage - let res = stable_swap::remove_liquidity_by_shares( + let res = handle_ink_error(stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, DAVE, 300 * ONE_LPT, vec![1 * ONE_DAI, 298 * ONE_USDT, 1 * ONE_USDC], dave(), - ) - .expect_err("Should return an error"); + )); assert_eq!( res, - StablePoolError::InsufficientOutputAmount(), + Err(StablePoolError::InsufficientOutputAmount()), "Should return correct error" ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap, None), + share_price_and_total_shares(&mut session, stable_swap), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); // dave remove by tokens trigger slippage - let res = stable_swap::remove_liquidity_by_amounts( + let res = handle_ink_error(stable_swap::remove_liquidity_by_amounts( &mut session, stable_swap, DAVE, 300 * ONE_LPT, vec![1 * ONE_DAI, 298 * ONE_USDT, 1 * ONE_USDC], dave(), - ) - .expect_err("Shoulf return an error"); + )); assert_eq!( res, - StablePoolError::InsufficientLiquidityBurned(), + Err(StablePoolError::InsufficientLiquidityBurned()), "Should return correct error" ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap, None), + share_price_and_total_shares(&mut session, stable_swap), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); @@ -411,15 +409,15 @@ fn test_02(mut session: Session) { ); // dave remove by share - _ = stable_swap::remove_liquidity_by_shares( + handle_ink_error(stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, DAVE, 300 * ONE_LPT, vec![1 * ONE_DAI, 1 * ONE_USDT, 1 * ONE_USDC], dave(), - ) - .expect("Should successfully remove liquidity"); + )) + .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); // "LP dave removed 498596320225563082252 shares by given tokens, and fee is 597500435701476809 shares", // "Exchange swap got 119500087140295361 shares", @@ -435,7 +433,7 @@ fn test_02(mut session: Session) { ); let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap, None); + share_price_and_total_shares(&mut session, stable_swap); assert_eq!( current_share_price, last_share_price, "Incorrect share price" @@ -447,15 +445,15 @@ fn test_02(mut session: Session) { ); let last_total_shares = last_total_shares - 300 * ONE_LPT; - _ = stable_swap::remove_liquidity_by_amounts( + handle_ink_error(stable_swap::remove_liquidity_by_amounts( &mut session, stable_swap, DAVE, 499 * ONE_LPT, vec![498 * ONE_DAI, 0 * ONE_USDT, 0 * ONE_USDC], dave(), - ) - .expect("Should successfully remove liquidity"); + )) + .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); // "LP user2 removed 498596320225563082252 shares by given tokens, and fee is 597500435701476809 shares", // "Exchange swap got 119500087140295361 shares, No referral fee, from remove_liquidity_by_tokens", // -- DIFF -- @@ -475,7 +473,7 @@ fn test_02(mut session: Session) { let last_total_shares = last_total_shares - 498596320224035614380 + 119500087140112295; let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap, None); + share_price_and_total_shares(&mut session, stable_swap); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -498,7 +496,7 @@ fn test_02(mut session: Session) { BOB, ); - stable_swap::add_liquidity( + handle_ink_error(stable_swap::add_liquidity( &mut session, stable_swap, EVA, @@ -509,8 +507,8 @@ fn test_02(mut session: Session) { 100_000_000_000 * ONE_USDC, ], eva(), - ) - .expect("Should successfully add liquidity"); + )) + .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); // "Mint 299997911758886758506069372942 shares for user3, fee is 895808190595468286848457 shares", // "Exchange swap got 179161638119093657369691 shares, No referral fee, from add_liquidity", // -- DIFF -- diff --git a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs index 331c95d..ba0015b 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs @@ -1,4 +1,4 @@ -use crate::mock_sazero_rate_contract; +use crate::sazero_rate_mock_contract; use crate::stable_pool_contract; use crate::utils::*; @@ -8,49 +8,40 @@ use drink::{self, runtime::MinimalRuntime, session::Session}; use ink_primitives::AccountId; use ink_wrapper_types::{Connection, ToAccountId}; -const WAZERO_DEC: u8 = 12; const SAZERO_DEC: u8 = 12; +const WAZERO_DEC: u8 = 12; -const ONE_LPT: u128 = 10u128.pow(18); -const ONE_WAZERO: u128 = 10u128.pow(WAZERO_DEC as u32); const ONE_SAZERO: u128 = 10u128.pow(SAZERO_DEC as u32); +const ONE_AZERO: u128 = 10u128.pow(WAZERO_DEC as u32); + +const INIT_SUPPLY: u128 = 1_000_000; // 1M -const EXPIRE_TS: u64 = 24 * 3600 * 1000; // 24h +const TRADE_FEE_BPS: u16 = 6; +const PROTOCOL_FEE_BPS: u16 = 2000; + +const AMP_COEF: u128 = 1000; fn setup_rated_swap_with_tokens( session: &mut Session, - caller: drink::AccountId32, - initial_token_supply: u128, + sazero: AccountId, + wazero: AccountId, init_amp_coef: u128, rate_expiration_duration_ms: u64, + caller: drink::AccountId32, trade_fee: u16, protocol_fee: u16, -) -> (AccountId, AccountId, AccountId, AccountId) { + fee_receiver: Option, +) -> stable_pool_contract::Instance { //upload and deploy rate mock session .upload_code(stable_pool_contract::upload()) .expect("Upload stable_stable_pair_contract code"); session - .upload_code(mock_sazero_rate_contract::upload()) + .upload_code(sazero_rate_mock_contract::upload()) .expect("Upload sazero_rate_mock_contract code"); let _ = session.set_actor(caller.clone()); - let instance = mock_sazero_rate_contract::Instance::new(); - - let wazero = psp22_utils::setup_with_amounts( - session, - "wAZERO".to_string(), - WAZERO_DEC, - initial_token_supply * ONE_WAZERO, - caller.clone(), - ); - let sazero = psp22_utils::setup_with_amounts( - session, - "SAZERO".to_string(), - SAZERO_DEC, - initial_token_supply * ONE_SAZERO, - caller.clone(), - ); + let instance = sazero_rate_mock_contract::Instance::new(); let rate_mock_address = session .instantiate(instance) @@ -59,7 +50,7 @@ fn setup_rated_swap_with_tokens( .to_account_id() .into(); let instance = stable_pool_contract::Instance::new_rated( - vec![sazero.into(), wazero.into()], + vec![sazero, wazero], vec![SAZERO_DEC, WAZERO_DEC], vec![Some(rate_mock_address), None], rate_expiration_duration_ms, @@ -67,166 +58,104 @@ fn setup_rated_swap_with_tokens( caller.to_account_id(), trade_fee, protocol_fee, - Some(fee_receiver()), + fee_receiver, ); - let rated_swap = session + session .instantiate(instance) .unwrap() .result .to_account_id() - .into(); + .into() +} + +fn setup_all( + session: &mut Session, + _enable_protocol_fee: bool, +) -> (AccountId, AccountId, AccountId) { + upload_all(session); + + let wazero = psp22_utils::setup_with_amounts( + session, + "wAZERO".to_string(), + WAZERO_DEC, + INIT_SUPPLY * ONE_AZERO, + BOB, + ); + let sazero = psp22_utils::setup_with_amounts( + session, + "SAZERO".to_string(), + SAZERO_DEC, + INIT_SUPPLY * ONE_SAZERO, + BOB, + ); + let stable_pool_contract = setup_rated_swap_with_tokens( + session, + sazero.into(), + wazero.into(), + AMP_COEF, + 10000, //10 seconds rate cache expiration + BOB, + TRADE_FEE_BPS, + PROTOCOL_FEE_BPS, + Some(bob()), + ); for token in [sazero, wazero] { psp22_utils::increase_allowance( session, token.into(), - rated_swap, + stable_pool_contract.into(), u128::MAX, - caller.clone(), + BOB, ) .unwrap(); } - (rated_swap, sazero.into(), wazero.into(), rate_mock_address) + (stable_pool_contract.into(), sazero.into(), wazero.into()) } -fn set_sazero_rate( - session: &mut Session, - mock_sazero_rate_contract: AccountId, - rate: u128, -) { - _ = handle_ink_error( - session - .execute( - mock_sazero_rate_contract::Instance::from(mock_sazero_rate_contract).set_rate(rate), - ) - .unwrap(), - ); -} - -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/tests/test_rated_pool.rs#L27 #[drink::test] fn test_01(mut session: Session) { - seed_account(&mut session, CHARLIE); - seed_account(&mut session, DAVE); - seed_account(&mut session, EVA); - + let one_minute: u64 = 60000; let now = get_timestamp(&mut session); set_timestamp(&mut session, now); - let initial_token_supply: u128 = 1_000_000_000; - let (rated_swap, sazero, wazero, mock_sazero_rate) = setup_rated_swap_with_tokens( - &mut session, - BOB, - initial_token_supply, - 10000, - EXPIRE_TS, - 25, - 2000, - ); - - set_timestamp(&mut session, now * EXPIRE_TS); - set_sazero_rate(&mut session, mock_sazero_rate, 2 * RATE_PRECISION); - + upload_all(&mut session); + let (rated_swap, sazero, wazero) = setup_all(&mut session, false); _ = stable_swap::add_liquidity( &mut session, rated_swap.into(), BOB, 1, - vec![50000 * ONE_SAZERO, 100000 * ONE_WAZERO], + vec![INIT_SUPPLY * ONE_SAZERO / 10, INIT_SUPPLY * ONE_AZERO / 10], bob(), - ) - .expect("Should successfully swap. Err: {err:?}"); - assert_eq!( - psp22_utils::balance_of(&mut session, rated_swap, bob()), - 200000 * ONE_LPT, - "Incorrect user share" ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), - ); - assert_eq!( - last_total_shares, - 200000 * ONE_LPT, - "Incorrect total shares" - ); - assert_eq!(last_share_price, 100000000, "Incorrect share price"); + let amount = 10_000 * ONE_SAZERO; // 10k - transfer_and_increase_allowance( - &mut session, - rated_swap, - vec![sazero, wazero], - CHARLIE, - vec![100000 * ONE_SAZERO, 100000 * ONE_WAZERO], - BOB, - ); - _ = stable_swap::add_liquidity( + psp22_utils::increase_allowance( &mut session, + sazero.into(), rated_swap.into(), - CHARLIE, - 1, - vec![50000 * ONE_SAZERO, 100000 * ONE_WAZERO], - charlie(), + u128::MAX, + BOB, ) - .expect("Should successfully swap"); - assert_eq!( - psp22_utils::balance_of(&mut session, rated_swap, charlie()), - 200000 * ONE_LPT, - "Incorrect user share" - ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), - ); - assert_eq!( - last_total_shares, - 400000 * ONE_LPT, - "Incorrect total shares" - ); - assert_eq!(last_share_price, 100000000, "Incorrect share price"); + .unwrap(); - _ = stable_swap::remove_liquidity_by_shares( + set_timestamp(&mut session, now + 10000 * one_minute); + let (_amount_out, _fee) = handle_ink_error(stable_swap::swap_exact_in( &mut session, rated_swap.into(), - CHARLIE, - 200000 * ONE_LPT, - vec![1 * ONE_SAZERO, 1 * ONE_WAZERO], - charlie(), - ) - .expect("Should successfully swap"); - assert_eq!( - psp22_utils::balance_of(&mut session, rated_swap, charlie()), - 0, - "Incorrect user share" - ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), - ); - assert_eq!( - last_total_shares, - 200000 * ONE_LPT, - "Incorrect total shares" - ); - assert_eq!(last_share_price, 100000000, "Incorrect share price"); - - // let err = stable_swap::remove_liquidity_by_shares( - // &mut session, - // rated_swap.into(), - // BOB, - // 200000 * ONE_LPT, - // vec![1 * ONE_SAZERO, 1 * ONE_WAZERO], - // bob(), - // ) - // .expect_err("Should return an error"); - - // assert_eq!( - // err, - // StablePoolError::MinReserve(), - // "Should return correct error" - // ) + BOB, + sazero.into(), + wazero.into(), + amount, + 1, // min_token_out + bob(), + )) + .unwrap_or_else(|err| panic!("Should return valid result. Err: {err:?}")); + + let reserves = stable_swap::reserves(&mut session, rated_swap.into()); + let balance_0 = psp22_utils::balance_of(&mut session, sazero.into(), rated_swap.into()); + let balance_1 = psp22_utils::balance_of(&mut session, wazero.into(), rated_swap.into()); + assert_eq!(reserves, vec![balance_0, balance_1]); } diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs index 6516126..51c69f1 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs @@ -32,16 +32,16 @@ fn setup_test_swap_exact_in( bob(), ); - let swap_result = stable_swap::swap_exact_in( + let swap_result = handle_ink_error(stable_swap::swap_exact_in( session, stable_swap, BOB, - tokens[0], // in - tokens[1], // out + tokens[0], // in + tokens[1], // out swap_amount_in, // amount_in 0, // min_token_out bob(), - ); + )); if expected_swap_amount_out_total_result.is_err() { match swap_result { @@ -93,7 +93,9 @@ fn setup_test_swap_exact_in( [0, expected_protocol_fee_part].to_vec(), bob(), ) - .expect("Should remove lp"); + .result + .unwrap() + .unwrap(); assert_eq!( total_lp_required - lp_fee_part, protocol_fee_lp, @@ -108,11 +110,11 @@ fn test_01(mut session: Session) { &mut session, vec![6, 6], // decimals vec![100000000000, 100000000000], // initial reserves - 1000, // A - 6, // fee BPS - 2000, // protocol fee BPS - 10000000000, // swap_amount_in - Ok(9999495232), // expected out (with fee) + 1000, // A + 6, // fee BPS + 2000, // protocol fee BPS + 10000000000, // swap_amount_in + Ok(9999495232), // expected out (with fee) ); } diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs index 7350a26..226dd1e 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs @@ -34,15 +34,15 @@ fn setup_test_swap_received( let _ = psp22_utils::transfer(session, tokens[0], stable_swap, swap_amount_in, BOB); - let swap_result = stable_swap::swap_received( + let swap_result = handle_ink_error(stable_swap::swap_received( session, stable_swap, BOB, tokens[0], // in tokens[1], // out - 0, // min_token_out + 0, // min_token_out bob(), - ); + )); if expected_swap_amount_out_total_result.is_err() { match swap_result { @@ -94,7 +94,9 @@ fn setup_test_swap_received( [0, expected_protocol_fee_part].to_vec(), bob(), ) - .expect("Should remove lp"); + .result + .unwrap() + .unwrap(); assert_eq!( total_lp_required - lp_fee_part, protocol_fee_lp, @@ -109,11 +111,11 @@ fn test_01(mut session: Session) { &mut session, vec![6, 6], // decimals vec![100000000000, 100000000000], // initial reserves - 1000, // A - 6, // fee BPS - 2000, // protocol fee BPS - 10000000000, // swap_amount_in - Ok(9999495232), // expected out (with fee) + 1000, // A + 6, // fee BPS + 2000, // protocol fee BPS + 10000000000, // swap_amount_in + Ok(9999495232), // expected out (with fee) ); } diff --git a/amm/drink-tests/src/utils.rs b/amm/drink-tests/src/utils.rs index 166ed95..2b1fc50 100644 --- a/amm/drink-tests/src/utils.rs +++ b/amm/drink-tests/src/utils.rs @@ -1,4 +1,3 @@ -#![allow(dead_code)] use crate::*; use anyhow::Result; @@ -82,9 +81,9 @@ pub mod stable_swap { min_share_amount: u128, amounts: Vec, to: AccountId, - ) -> Result<(u128, u128), StablePoolError> { - _ = session.set_actor(caller); - handle_ink_error(session + ) -> ContractResult, InkLangError>> { + let _ = session.set_actor(caller); + session .execute( stable_pool_contract::Instance::from(stable_pool).add_liquidity( min_share_amount, @@ -92,7 +91,7 @@ pub mod stable_swap { to, ), ) - .unwrap()) + .unwrap() } pub fn remove_liquidity_by_amounts( @@ -102,9 +101,9 @@ pub mod stable_swap { max_share_amount: u128, amounts: Vec, to: AccountId, - ) -> Result<(u128, u128), StablePoolError> { - _ = session.set_actor(caller); - handle_ink_error(session + ) -> ContractResult, InkLangError>> { + let _ = session.set_actor(caller); + session .execute( stable_pool_contract::Instance::from(stable_pool).remove_liquidity_by_amounts( max_share_amount, @@ -112,7 +111,7 @@ pub mod stable_swap { to, ), ) - .unwrap()) + .unwrap() } pub fn remove_liquidity_by_shares( @@ -122,19 +121,17 @@ pub mod stable_swap { shares_amount: u128, min_amounts: Vec, to: AccountId, - ) -> Result, StablePoolError> { - _ = session.set_actor(caller); - handle_ink_error( - session - .execute( - stable_pool_contract::Instance::from(stable_pool).remove_liquidity_by_shares( - shares_amount, - min_amounts, - to, - ), - ) - .unwrap(), - ) + ) -> ContractResult, StablePoolError>, InkLangError>> { + let _ = session.set_actor(caller); + session + .execute( + stable_pool_contract::Instance::from(stable_pool).remove_liquidity_by_shares( + shares_amount, + min_amounts, + to, + ), + ) + .unwrap() } pub fn swap_exact_in( @@ -146,21 +143,21 @@ pub mod stable_swap { token_in_amount: u128, min_token_out_amount: u128, to: AccountId, - ) -> Result<(u128, u128), StablePoolError> { - _ = session.set_actor(caller); - handle_ink_error( - session - .execute( - stable_pool_contract::Instance::from(stable_pool).swap_exact_in( - token_in, - token_out, - token_in_amount, - min_token_out_amount, - to, - ), - ) - .unwrap(), - ) + ) -> ContractResult< + Result, ink_wrapper_types::InkLangError>, + > { + let _ = session.set_actor(caller); + session + .execute( + stable_pool_contract::Instance::from(stable_pool).swap_exact_in( + token_in, + token_out, + token_in_amount, + min_token_out_amount, + to, + ), + ) + .unwrap() } pub fn swap_exact_out( @@ -172,21 +169,21 @@ pub mod stable_swap { token_out_amount: u128, max_token_in_amount: u128, to: AccountId, - ) -> Result<(u128, u128), StablePoolError> { - _ = session.set_actor(caller); - handle_ink_error( - session - .execute( - stable_pool_contract::Instance::from(stable_pool).swap_exact_out( - token_in, - token_out, - token_out_amount, - max_token_in_amount, - to, - ), - ) - .unwrap(), - ) + ) -> ContractResult< + Result, ink_wrapper_types::InkLangError>, + > { + let _ = session.set_actor(caller); + session + .execute( + stable_pool_contract::Instance::from(stable_pool).swap_exact_out( + token_in, + token_out, + token_out_amount, + max_token_in_amount, + to, + ), + ) + .unwrap() } pub fn swap_received( @@ -197,58 +194,59 @@ pub mod stable_swap { token_out: AccountId, min_token_out_amount: u128, to: AccountId, - ) -> Result<(u128, u128), StablePoolError> { - _ = session.set_actor(caller); - handle_ink_error( - session - .execute( - stable_pool_contract::Instance::from(stable_pool).swap_received( - token_in, - token_out, - min_token_out_amount, - to, - ), - ) - .unwrap(), - ) + ) -> ContractResult< + Result, ink_wrapper_types::InkLangError>, + > { + let _ = session.set_actor(caller); + session + .execute( + stable_pool_contract::Instance::from(stable_pool).swap_received( + token_in, + token_out, + min_token_out_amount, + to, + ), + ) + .unwrap() } pub fn reserves(session: &mut Session, stable_pool: AccountId) -> Vec { - handle_ink_error( - session - .query(stable_pool_contract::Instance::from(stable_pool).reserves()) - .unwrap(), - ) + session + .query(stable_pool_contract::Instance::from(stable_pool).reserves()) + .unwrap() + .result + .unwrap() } pub fn amp_coef(session: &mut Session, stable_pool: AccountId) -> u128 { - handle_ink_error( - session - .query(stable_pool_contract::Instance::from(stable_pool).amp_coef()) - .unwrap(), - ) + session + .query(stable_pool_contract::Instance::from(stable_pool).amp_coef()) + .unwrap() + .result + .unwrap() } pub fn fees(session: &mut Session, stable_pool: AccountId) -> (u16, u16) { - handle_ink_error( - session - .query(stable_pool_contract::Instance::from(stable_pool).fees()) - .unwrap(), - ) + session + .query(stable_pool_contract::Instance::from(stable_pool).fees()) + .unwrap() + .result + .unwrap() } pub fn tokens(session: &mut Session, stable_pool: AccountId) -> Vec { - handle_ink_error( - session - .query(stable_pool_contract::Instance::from(stable_pool).tokens()) - .unwrap(), - ) + session + .query(stable_pool_contract::Instance::from(stable_pool).tokens()) + .unwrap() + .result + .unwrap() } } pub mod psp22_utils { use super::*; - use psp22::{Instance as PSP22, PSP22Metadata as _, PSP22 as _}; + use psp22::{Instance as PSP22, PSP22 as _, PSP22Metadata as _}; + /// Uploads and creates a PSP22 instance with 1B*10^18 issuance and given names. /// Returns its AccountId casted to PSP22 interface. diff --git a/amm/scripts/prepare_rust_wrappers.sh b/amm/scripts/prepare_rust_wrappers.sh index 037df52..88e8443 100755 --- a/amm/scripts/prepare_rust_wrappers.sh +++ b/amm/scripts/prepare_rust_wrappers.sh @@ -9,7 +9,7 @@ readonly SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null declare -a CONTRACTS=( "stable_pool_contract" "psp22" - "mock_sazero_rate_contract" + "sazero_rate_mock_contract" ) function wrap_contracts() { From 82a918087c042aa002808b61f8eb7e0c1518491c Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 3 Jul 2024 22:15:45 +0200 Subject: [PATCH 07/28] fix share price calculation --- amm/drink-tests/src/stable_swap_tests/mod.rs | 18 +- .../stable_swap_tests/tests_add_remove_lp.rs | 100 +++++----- amm/drink-tests/src/utils.rs | 172 +++++++++--------- 3 files changed, 153 insertions(+), 137 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/mod.rs b/amm/drink-tests/src/stable_swap_tests/mod.rs index 2842457..f10a990 100644 --- a/amm/drink-tests/src/stable_swap_tests/mod.rs +++ b/amm/drink-tests/src/stable_swap_tests/mod.rs @@ -1,5 +1,5 @@ -mod tests_rated; mod tests_add_remove_lp; +mod tests_rated; mod tests_swap_exact_in; mod tests_swap_received; @@ -18,6 +18,8 @@ use ink_wrapper_types::{Connection, ToAccountId}; pub const FEE_BPS_DENOM: u128 = 10_000; +pub const RATE_PRECISION: u128 = 10u128.pow(12); + pub const FEE_RECEIVER: AccountId32 = AccountId32::new([42u8; 32]); pub fn fee_receiver() -> ink_primitives::AccountId { @@ -88,14 +90,24 @@ pub fn setup_stable_swap_with_tokens( pub fn share_price_and_total_shares( session: &mut Session, stable_swap: AccountId, + token_rates: Option>, ) -> (u128, u128) { let total_shares = psp22_utils::total_supply(session, stable_swap); let reserves = stable_swap::reserves(session, stable_swap); + let token_rates: Vec = if let Some(rates) = token_rates { + rates + } else { + reserves.iter().map(|_| RATE_PRECISION).collect() + }; let sum_token = stable_swap::tokens(session, stable_swap) .iter() .zip(reserves.iter()) - .fold(0, |acc, (&token, reserve)| { - acc + reserve * 10u128.pow((18 - psp22_utils::token_decimals(session, token)).into()) + .zip(token_rates.iter()) + .fold(0, |acc, ((&token, reserve), rate)| { + acc + reserve + * 10u128.pow((18 - psp22_utils::token_decimals(session, token)).into()) + * rate + / RATE_PRECISION }); ( diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index 30b73b5..8f0a18d 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -21,15 +21,15 @@ fn test_01(mut session: Session) { BOB, ); - handle_ink_error(stable_swap::add_liquidity( + _ = stable_swap::add_liquidity( &mut session, stable_swap, BOB, 1, initial_reserves.clone(), bob(), - )) - .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + ) + .expect("Should successfully add liquidity"); assert_eq!( stable_swap::tokens(&mut session, stable_swap), @@ -75,7 +75,7 @@ fn test_01(mut session: Session) { "Incorrect Users tokens balances" ); - _ = handle_ink_error(stable_swap::swap_exact_in( + _ = stable_swap::swap_exact_in( &mut session, stable_swap, BOB, @@ -84,10 +84,10 @@ fn test_01(mut session: Session) { ONE_DAI, // amount_in 1, // min_token_out charlie(), - )) - .unwrap_or_else(|err| panic!("Should successfully swap. Err: {err:?}")); + ) + .expect("Should successfully swap"); - _ = handle_ink_error(stable_swap::swap_exact_in( + _ = stable_swap::swap_exact_in( &mut session, stable_swap, BOB, @@ -96,8 +96,8 @@ fn test_01(mut session: Session) { ONE_DAI, // amount_in 1, // min_token_out charlie(), - )) - .unwrap_or_else(|err| panic!("Should successfully swap. Err: {err:?}")); + ) + .expect("Should successfully swap. "); let balances: Vec = tokens .iter() @@ -155,18 +155,18 @@ fn test_02(mut session: Session) { BOB, ); - handle_ink_error(stable_swap::add_liquidity( + _ = stable_swap::add_liquidity( &mut session, stable_swap, BOB, 1, initial_reserves.clone(), bob(), - )) - .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + ) + .expect("Should successfully add liquidity"); let (last_share_price, last_total_shares) = - share_price_and_total_shares(&mut session, stable_swap); + share_price_and_total_shares(&mut session, stable_swap, None); transfer_and_increase_allowance( &mut session, @@ -178,33 +178,33 @@ fn test_02(mut session: Session) { ); // add more liquidity with balanced tokens (charlie) - handle_ink_error(stable_swap::add_liquidity( + _ = stable_swap::add_liquidity( &mut session, stable_swap, CHARLIE, 1, vec![500 * ONE_DAI, 500 * ONE_USDT, 500 * ONE_USDC], charlie(), - )) - .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + ) + .expect("Should successfully add liquidity"); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap), + share_price_and_total_shares(&mut session, stable_swap, None), (last_share_price, last_total_shares + 1500 * ONE_LPT) ); let last_total_shares = last_total_shares + 1500 * ONE_LPT; // remove by shares (charlie) - handle_ink_error(stable_swap::remove_liquidity_by_shares( + _ = stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, CHARLIE, 300 * ONE_LPT, vec![1 * ONE_DAI, 1 * ONE_USDT, 1 * ONE_USDC], charlie(), - )) - .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + ) + .expect("Should successfully remove liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), @@ -220,7 +220,7 @@ fn test_02(mut session: Session) { "Incorrect Users tokens balances" ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap), + share_price_and_total_shares(&mut session, stable_swap, None), (last_share_price, last_total_shares - 300 * ONE_LPT) ); let last_total_shares = last_total_shares - 300 * ONE_LPT; @@ -235,15 +235,15 @@ fn test_02(mut session: Session) { ); // add more liquidity with imbalanced tokens (dave) - handle_ink_error(stable_swap::add_liquidity( + _ = stable_swap::add_liquidity( &mut session, stable_swap, DAVE, 1, vec![100 * ONE_DAI, 200 * ONE_USDT, 400 * ONE_USDC], dave(), - )) - .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + ) + .expect("Should successfully add liquidity"); // "Mint 699699997426210330025 shares for user2, fee is 299999998348895348 shares", // "Exchange swap got 59999999669779069 shares", @@ -264,7 +264,7 @@ fn test_02(mut session: Session) { ); let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap); + share_price_and_total_shares(&mut session, stable_swap, None); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -278,15 +278,15 @@ fn test_02(mut session: Session) { let last_total_shares = current_total_shares; // remove by tokens (charlie) - handle_ink_error(stable_swap::remove_liquidity_by_amounts( + _ = stable_swap::remove_liquidity_by_amounts( &mut session, stable_swap, CHARLIE, 550 * ONE_LPT, vec![1 * ONE_DAI, 500 * ONE_USDT, 1 * ONE_USDC], charlie(), - )) - .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + ) + .expect("Should successfully remove liquidity. Err: {err:?}"); // "LP charlie removed 502598511257512352631 shares by given tokens, and fee is 598899301432400519 shares", // "Exchange swap got 119779860286480103 shares", assert_eq!( @@ -325,7 +325,7 @@ fn test_02(mut session: Session) { 699699997426210330025, "Incorrect users share" ); - let (current_share_price, _) = share_price_and_total_shares(&mut session, stable_swap); + let (current_share_price, _) = share_price_and_total_shares(&mut session, stable_swap, None); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -348,51 +348,53 @@ fn test_02(mut session: Session) { ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap), + share_price_and_total_shares(&mut session, stable_swap, None), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); // dave remove by shares trigger slippage - let res = handle_ink_error(stable_swap::remove_liquidity_by_shares( + let res = stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, DAVE, 300 * ONE_LPT, vec![1 * ONE_DAI, 298 * ONE_USDT, 1 * ONE_USDC], dave(), - )); + ) + .expect_err("Should return an error"); assert_eq!( res, - Err(StablePoolError::InsufficientOutputAmount()), + StablePoolError::InsufficientOutputAmount(), "Should return correct error" ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap), + share_price_and_total_shares(&mut session, stable_swap, None), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); // dave remove by tokens trigger slippage - let res = handle_ink_error(stable_swap::remove_liquidity_by_amounts( + let res = stable_swap::remove_liquidity_by_amounts( &mut session, stable_swap, DAVE, 300 * ONE_LPT, vec![1 * ONE_DAI, 298 * ONE_USDT, 1 * ONE_USDC], dave(), - )); + ) + .expect_err("Should return an error"); assert_eq!( res, - Err(StablePoolError::InsufficientLiquidityBurned()), + StablePoolError::InsufficientLiquidityBurned(), "Should return correct error" ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap), + share_price_and_total_shares(&mut session, stable_swap, None), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); @@ -409,15 +411,15 @@ fn test_02(mut session: Session) { ); // dave remove by share - handle_ink_error(stable_swap::remove_liquidity_by_shares( + _ = stable_swap::remove_liquidity_by_shares( &mut session, stable_swap, DAVE, 300 * ONE_LPT, vec![1 * ONE_DAI, 1 * ONE_USDT, 1 * ONE_USDC], dave(), - )) - .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + ) + .expect("Should successfully remove liquidity"); // "LP dave removed 498596320225563082252 shares by given tokens, and fee is 597500435701476809 shares", // "Exchange swap got 119500087140295361 shares", @@ -433,7 +435,7 @@ fn test_02(mut session: Session) { ); let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap); + share_price_and_total_shares(&mut session, stable_swap, None); assert_eq!( current_share_price, last_share_price, "Incorrect share price" @@ -445,15 +447,15 @@ fn test_02(mut session: Session) { ); let last_total_shares = last_total_shares - 300 * ONE_LPT; - handle_ink_error(stable_swap::remove_liquidity_by_amounts( + _ = stable_swap::remove_liquidity_by_amounts( &mut session, stable_swap, DAVE, 499 * ONE_LPT, vec![498 * ONE_DAI, 0 * ONE_USDT, 0 * ONE_USDC], dave(), - )) - .unwrap_or_else(|err| panic!("Should successfully remove liquidity. Err: {err:?}")); + ) + .expect("Should successfully remove liquidity"); // "LP user2 removed 498596320225563082252 shares by given tokens, and fee is 597500435701476809 shares", // "Exchange swap got 119500087140295361 shares, No referral fee, from remove_liquidity_by_tokens", // -- DIFF -- @@ -473,7 +475,7 @@ fn test_02(mut session: Session) { let last_total_shares = last_total_shares - 498596320224035614380 + 119500087140112295; let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap); + share_price_and_total_shares(&mut session, stable_swap, None); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -496,7 +498,7 @@ fn test_02(mut session: Session) { BOB, ); - handle_ink_error(stable_swap::add_liquidity( + stable_swap::add_liquidity( &mut session, stable_swap, EVA, @@ -507,8 +509,8 @@ fn test_02(mut session: Session) { 100_000_000_000 * ONE_USDC, ], eva(), - )) - .unwrap_or_else(|err| panic!("Should successfully add liquidity. Err: {err:?}")); + ) + .expect("Should successfully add liquidity"); // "Mint 299997911758886758506069372942 shares for user3, fee is 895808190595468286848457 shares", // "Exchange swap got 179161638119093657369691 shares, No referral fee, from add_liquidity", // -- DIFF -- diff --git a/amm/drink-tests/src/utils.rs b/amm/drink-tests/src/utils.rs index 2b1fc50..166ed95 100644 --- a/amm/drink-tests/src/utils.rs +++ b/amm/drink-tests/src/utils.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use crate::*; use anyhow::Result; @@ -81,9 +82,9 @@ pub mod stable_swap { min_share_amount: u128, amounts: Vec, to: AccountId, - ) -> ContractResult, InkLangError>> { - let _ = session.set_actor(caller); - session + ) -> Result<(u128, u128), StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error(session .execute( stable_pool_contract::Instance::from(stable_pool).add_liquidity( min_share_amount, @@ -91,7 +92,7 @@ pub mod stable_swap { to, ), ) - .unwrap() + .unwrap()) } pub fn remove_liquidity_by_amounts( @@ -101,9 +102,9 @@ pub mod stable_swap { max_share_amount: u128, amounts: Vec, to: AccountId, - ) -> ContractResult, InkLangError>> { - let _ = session.set_actor(caller); - session + ) -> Result<(u128, u128), StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error(session .execute( stable_pool_contract::Instance::from(stable_pool).remove_liquidity_by_amounts( max_share_amount, @@ -111,7 +112,7 @@ pub mod stable_swap { to, ), ) - .unwrap() + .unwrap()) } pub fn remove_liquidity_by_shares( @@ -121,17 +122,19 @@ pub mod stable_swap { shares_amount: u128, min_amounts: Vec, to: AccountId, - ) -> ContractResult, StablePoolError>, InkLangError>> { - let _ = session.set_actor(caller); - session - .execute( - stable_pool_contract::Instance::from(stable_pool).remove_liquidity_by_shares( - shares_amount, - min_amounts, - to, - ), - ) - .unwrap() + ) -> Result, StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error( + session + .execute( + stable_pool_contract::Instance::from(stable_pool).remove_liquidity_by_shares( + shares_amount, + min_amounts, + to, + ), + ) + .unwrap(), + ) } pub fn swap_exact_in( @@ -143,21 +146,21 @@ pub mod stable_swap { token_in_amount: u128, min_token_out_amount: u128, to: AccountId, - ) -> ContractResult< - Result, ink_wrapper_types::InkLangError>, - > { - let _ = session.set_actor(caller); - session - .execute( - stable_pool_contract::Instance::from(stable_pool).swap_exact_in( - token_in, - token_out, - token_in_amount, - min_token_out_amount, - to, - ), - ) - .unwrap() + ) -> Result<(u128, u128), StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error( + session + .execute( + stable_pool_contract::Instance::from(stable_pool).swap_exact_in( + token_in, + token_out, + token_in_amount, + min_token_out_amount, + to, + ), + ) + .unwrap(), + ) } pub fn swap_exact_out( @@ -169,21 +172,21 @@ pub mod stable_swap { token_out_amount: u128, max_token_in_amount: u128, to: AccountId, - ) -> ContractResult< - Result, ink_wrapper_types::InkLangError>, - > { - let _ = session.set_actor(caller); - session - .execute( - stable_pool_contract::Instance::from(stable_pool).swap_exact_out( - token_in, - token_out, - token_out_amount, - max_token_in_amount, - to, - ), - ) - .unwrap() + ) -> Result<(u128, u128), StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error( + session + .execute( + stable_pool_contract::Instance::from(stable_pool).swap_exact_out( + token_in, + token_out, + token_out_amount, + max_token_in_amount, + to, + ), + ) + .unwrap(), + ) } pub fn swap_received( @@ -194,59 +197,58 @@ pub mod stable_swap { token_out: AccountId, min_token_out_amount: u128, to: AccountId, - ) -> ContractResult< - Result, ink_wrapper_types::InkLangError>, - > { - let _ = session.set_actor(caller); - session - .execute( - stable_pool_contract::Instance::from(stable_pool).swap_received( - token_in, - token_out, - min_token_out_amount, - to, - ), - ) - .unwrap() + ) -> Result<(u128, u128), StablePoolError> { + _ = session.set_actor(caller); + handle_ink_error( + session + .execute( + stable_pool_contract::Instance::from(stable_pool).swap_received( + token_in, + token_out, + min_token_out_amount, + to, + ), + ) + .unwrap(), + ) } pub fn reserves(session: &mut Session, stable_pool: AccountId) -> Vec { - session - .query(stable_pool_contract::Instance::from(stable_pool).reserves()) - .unwrap() - .result - .unwrap() + handle_ink_error( + session + .query(stable_pool_contract::Instance::from(stable_pool).reserves()) + .unwrap(), + ) } pub fn amp_coef(session: &mut Session, stable_pool: AccountId) -> u128 { - session - .query(stable_pool_contract::Instance::from(stable_pool).amp_coef()) - .unwrap() - .result - .unwrap() + handle_ink_error( + session + .query(stable_pool_contract::Instance::from(stable_pool).amp_coef()) + .unwrap(), + ) } pub fn fees(session: &mut Session, stable_pool: AccountId) -> (u16, u16) { - session - .query(stable_pool_contract::Instance::from(stable_pool).fees()) - .unwrap() - .result - .unwrap() + handle_ink_error( + session + .query(stable_pool_contract::Instance::from(stable_pool).fees()) + .unwrap(), + ) } pub fn tokens(session: &mut Session, stable_pool: AccountId) -> Vec { - session - .query(stable_pool_contract::Instance::from(stable_pool).tokens()) - .unwrap() - .result - .unwrap() + handle_ink_error( + session + .query(stable_pool_contract::Instance::from(stable_pool).tokens()) + .unwrap(), + ) } } pub mod psp22_utils { use super::*; - use psp22::{Instance as PSP22, PSP22 as _, PSP22Metadata as _}; - + use psp22::{Instance as PSP22, PSP22Metadata as _, PSP22 as _}; /// Uploads and creates a PSP22 instance with 1B*10^18 issuance and given names. /// Returns its AccountId casted to PSP22 interface. From b76ef43b3f6427b4c2abf339880e47e1066bf578 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 3 Jul 2024 22:20:54 +0200 Subject: [PATCH 08/28] additional swap tests --- .../stable_swap_tests/tests_swap_exact_in.rs | 77 +++++++++++++------ .../stable_swap_tests/tests_swap_received.rs | 75 ++++++++++++------ 2 files changed, 105 insertions(+), 47 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs index 51c69f1..f649a38 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs @@ -3,7 +3,7 @@ use drink::{self, runtime::MinimalRuntime, session::Session}; use super::*; /// Tests swap of token at index 0 to token at index 1. -fn setup_test_swap_exact_in( +fn test_swap_exact_in( session: &mut Session, token_decimals: Vec, initial_reserves: Vec, @@ -32,16 +32,16 @@ fn setup_test_swap_exact_in( bob(), ); - let swap_result = handle_ink_error(stable_swap::swap_exact_in( + let swap_result = stable_swap::swap_exact_in( session, stable_swap, BOB, - tokens[0], // in - tokens[1], // out + tokens[0], // in + tokens[1], // out swap_amount_in, // amount_in 0, // min_token_out bob(), - )); + ); if expected_swap_amount_out_total_result.is_err() { match swap_result { @@ -93,9 +93,7 @@ fn setup_test_swap_exact_in( [0, expected_protocol_fee_part].to_vec(), bob(), ) - .result - .unwrap() - .unwrap(); + .expect("Should remove lp"); assert_eq!( total_lp_required - lp_fee_part, protocol_fee_lp, @@ -106,22 +104,22 @@ fn setup_test_swap_exact_in( // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L744 #[drink::test] fn test_01(mut session: Session) { - setup_test_swap_exact_in( + test_swap_exact_in( &mut session, vec![6, 6], // decimals vec![100000000000, 100000000000], // initial reserves - 1000, // A - 6, // fee BPS - 2000, // protocol fee BPS - 10000000000, // swap_amount_in - Ok(9999495232), // expected out (with fee) + 1000, // A + 6, // fee BPS + 2000, // protocol fee BPS + 10000000000, // swap_amount_in + Ok(9999495232), // expected out (with fee) ); } // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L763 #[drink::test] fn test_02(mut session: Session) { - setup_test_swap_exact_in( + test_swap_exact_in( &mut session, vec![12, 18], vec![100000000000000000, 100000000000000000000000], @@ -136,7 +134,7 @@ fn test_02(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L782 #[drink::test] fn test_03(mut session: Session) { - setup_test_swap_exact_in( + test_swap_exact_in( &mut session, vec![6, 6], vec![100000000000, 100000000000], @@ -151,7 +149,7 @@ fn test_03(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L801 #[drink::test] fn test_04(mut session: Session) { - setup_test_swap_exact_in( + test_swap_exact_in( &mut session, vec![12, 18], vec![100000000000000000, 100000000000000000000000], @@ -166,7 +164,7 @@ fn test_04(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L820 #[drink::test] fn test_05(mut session: Session) { - setup_test_swap_exact_in( + test_swap_exact_in( &mut session, vec![6, 6], vec![100000000000, 100000000000], @@ -179,9 +177,10 @@ fn test_05(mut session: Session) { } // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L839 +// Test that swapping 0.000000000001000000 gives 0.000000000000 (token precision cut) #[drink::test] -fn test_06(mut session: Session) { - setup_test_swap_exact_in( +fn test_06_a(mut session: Session) { + test_swap_exact_in( &mut session, vec![18, 12], vec![100000000000000000000000, 100000000000000000], @@ -193,10 +192,40 @@ fn test_06(mut session: Session) { ); } +// Test that swapping (with fees disabled) 0.000000000001000000 gives 0.000000000000 +#[drink::test] +fn test_06_b(mut session: Session) { + test_swap_exact_in( + &mut session, + vec![18, 12], + vec![100000000000000000000000, 100000000000000000], + 1000, + 0, + 0, + 1000000, + Ok(0), + ); +} + +// Test that swapping (with disabled fees) 0.000000000001000001 gives 0.000000000001 +#[drink::test] +fn test_06_c(mut session: Session) { + test_swap_exact_in( + &mut session, + vec![18, 12], + vec![100000000000000000000000, 100000000000000000], + 1000, + 0, + 0, + 1000001, + Ok(1), + ); +} + // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L858 #[drink::test] fn test_07(mut session: Session) { - setup_test_swap_exact_in( + test_swap_exact_in( &mut session, vec![6, 6], vec![100000000000, 100000000000], @@ -211,7 +240,7 @@ fn test_07(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L877 #[drink::test] fn test_08(mut session: Session) { - setup_test_swap_exact_in( + test_swap_exact_in( &mut session, vec![12, 18], vec![100000000000000000, 100000000000000000000000], @@ -226,7 +255,7 @@ fn test_08(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L896 #[drink::test] fn test_09(mut session: Session) { - setup_test_swap_exact_in( + test_swap_exact_in( &mut session, vec![6, 6], vec![100000000000, 100000000000], @@ -241,7 +270,7 @@ fn test_09(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L915 #[drink::test] fn test_10(mut session: Session) { - setup_test_swap_exact_in( + test_swap_exact_in( &mut session, vec![12, 18], vec![100000000000000000, 100000000000000000000000], diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs index 226dd1e..ab05371 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs @@ -3,7 +3,7 @@ use drink::{self, runtime::MinimalRuntime, session::Session}; use super::*; /// Tests swap of token at index 0 to token at index 1. -fn setup_test_swap_received( +fn test_swap_received( session: &mut Session, token_decimals: Vec, initial_reserves: Vec, @@ -34,15 +34,15 @@ fn setup_test_swap_received( let _ = psp22_utils::transfer(session, tokens[0], stable_swap, swap_amount_in, BOB); - let swap_result = handle_ink_error(stable_swap::swap_received( + let swap_result = stable_swap::swap_received( session, stable_swap, BOB, tokens[0], // in tokens[1], // out - 0, // min_token_out + 0, // min_token_out bob(), - )); + ); if expected_swap_amount_out_total_result.is_err() { match swap_result { @@ -94,9 +94,7 @@ fn setup_test_swap_received( [0, expected_protocol_fee_part].to_vec(), bob(), ) - .result - .unwrap() - .unwrap(); + .expect("Should remove lp"); assert_eq!( total_lp_required - lp_fee_part, protocol_fee_lp, @@ -107,22 +105,22 @@ fn setup_test_swap_received( // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L744 #[drink::test] fn test_01(mut session: Session) { - setup_test_swap_received( + test_swap_received( &mut session, vec![6, 6], // decimals vec![100000000000, 100000000000], // initial reserves - 1000, // A - 6, // fee BPS - 2000, // protocol fee BPS - 10000000000, // swap_amount_in - Ok(9999495232), // expected out (with fee) + 1000, // A + 6, // fee BPS + 2000, // protocol fee BPS + 10000000000, // swap_amount_in + Ok(9999495232), // expected out (with fee) ); } // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L763 #[drink::test] fn test_02(mut session: Session) { - setup_test_swap_received( + test_swap_received( &mut session, vec![12, 18], vec![100000000000000000, 100000000000000000000000], @@ -137,7 +135,7 @@ fn test_02(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L782 #[drink::test] fn test_03(mut session: Session) { - setup_test_swap_received( + test_swap_received( &mut session, vec![6, 6], vec![100000000000, 100000000000], @@ -152,7 +150,7 @@ fn test_03(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L801 #[drink::test] fn test_04(mut session: Session) { - setup_test_swap_received( + test_swap_received( &mut session, vec![12, 18], vec![100000000000000000, 100000000000000000000000], @@ -167,7 +165,7 @@ fn test_04(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L820 #[drink::test] fn test_05(mut session: Session) { - setup_test_swap_received( + test_swap_received( &mut session, vec![6, 6], vec![100000000000, 100000000000], @@ -180,9 +178,10 @@ fn test_05(mut session: Session) { } // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L839 +// Test that swapping 0.000000000001000000 gives 0.000000000000 (token precision cut) #[drink::test] -fn test_06(mut session: Session) { - setup_test_swap_received( +fn test_06_a(mut session: Session) { + test_swap_received( &mut session, vec![18, 12], vec![100000000000000000000000, 100000000000000000], @@ -194,10 +193,40 @@ fn test_06(mut session: Session) { ); } +// Test that swapping (with disabled fees) 0.000000000001000000 gives 0.000000000000 +#[drink::test] +fn test_06_b(mut session: Session) { + test_swap_received( + &mut session, + vec![18, 12], + vec![100000000000000000000000, 100000000000000000], + 1000, + 0, + 0, + 1000000, + Ok(0), + ); +} + +/// Test that swapping (with disabled fees) 0.000000000001000001 gives 0.000000000001 +#[drink::test] +fn test_06_c(mut session: Session) { + test_swap_received( + &mut session, + vec![18, 12], + vec![100000000000000000000000, 100000000000000000], + 1000, + 0, + 0, + 1000001, + Ok(1), + ); +} + // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L858 #[drink::test] fn test_07(mut session: Session) { - setup_test_swap_received( + test_swap_received( &mut session, vec![6, 6], vec![100000000000, 100000000000], @@ -212,7 +241,7 @@ fn test_07(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L877 #[drink::test] fn test_08(mut session: Session) { - setup_test_swap_received( + test_swap_received( &mut session, vec![12, 18], vec![100000000000000000, 100000000000000000000000], @@ -227,7 +256,7 @@ fn test_08(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L896 #[drink::test] fn test_09(mut session: Session) { - setup_test_swap_received( + test_swap_received( &mut session, vec![6, 6], vec![100000000000, 100000000000], @@ -242,7 +271,7 @@ fn test_09(mut session: Session) { // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L915 #[drink::test] fn test_10(mut session: Session) { - setup_test_swap_received( + test_swap_received( &mut session, vec![12, 18], vec![100000000000000000, 100000000000000000000000], From b2149844c69a51cadeeef5e69618ba037711df8e Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 3 Jul 2024 22:36:18 +0200 Subject: [PATCH 09/28] split tests --- amm/drink-tests/src/stable_swap_tests/mod.rs | 6 + .../stable_swap_tests/tests_add_remove_lp.rs | 135 +----------------- .../src/stable_swap_tests/tests_getters.rs | 129 +++++++++++++++++ 3 files changed, 136 insertions(+), 134 deletions(-) create mode 100644 amm/drink-tests/src/stable_swap_tests/tests_getters.rs diff --git a/amm/drink-tests/src/stable_swap_tests/mod.rs b/amm/drink-tests/src/stable_swap_tests/mod.rs index f10a990..d3eb393 100644 --- a/amm/drink-tests/src/stable_swap_tests/mod.rs +++ b/amm/drink-tests/src/stable_swap_tests/mod.rs @@ -1,4 +1,5 @@ mod tests_add_remove_lp; +mod tests_getters; mod tests_rated; mod tests_swap_exact_in; mod tests_swap_received; @@ -26,6 +27,11 @@ pub fn fee_receiver() -> ink_primitives::AccountId { AsRef::<[u8; 32]>::as_ref(&FEE_RECEIVER).clone().into() } +pub const ONE_LPT: u128 = 1000000000000000000; +pub const ONE_DAI: u128 = 1000000000000000000; +pub const ONE_USDT: u128 = 1000000; +pub const ONE_USDC: u128 = 1000000; + pub fn setup_stable_swap_with_tokens( session: &mut Session, token_decimals: Vec, diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index 8f0a18d..df59c2d 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -1,143 +1,10 @@ use drink::{self, session::Session}; -const ONE_LPT: u128 = 1000000000000000000; -const ONE_DAI: u128 = 1000000000000000000; -const ONE_USDT: u128 = 1000000; -const ONE_USDC: u128 = 1000000; - use super::*; -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/tests/test_stable_pool.rs#L23 -#[drink::test] -fn test_01(mut session: Session) { - let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; - let (stable_swap, tokens) = setup_stable_swap_with_tokens( - &mut session, - vec![18, 6, 6], - initial_reserves.iter().map(|amount| amount * 10).collect(), - 10_000, - 25, - 2000, - BOB, - ); - - _ = stable_swap::add_liquidity( - &mut session, - stable_swap, - BOB, - 1, - initial_reserves.clone(), - bob(), - ) - .expect("Should successfully add liquidity"); - - assert_eq!( - stable_swap::tokens(&mut session, stable_swap), - tokens, - "Incorrect token accounts" - ); - assert_eq!( - stable_swap::reserves(&mut session, stable_swap), - initial_reserves, - "Incorrect reserves" - ); - assert_eq!( - stable_swap::amp_coef(&mut session, stable_swap), - 10_000, - "Incorrect A" - ); - assert_eq!( - stable_swap::fees(&mut session, stable_swap), - (25, 2000), - "Incorrect fees" - ); - assert_eq!( - psp22_utils::total_supply(&mut session, stable_swap), - 300_000 * ONE_LPT, - "Incorrect LP token supply" - ); - assert_eq!( - psp22_utils::balance_of(&mut session, stable_swap, bob()), - 300_000 * ONE_LPT, - "Incorrect Users LP token balance" - ); - - let balances: Vec = tokens - .iter() - .map(|&token| psp22_utils::balance_of(&mut session, token, bob())) - .collect(); - assert_eq!( - balances, - initial_reserves - .iter() - .map(|amount| amount * 9) - .collect::>(), - "Incorrect Users tokens balances" - ); - - _ = stable_swap::swap_exact_in( - &mut session, - stable_swap, - BOB, - tokens[0], // DAI - tokens[2], // USDC - ONE_DAI, // amount_in - 1, // min_token_out - charlie(), - ) - .expect("Should successfully swap"); - - _ = stable_swap::swap_exact_in( - &mut session, - stable_swap, - BOB, - tokens[0], // DAI - tokens[1], // USDC - ONE_DAI, // amount_in - 1, // min_token_out - charlie(), - ) - .expect("Should successfully swap. "); - - let balances: Vec = tokens - .iter() - .map(|&token| psp22_utils::balance_of(&mut session, token, charlie())) - .collect(); - assert_eq!( - balances, - vec![0, 997499, 997499], - "Incorrect Users tokens balances" - ); - - let balances: Vec = tokens - .iter() - .map(|&token| psp22_utils::balance_of(&mut session, token, stable_swap)) - .collect(); - assert_eq!( - stable_swap::reserves(&mut session, stable_swap), - balances, - "Pool reserves and token balances mismatch" - ); - - assert_eq!( - stable_swap::reserves(&mut session, stable_swap), - vec![ - 100002 * ONE_DAI, - 99999 * ONE_USDT + 2501, // -- DIFF -- 99999 * ONE_USDT + 2500 - 99999 * ONE_USDC + 2501 // -- DIFF -- 99999 * ONE_USDC + 2500 - ], - "Incorrect reserves" - ); - assert_eq!( - psp22_utils::total_supply(&mut session, stable_swap), - 300000 * ONE_LPT + 498999996725367 + 498999993395420, // -- DIFF -- 300000 * ONE_LPT + 499999996666583 + 499999993277742 - "Incorrect LP token supply" - ); -} - // ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/tests/test_stable_pool.rs#L123 #[drink::test] -fn test_02(mut session: Session) { +fn test_01(mut session: Session) { seed_account(&mut session, CHARLIE); seed_account(&mut session, DAVE); seed_account(&mut session, EVA); diff --git a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs new file mode 100644 index 0000000..d8c12f3 --- /dev/null +++ b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs @@ -0,0 +1,129 @@ +use super::*; + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/tests/test_stable_pool.rs#L23 +#[drink::test] +fn test_01(mut session: Session) { + let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![18, 6, 6], + initial_reserves.iter().map(|amount| amount * 10).collect(), + 10_000, + 25, + 2000, + BOB, + ); + + _ = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + assert_eq!( + stable_swap::tokens(&mut session, stable_swap), + tokens, + "Incorrect token accounts" + ); + assert_eq!( + stable_swap::reserves(&mut session, stable_swap), + initial_reserves, + "Incorrect reserves" + ); + assert_eq!( + stable_swap::amp_coef(&mut session, stable_swap), + 10_000, + "Incorrect A" + ); + assert_eq!( + stable_swap::fees(&mut session, stable_swap), + (25, 2000), + "Incorrect fees" + ); + assert_eq!( + psp22_utils::total_supply(&mut session, stable_swap), + 300_000 * ONE_LPT, + "Incorrect LP token supply" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, bob()), + 300_000 * ONE_LPT, + "Incorrect Users LP token balance" + ); + + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, bob())) + .collect(); + assert_eq!( + balances, + initial_reserves + .iter() + .map(|amount| amount * 9) + .collect::>(), + "Incorrect Users tokens balances" + ); + + _ = stable_swap::swap_exact_in( + &mut session, + stable_swap, + BOB, + tokens[0], // DAI + tokens[2], // USDC + ONE_DAI, // amount_in + 1, // min_token_out + charlie(), + ) + .expect("Should successfully swap"); + + _ = stable_swap::swap_exact_in( + &mut session, + stable_swap, + BOB, + tokens[0], // DAI + tokens[1], // USDC + ONE_DAI, // amount_in + 1, // min_token_out + charlie(), + ) + .expect("Should successfully swap. "); + + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, charlie())) + .collect(); + assert_eq!( + balances, + vec![0, 997499, 997499], + "Incorrect Users tokens balances" + ); + + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, stable_swap)) + .collect(); + assert_eq!( + stable_swap::reserves(&mut session, stable_swap), + balances, + "Pool reserves and token balances mismatch" + ); + + assert_eq!( + stable_swap::reserves(&mut session, stable_swap), + vec![ + 100002 * ONE_DAI, + 99999 * ONE_USDT + 2501, // -- DIFF -- 99999 * ONE_USDT + 2500 + 99999 * ONE_USDC + 2501 // -- DIFF -- 99999 * ONE_USDC + 2500 + ], + "Incorrect reserves" + ); + assert_eq!( + psp22_utils::total_supply(&mut session, stable_swap), + 300000 * ONE_LPT + 498999996725367 + 498999993395420, // -- DIFF -- 300000 * ONE_LPT + 499999996666583 + 499999993277742 + "Incorrect LP token supply" + ); +} \ No newline at end of file From b63808ad00b20105ed5563aa8cf0893379c36224 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 3 Jul 2024 22:39:04 +0200 Subject: [PATCH 10/28] ensure reserves updated properly --- .../src/stable_swap_tests/tests_swap_exact_in.rs | 12 +++++++++++- .../src/stable_swap_tests/tests_swap_received.rs | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs index f649a38..1b72056 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs @@ -64,8 +64,18 @@ fn test_swap_exact_in( assert_eq!(expected_swap_amount_out, amount_out, "Amount out mismatch"); assert_eq!(expected_fee, fee, "Fee mismatch"); - // check if reserves are equal the actual balances + // check if reserves were updated properly let reserves = stable_swap::reserves(session, stable_swap); + assert_eq!( + reserves, + [ + initial_reserves[0] + swap_amount_in, + initial_reserves[1] - expected_swap_amount_out + ], + "Reserves not updated properly" + ); + + // check if reserves are equal the actual balances let balance_0 = psp22_utils::balance_of(session, tokens[0], stable_swap); let balance_1 = psp22_utils::balance_of(session, tokens[1], stable_swap); assert_eq!( diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs index ab05371..bf15a3c 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs @@ -65,8 +65,18 @@ fn test_swap_received( assert_eq!(expected_swap_amount_out, amount_out, "Amount out mismatch"); assert_eq!(expected_fee, fee, "Fee mismatch"); - // check if reserves are equal the actual balances + // check if reserves were updated properly let reserves = stable_swap::reserves(session, stable_swap); + assert_eq!( + reserves, + [ + initial_reserves[0] + swap_amount_in, + initial_reserves[1] - expected_swap_amount_out + ], + "Reserves not updated properly" + ); + + // check if reserves are equal the actual balances let balance_0 = psp22_utils::balance_of(session, tokens[0], stable_swap); let balance_1 = psp22_utils::balance_of(session, tokens[1], stable_swap); assert_eq!( From 83aecb8eb3f188c790fa348cce92de762933d3fd Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 3 Jul 2024 22:53:19 +0200 Subject: [PATCH 11/28] test rated wip --- .../src/stable_swap_tests/tests_rated.rs | 227 ++++++++++++------ 1 file changed, 149 insertions(+), 78 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs index 8731ea5..331c95d 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs @@ -8,30 +8,24 @@ use drink::{self, runtime::MinimalRuntime, session::Session}; use ink_primitives::AccountId; use ink_wrapper_types::{Connection, ToAccountId}; -const SAZERO_DEC: u8 = 12; const WAZERO_DEC: u8 = 12; +const SAZERO_DEC: u8 = 12; +const ONE_LPT: u128 = 10u128.pow(18); +const ONE_WAZERO: u128 = 10u128.pow(WAZERO_DEC as u32); const ONE_SAZERO: u128 = 10u128.pow(SAZERO_DEC as u32); -const ONE_AZERO: u128 = 10u128.pow(WAZERO_DEC as u32); - -const INIT_SUPPLY: u128 = 1_000_000; // 1M -const TRADE_FEE_BPS: u16 = 6; -const PROTOCOL_FEE_BPS: u16 = 2000; - -const AMP_COEF: u128 = 1000; +const EXPIRE_TS: u64 = 24 * 3600 * 1000; // 24h fn setup_rated_swap_with_tokens( session: &mut Session, - sazero: AccountId, - wazero: AccountId, + caller: drink::AccountId32, + initial_token_supply: u128, init_amp_coef: u128, rate_expiration_duration_ms: u64, - caller: drink::AccountId32, trade_fee: u16, protocol_fee: u16, - fee_receiver: Option, -) -> stable_pool_contract::Instance { +) -> (AccountId, AccountId, AccountId, AccountId) { //upload and deploy rate mock session .upload_code(stable_pool_contract::upload()) @@ -43,6 +37,21 @@ fn setup_rated_swap_with_tokens( let instance = mock_sazero_rate_contract::Instance::new(); + let wazero = psp22_utils::setup_with_amounts( + session, + "wAZERO".to_string(), + WAZERO_DEC, + initial_token_supply * ONE_WAZERO, + caller.clone(), + ); + let sazero = psp22_utils::setup_with_amounts( + session, + "SAZERO".to_string(), + SAZERO_DEC, + initial_token_supply * ONE_SAZERO, + caller.clone(), + ); + let rate_mock_address = session .instantiate(instance) .unwrap() @@ -50,7 +59,7 @@ fn setup_rated_swap_with_tokens( .to_account_id() .into(); let instance = stable_pool_contract::Instance::new_rated( - vec![sazero, wazero], + vec![sazero.into(), wazero.into()], vec![SAZERO_DEC, WAZERO_DEC], vec![Some(rate_mock_address), None], rate_expiration_duration_ms, @@ -58,104 +67,166 @@ fn setup_rated_swap_with_tokens( caller.to_account_id(), trade_fee, protocol_fee, - fee_receiver, + Some(fee_receiver()), ); - session + let rated_swap = session .instantiate(instance) .unwrap() .result .to_account_id() - .into() -} - -fn setup_all( - session: &mut Session, - _enable_protocol_fee: bool, -) -> (AccountId, AccountId, AccountId) { - upload_all(session); - - let wazero = psp22_utils::setup_with_amounts( - session, - "wAZERO".to_string(), - WAZERO_DEC, - INIT_SUPPLY * ONE_AZERO, - BOB, - ); - let sazero = psp22_utils::setup_with_amounts( - session, - "SAZERO".to_string(), - SAZERO_DEC, - INIT_SUPPLY * ONE_SAZERO, - BOB, - ); - let stable_pool_contract = setup_rated_swap_with_tokens( - session, - sazero.into(), - wazero.into(), - AMP_COEF, - 10000, //10 seconds rate cache expiration - BOB, - TRADE_FEE_BPS, - PROTOCOL_FEE_BPS, - Some(bob()), - ); + .into(); for token in [sazero, wazero] { psp22_utils::increase_allowance( session, token.into(), - stable_pool_contract.into(), + rated_swap, u128::MAX, - BOB, + caller.clone(), ) .unwrap(); } - (stable_pool_contract.into(), sazero.into(), wazero.into()) + (rated_swap, sazero.into(), wazero.into(), rate_mock_address) } +fn set_sazero_rate( + session: &mut Session, + mock_sazero_rate_contract: AccountId, + rate: u128, +) { + _ = handle_ink_error( + session + .execute( + mock_sazero_rate_contract::Instance::from(mock_sazero_rate_contract).set_rate(rate), + ) + .unwrap(), + ); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/tests/test_rated_pool.rs#L27 #[drink::test] fn test_01(mut session: Session) { - let one_minute: u64 = 60000; + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + let now = get_timestamp(&mut session); set_timestamp(&mut session, now); - upload_all(&mut session); - let (rated_swap, sazero, wazero) = setup_all(&mut session, false); + let initial_token_supply: u128 = 1_000_000_000; + let (rated_swap, sazero, wazero, mock_sazero_rate) = setup_rated_swap_with_tokens( + &mut session, + BOB, + initial_token_supply, + 10000, + EXPIRE_TS, + 25, + 2000, + ); + + set_timestamp(&mut session, now * EXPIRE_TS); + set_sazero_rate(&mut session, mock_sazero_rate, 2 * RATE_PRECISION); + _ = stable_swap::add_liquidity( &mut session, rated_swap.into(), BOB, 1, - vec![INIT_SUPPLY * ONE_SAZERO / 10, INIT_SUPPLY * ONE_AZERO / 10], + vec![50000 * ONE_SAZERO, 100000 * ONE_WAZERO], bob(), + ) + .expect("Should successfully swap. Err: {err:?}"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, bob()), + 200000 * ONE_LPT, + "Incorrect user share" ); - let amount = 10_000 * ONE_SAZERO; // 10k + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 200000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); - psp22_utils::increase_allowance( + transfer_and_increase_allowance( &mut session, - sazero.into(), - rated_swap.into(), - u128::MAX, + rated_swap, + vec![sazero, wazero], + CHARLIE, + vec![100000 * ONE_SAZERO, 100000 * ONE_WAZERO], BOB, + ); + _ = stable_swap::add_liquidity( + &mut session, + rated_swap.into(), + CHARLIE, + 1, + vec![50000 * ONE_SAZERO, 100000 * ONE_WAZERO], + charlie(), ) - .unwrap(); + .expect("Should successfully swap"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, charlie()), + 200000 * ONE_LPT, + "Incorrect user share" + ); + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 400000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); - set_timestamp(&mut session, now + 10000 * one_minute); - let (_amount_out, _fee) = handle_ink_error(stable_swap::swap_exact_in( + _ = stable_swap::remove_liquidity_by_shares( &mut session, rated_swap.into(), - BOB, - sazero.into(), - wazero.into(), - amount, - 1, // min_token_out - bob(), - )) - .unwrap_or_else(|err| panic!("Should return valid result. Err: {err:?}")); - - let reserves = stable_swap::reserves(&mut session, rated_swap.into()); - let balance_0 = psp22_utils::balance_of(&mut session, sazero.into(), rated_swap.into()); - let balance_1 = psp22_utils::balance_of(&mut session, wazero.into(), rated_swap.into()); - assert_eq!(reserves, vec![balance_0, balance_1]); + CHARLIE, + 200000 * ONE_LPT, + vec![1 * ONE_SAZERO, 1 * ONE_WAZERO], + charlie(), + ) + .expect("Should successfully swap"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, charlie()), + 0, + "Incorrect user share" + ); + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 200000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); + + // let err = stable_swap::remove_liquidity_by_shares( + // &mut session, + // rated_swap.into(), + // BOB, + // 200000 * ONE_LPT, + // vec![1 * ONE_SAZERO, 1 * ONE_WAZERO], + // bob(), + // ) + // .expect_err("Should return an error"); + + // assert_eq!( + // err, + // StablePoolError::MinReserve(), + // "Should return correct error" + // ) } From f59a452baae0e7fa5137ef0b6dfb8c89d07cf812 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Fri, 5 Jul 2024 13:21:51 +0200 Subject: [PATCH 12/28] fmt --- amm/drink-tests/src/lib.rs | 4 +- .../src/stable_swap_tests/tests_getters.rs | 2 +- amm/drink-tests/src/utils.rs | 40 ++++++++++--------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/amm/drink-tests/src/lib.rs b/amm/drink-tests/src/lib.rs index 0681550..d4a9d82 100644 --- a/amm/drink-tests/src/lib.rs +++ b/amm/drink-tests/src/lib.rs @@ -1,9 +1,9 @@ #[cfg(test)] -mod psp22; -#[cfg(test)] #[allow(unused_imports)] mod mock_sazero_rate_contract; #[cfg(test)] +mod psp22; +#[cfg(test)] mod stable_pool_contract; #[cfg(test)] mod stable_swap_tests; diff --git a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs index d8c12f3..c2d2828 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs @@ -126,4 +126,4 @@ fn test_01(mut session: Session) { 300000 * ONE_LPT + 498999996725367 + 498999993395420, // -- DIFF -- 300000 * ONE_LPT + 499999996666583 + 499999993277742 "Incorrect LP token supply" ); -} \ No newline at end of file +} diff --git a/amm/drink-tests/src/utils.rs b/amm/drink-tests/src/utils.rs index 9ae4ab7..a0a1d68 100644 --- a/amm/drink-tests/src/utils.rs +++ b/amm/drink-tests/src/utils.rs @@ -90,15 +90,17 @@ pub mod stable_swap { to: AccountId, ) -> Result<(u128, u128), StablePoolError> { _ = session.set_actor(caller); - handle_ink_error(session - .execute( - stable_pool_contract::Instance::from(stable_pool).add_liquidity( - min_share_amount, - amounts, - to, - ), - ) - .unwrap()) + handle_ink_error( + session + .execute( + stable_pool_contract::Instance::from(stable_pool).add_liquidity( + min_share_amount, + amounts, + to, + ), + ) + .unwrap(), + ) } pub fn remove_liquidity_by_amounts( @@ -110,15 +112,17 @@ pub mod stable_swap { to: AccountId, ) -> Result<(u128, u128), StablePoolError> { _ = session.set_actor(caller); - handle_ink_error(session - .execute( - stable_pool_contract::Instance::from(stable_pool).remove_liquidity_by_amounts( - max_share_amount, - amounts, - to, - ), - ) - .unwrap()) + handle_ink_error( + session + .execute( + stable_pool_contract::Instance::from(stable_pool).remove_liquidity_by_amounts( + max_share_amount, + amounts, + to, + ), + ) + .unwrap(), + ) } pub fn remove_liquidity_by_shares( From 07f687f606837c66926dafc3d0dc2a0927d8789d Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Fri, 5 Jul 2024 13:24:58 +0200 Subject: [PATCH 13/28] fix helper function --- amm/drink-tests/src/stable_swap_tests/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amm/drink-tests/src/stable_swap_tests/mod.rs b/amm/drink-tests/src/stable_swap_tests/mod.rs index d3eb393..df62165 100644 --- a/amm/drink-tests/src/stable_swap_tests/mod.rs +++ b/amm/drink-tests/src/stable_swap_tests/mod.rs @@ -121,7 +121,7 @@ pub fn share_price_and_total_shares( .checked_mul(100000000.into()) .unwrap() .checked_div(total_shares.into()) - .unwrap_or(100000000.into()) + .unwrap_or(0.into()) // return 0 if total shares 0 .as_u128(), total_shares, ) From d32778695c25190f6562c5ca097c4f0848f145a2 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Fri, 5 Jul 2024 13:28:45 +0200 Subject: [PATCH 14/28] test rated part 1 --- .../src/stable_swap_tests/tests_rated.rs | 486 +++++++++++++++--- 1 file changed, 424 insertions(+), 62 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs index 331c95d..cc0cfa1 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs @@ -17,51 +17,47 @@ const ONE_SAZERO: u128 = 10u128.pow(SAZERO_DEC as u32); const EXPIRE_TS: u64 = 24 * 3600 * 1000; // 24h +fn deploy_rate_provider(session: &mut Session, salt: Vec) -> AccountId { + let instance = mock_sazero_rate_contract::Instance::new().with_salt(salt); + session + .instantiate(instance) + .unwrap() + .result + .to_account_id() + .into() +} + fn setup_rated_swap_with_tokens( session: &mut Session, caller: drink::AccountId32, + rate_providers: Vec>, initial_token_supply: u128, init_amp_coef: u128, rate_expiration_duration_ms: u64, trade_fee: u16, protocol_fee: u16, -) -> (AccountId, AccountId, AccountId, AccountId) { - //upload and deploy rate mock - session - .upload_code(stable_pool_contract::upload()) - .expect("Upload stable_stable_pair_contract code"); - session - .upload_code(mock_sazero_rate_contract::upload()) - .expect("Upload sazero_rate_mock_contract code"); +) -> (AccountId, Vec) { let _ = session.set_actor(caller.clone()); - let instance = mock_sazero_rate_contract::Instance::new(); - - let wazero = psp22_utils::setup_with_amounts( - session, - "wAZERO".to_string(), - WAZERO_DEC, - initial_token_supply * ONE_WAZERO, - caller.clone(), - ); - let sazero = psp22_utils::setup_with_amounts( - session, - "SAZERO".to_string(), - SAZERO_DEC, - initial_token_supply * ONE_SAZERO, - caller.clone(), - ); + let tokens: Vec = rate_providers + .iter() + .enumerate() + .map(|(i, _)| { + psp22_utils::setup_with_amounts( + session, + format!("Token{i}"), + WAZERO_DEC, + initial_token_supply * ONE_WAZERO, + caller.clone(), + ) + .into() + }) + .collect(); - let rate_mock_address = session - .instantiate(instance) - .unwrap() - .result - .to_account_id() - .into(); let instance = stable_pool_contract::Instance::new_rated( - vec![sazero.into(), wazero.into()], - vec![SAZERO_DEC, WAZERO_DEC], - vec![Some(rate_mock_address), None], + tokens.clone(), + vec![WAZERO_DEC; rate_providers.len()], + rate_providers, rate_expiration_duration_ms, init_amp_coef, caller.to_account_id(), @@ -77,7 +73,7 @@ fn setup_rated_swap_with_tokens( .to_account_id() .into(); - for token in [sazero, wazero] { + for token in tokens.clone() { psp22_utils::increase_allowance( session, token.into(), @@ -88,19 +84,13 @@ fn setup_rated_swap_with_tokens( .unwrap(); } - (rated_swap, sazero.into(), wazero.into(), rate_mock_address) + (rated_swap, tokens) } -fn set_sazero_rate( - session: &mut Session, - mock_sazero_rate_contract: AccountId, - rate: u128, -) { +fn set_mock_rate(session: &mut Session, mock_rate_contract: AccountId, rate: u128) { _ = handle_ink_error( session - .execute( - mock_sazero_rate_contract::Instance::from(mock_sazero_rate_contract).set_rate(rate), - ) + .execute(mock_sazero_rate_contract::Instance::from(mock_rate_contract).set_rate(rate)) .unwrap(), ); } @@ -112,21 +102,26 @@ fn test_01(mut session: Session) { seed_account(&mut session, DAVE); seed_account(&mut session, EVA); + upload_all(&mut session); + let now = get_timestamp(&mut session); set_timestamp(&mut session, now); let initial_token_supply: u128 = 1_000_000_000; - let (rated_swap, sazero, wazero, mock_sazero_rate) = setup_rated_swap_with_tokens( + let mock_sazero_rate = deploy_rate_provider(&mut session, vec![0]); + let (rated_swap, tokens) = setup_rated_swap_with_tokens( &mut session, BOB, + vec![Some(mock_sazero_rate), None], initial_token_supply, 10000, EXPIRE_TS, 25, 2000, ); + let [sazero, wazero]: [AccountId; 2] = tokens.try_into().unwrap(); - set_timestamp(&mut session, now * EXPIRE_TS); - set_sazero_rate(&mut session, mock_sazero_rate, 2 * RATE_PRECISION); + set_timestamp(&mut session, now + EXPIRE_TS + 1); + set_mock_rate(&mut session, mock_sazero_rate, 2 * RATE_PRECISION); _ = stable_swap::add_liquidity( &mut session, @@ -136,7 +131,7 @@ fn test_01(mut session: Session) { vec![50000 * ONE_SAZERO, 100000 * ONE_WAZERO], bob(), ) - .expect("Should successfully swap. Err: {err:?}"); + .expect("Should successfully add LP"); assert_eq!( psp22_utils::balance_of(&mut session, rated_swap, bob()), 200000 * ONE_LPT, @@ -214,19 +209,386 @@ fn test_01(mut session: Session) { ); assert_eq!(last_share_price, 100000000, "Incorrect share price"); - // let err = stable_swap::remove_liquidity_by_shares( - // &mut session, - // rated_swap.into(), - // BOB, - // 200000 * ONE_LPT, - // vec![1 * ONE_SAZERO, 1 * ONE_WAZERO], - // bob(), - // ) - // .expect_err("Should return an error"); - - // assert_eq!( - // err, - // StablePoolError::MinReserve(), - // "Should return correct error" - // ) + // --- DIFF ---- + // Allow withdrawing all liquidity from the pool + + _ = stable_swap::remove_liquidity_by_shares( + &mut session, + rated_swap.into(), + BOB, + 200000 * ONE_LPT, + vec![1 * ONE_SAZERO, 1 * ONE_WAZERO], + bob(), + ) + .expect("Should successfully remove liquidity"); + + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, bob()), + 0, + "Incorrect user share" + ); + + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), + ); + + // no shares left + assert_eq!(last_total_shares, 0, "Incorrect total shares"); + assert_eq!(last_share_price, 0, "Incorrect share price"); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/tests/test_rated_pool.rs#L116 +#[drink::test] +fn test_02(mut session: Session) { + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + + upload_all(&mut session); + + let now = get_timestamp(&mut session); + set_timestamp(&mut session, now); + let mock_token_2_rate = deploy_rate_provider(&mut session, vec![0]); + + let initial_token_supply: u128 = 1_000_000_000; + let (rated_swap, tokens) = setup_rated_swap_with_tokens( + &mut session, + BOB, + vec![None, Some(mock_token_2_rate), None], + initial_token_supply, + 10000, + EXPIRE_TS, + 25, + 2000, + ); + + set_timestamp(&mut session, now + EXPIRE_TS); + set_mock_rate(&mut session, mock_token_2_rate, 2 * RATE_PRECISION); + + _ = stable_swap::add_liquidity( + &mut session, + rated_swap.into(), + BOB, + 1, + vec![100000 * ONE_WAZERO, 50000 * ONE_WAZERO, 100000 * ONE_WAZERO], + bob(), + ) + .expect("Should successfully add LP"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, bob()), + 300000 * ONE_LPT, + "Incorrect user share" + ); + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 300000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); + + transfer_and_increase_allowance( + &mut session, + rated_swap, + tokens, + CHARLIE, + vec![ + 100000 * ONE_WAZERO, + 100000 * ONE_WAZERO, + 100000 * ONE_WAZERO, + ], + BOB, + ); + _ = stable_swap::add_liquidity( + &mut session, + rated_swap.into(), + CHARLIE, + 1, + vec![100000 * ONE_WAZERO, 50000 * ONE_WAZERO, 100000 * ONE_WAZERO], + charlie(), + ) + .expect("Should successfully add LP"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, charlie()), + 300000 * ONE_LPT, + "Incorrect user share" + ); + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 600000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); + + _ = stable_swap::remove_liquidity_by_shares( + &mut session, + rated_swap.into(), + CHARLIE, + 300000 * ONE_LPT, + vec![1 * ONE_WAZERO, 1 * ONE_WAZERO, 1 * ONE_WAZERO], + charlie(), + ) + .expect("Should successfully remove LP"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, charlie()), + 0, + "Incorrect user share" + ); + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 300000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/tests/test_rated_pool.rs#L197 +#[drink::test] +fn test_03(mut session: Session) { + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + + upload_all(&mut session); + + let now = get_timestamp(&mut session); + set_timestamp(&mut session, now); + let mock_token_2_rate = deploy_rate_provider(&mut session, vec![0]); + let mock_token_3_rate = deploy_rate_provider(&mut session, vec![1]); + + let initial_token_supply: u128 = 1_000_000_000; + let (rated_swap, tokens) = setup_rated_swap_with_tokens( + &mut session, + BOB, + vec![None, Some(mock_token_2_rate), Some(mock_token_3_rate)], + initial_token_supply, + 10000, + EXPIRE_TS, + 25, + 2000, + ); + + set_timestamp(&mut session, now + EXPIRE_TS); + set_mock_rate(&mut session, mock_token_2_rate, 2 * RATE_PRECISION); + set_mock_rate(&mut session, mock_token_3_rate, 4 * RATE_PRECISION); + + _ = stable_swap::add_liquidity( + &mut session, + rated_swap.into(), + BOB, + 1, + vec![100000 * ONE_WAZERO, 50000 * ONE_WAZERO, 25000 * ONE_WAZERO], + bob(), + ) + .expect("Should successfully add LP"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, bob()), + 300000 * ONE_LPT, + "Incorrect user share" + ); + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, 4 * RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 300000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); + + transfer_and_increase_allowance( + &mut session, + rated_swap, + tokens, + CHARLIE, + vec![ + 100000 * ONE_WAZERO, + 100000 * ONE_WAZERO, + 100000 * ONE_WAZERO, + ], + BOB, + ); + + _ = stable_swap::add_liquidity( + &mut session, + rated_swap.into(), + CHARLIE, + 1, + vec![100000 * ONE_WAZERO, 50000 * ONE_WAZERO, 25000 * ONE_WAZERO], + charlie(), + ) + .expect("Should successfully add LP"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, charlie()), + 300000 * ONE_LPT, + "Incorrect user share" + ); + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, 4 * RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 600000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); + + _ = stable_swap::remove_liquidity_by_shares( + &mut session, + rated_swap.into(), + CHARLIE, + 300000 * ONE_LPT, + vec![1 * ONE_WAZERO, 1 * ONE_WAZERO, 1 * ONE_WAZERO], + charlie(), + ) + .expect("Should successfully remove LP"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, charlie()), + 0, + "Incorrect user share" + ); + let (last_share_price, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, 4 * RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 300000 * ONE_LPT, + "Incorrect total shares" + ); + assert_eq!(last_share_price, 100000000, "Incorrect share price"); +} + +// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/tests/test_rated_pool.rs#L303 +#[drink::test] +fn test_04(mut session: Session) { + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + + upload_all(&mut session); + + let initial_token_supply: u128 = 1_000_000_000; + let (rated_swap, tokens) = setup_rated_swap_with_tokens( + &mut session, + BOB, + vec![None, None], + initial_token_supply, + 10000, + EXPIRE_TS, + 25, + 2000, + ); + + _ = stable_swap::add_liquidity( + &mut session, + rated_swap.into(), + BOB, + 1, + vec![100000 * ONE_WAZERO, 100000 * ONE_WAZERO], + bob(), + ) + .expect("Should successfully add LP"); + assert_eq!( + psp22_utils::balance_of(&mut session, rated_swap, bob()), + 200000 * ONE_LPT, + "Incorrect user share" + ); + let (_, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![RATE_PRECISION, RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 200000 * ONE_LPT, + "Incorrect total shares" + ); + + assert_eq!( + psp22_utils::balance_of(&mut session, tokens[0], charlie()), + 0, + "Incorrect user token balance" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, tokens[1], charlie()), + 0, + "Incorrect user token balance" + ); + transfer_and_increase_allowance( + &mut session, + rated_swap, + tokens.clone(), + CHARLIE, + vec![ONE_WAZERO, 0], + BOB, + ); + assert_eq!( + psp22_utils::balance_of(&mut session, tokens[0], charlie()), + ONE_WAZERO, + "Incorrect user token balance" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, tokens[1], charlie()), + 0, + "Incorrect user token balance" + ); + let (amount_out, fee) = stable_swap::swap_exact_in( + &mut session, + rated_swap.into(), + CHARLIE, + tokens[0], + tokens[1], + ONE_WAZERO, + 1, + charlie(), + ) + .expect("Should swap"); + assert_eq!( + psp22_utils::balance_of(&mut session, tokens[0], charlie()), + 0, + "Incorrect user token balance" + ); + assert_eq!( + psp22_utils::balance_of(&mut session, tokens[1], charlie()), + 997499999501, + "Incorrect user token balance" + ); + + let (_, last_total_shares) = share_price_and_total_shares( + &mut session, + rated_swap, + Some(vec![RATE_PRECISION, RATE_PRECISION]), + ); + assert_eq!( + last_total_shares, + 200000 * ONE_LPT + 499999994249708, // -- DIFF -- 499999994999720 [058346] + "Incorrect total shares" + ); + assert_eq!( + stable_swap::reserves(&mut session, rated_swap), + vec![100001 * ONE_WAZERO, 99999 * ONE_WAZERO + 2500000499], + "Incorrect reserves" + ); } From bfe42bbae46dfdf9140e467cdc2184f07f16c9a5 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Fri, 5 Jul 2024 13:49:29 +0200 Subject: [PATCH 15/28] extract initial variables --- .../stable_swap_tests/tests_add_remove_lp.rs | 11 +++++----- .../src/stable_swap_tests/tests_getters.rs | 21 ++++++++++++------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index df59c2d..2b1adc1 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -9,13 +9,14 @@ fn test_01(mut session: Session) { seed_account(&mut session, DAVE); seed_account(&mut session, EVA); let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; + let initial_supply = initial_reserves + .iter() + .map(|amount| amount * 100_000_000_000) + .collect(); let (stable_swap, tokens) = setup_stable_swap_with_tokens( &mut session, vec![18, 6, 6], - initial_reserves - .iter() - .map(|amount| amount * 100_000_000_000) - .collect(), + initial_supply, 10_000, 25, 2000, @@ -200,7 +201,7 @@ fn test_01(mut session: Session) { let last_share_price = current_share_price; let last_total_shares = last_total_shares - 502598511257512352631 + 119779860286480103; - // tansfer some LPT to from charlie to dave + // transfer some LPT to from charlie to dave _ = psp22_utils::transfer(&mut session, stable_swap, dave(), 100 * ONE_LPT, CHARLIE); assert_eq!( diff --git a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs index c2d2828..cbdb90f 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs @@ -4,13 +4,17 @@ use super::*; #[drink::test] fn test_01(mut session: Session) { let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; + let initial_supply: Vec = initial_reserves.iter().map(|amount| amount * 10).collect(); + let amp_coef = 10_000u128; + let trade_fee = 25u16; + let protocol_fee = 2000u16; let (stable_swap, tokens) = setup_stable_swap_with_tokens( &mut session, vec![18, 6, 6], - initial_reserves.iter().map(|amount| amount * 10).collect(), - 10_000, - 25, - 2000, + initial_supply.clone(), + amp_coef, + trade_fee, + protocol_fee, BOB, ); @@ -36,12 +40,12 @@ fn test_01(mut session: Session) { ); assert_eq!( stable_swap::amp_coef(&mut session, stable_swap), - 10_000, + amp_coef, "Incorrect A" ); assert_eq!( stable_swap::fees(&mut session, stable_swap), - (25, 2000), + (trade_fee, protocol_fee), "Incorrect fees" ); assert_eq!( @@ -61,9 +65,10 @@ fn test_01(mut session: Session) { .collect(); assert_eq!( balances, - initial_reserves + initial_supply .iter() - .map(|amount| amount * 9) + .zip(initial_reserves) + .map(|(init_token_supply, init_reserve)| init_token_supply - init_reserve) .collect::>(), "Incorrect Users tokens balances" ); From 1250be937d6a754bd5a9d6305159d16203df5e66 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Fri, 5 Jul 2024 17:29:51 +0200 Subject: [PATCH 16/28] tests withdrawing all liquidity --- .../stable_swap_tests/tests_add_remove_lp.rs | 447 +++++++++++++++++- 1 file changed, 443 insertions(+), 4 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index 2b1adc1..9ce64c0 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -1,4 +1,5 @@ use drink::{self, session::Session}; +use stable_pool_contract::MathError; use super::*; @@ -12,11 +13,11 @@ fn test_01(mut session: Session) { let initial_supply = initial_reserves .iter() .map(|amount| amount * 100_000_000_000) - .collect(); + .collect::>(); let (stable_swap, tokens) = setup_stable_swap_with_tokens( &mut session, vec![18, 6, 6], - initial_supply, + initial_supply.clone(), 10_000, 25, 2000, @@ -81,7 +82,7 @@ fn test_01(mut session: Session) { let balances: Vec = tokens .iter() .map(|&token| psp22_utils::balance_of(&mut session, token, charlie())) - .collect(); + .collect::>(); assert_eq!( balances, vec![100 * ONE_DAI, 100 * ONE_USDT, 100 * ONE_USDC], @@ -166,7 +167,7 @@ fn test_01(mut session: Session) { let balances: Vec = tokens .iter() .map(|&token| psp22_utils::balance_of(&mut session, token, charlie())) - .collect(); + .collect::>(); assert_eq!( balances, vec![101 * ONE_DAI, 600 * ONE_USDT, 101 * ONE_USDC], @@ -399,3 +400,441 @@ fn test_01(mut session: Session) { "Incorrect total shares" ); } + +/// Test withdrawing all liquidity with all shares +#[drink::test] +fn test_02(mut session: Session) { + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + + let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; + let initial_supply = initial_reserves + .iter() + .map(|amount| amount * 100_000_000_000) + .collect::>(); + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![18, 6, 6], + initial_supply.clone(), + 10_000, + 25, + 2000, + BOB, + ); + + _ = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + // remove by shares + _ = stable_swap::remove_liquidity_by_shares( + &mut session, + stable_swap, + BOB, + 300000 * ONE_LPT, + vec![1 * ONE_DAI, 1 * ONE_USDT, 1 * ONE_USDC], + bob(), + ) + .expect("Should successfully remove liquidity"); + + assert_eq!(psp22_utils::balance_of(&mut session, stable_swap, bob()), 0); + assert_eq!(psp22_utils::total_supply(&mut session, stable_swap), 0); + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, bob())) + .collect::>(); + assert_eq!(balances, initial_supply, "Incorrect Users tokens balances"); +} + +/// Test withdrawing all liquidity by amounts +#[drink::test] +fn test_03(mut session: Session) { + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + + let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; + let initial_supply = initial_reserves + .iter() + .map(|amount| amount * 100_000_000_000) + .collect::>(); + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![18, 6, 6], + initial_supply.clone(), + 10_000, + 25, + 2000, + BOB, + ); + + _ = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + _ = stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + BOB, + 300000 * ONE_LPT, + initial_reserves, + bob(), + ) + .expect("Should successfully remove liquidity"); + + assert_eq!(psp22_utils::balance_of(&mut session, stable_swap, bob()), 0); + assert_eq!(psp22_utils::total_supply(&mut session, stable_swap), 0); + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, bob())) + .collect::>(); + assert_eq!(balances, initial_supply, "Incorrect Users tokens balances"); +} + +/// Test withdrawing all liquidity with shares - 1 +#[drink::test] +fn test_04(mut session: Session) { + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + + let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; + let initial_supply = initial_reserves + .iter() + .map(|amount| amount * 100_000_000_000) + .collect::>(); + let initial_supply_sub_reserves = initial_supply + .iter() + .zip(initial_reserves.iter()) + .map(|(supply, reserve)| supply - reserve) + .collect::>(); + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![18, 6, 6], + initial_supply.clone(), + 10_000, + 25, + 2000, + BOB, + ); + + _ = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + let err = stable_swap::remove_liquidity_by_shares( + &mut session, + stable_swap, + BOB, + 300000 * ONE_LPT - 1, + initial_reserves.clone(), + bob(), + ) + .expect_err("Liquidity withdraw should fail"); + assert_eq!( + err, + StablePoolError::InsufficientOutputAmount(), + "Should return appropriate error" + ); + + let err = stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + BOB, + 300000 * ONE_LPT - 1, + initial_reserves, + bob(), + ) + .expect_err("Liquidity withdraw should fail"); + assert_eq!( + err, + StablePoolError::InsufficientLiquidityBurned(), + "Should return appropriate error" + ); + + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, bob()), + 300000 * ONE_LPT + ); + assert_eq!( + psp22_utils::total_supply(&mut session, stable_swap), + 300000 * ONE_LPT + ); + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, bob())) + .collect::>(); + assert_eq!( + balances, initial_supply_sub_reserves, + "Incorrect Users tokens balances" + ); +} + +/// Test withdrawing single token whole reserve +#[drink::test] +fn test_05(mut session: Session) { + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + + let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; + let initial_supply = initial_reserves + .iter() + .map(|amount| amount * 100_000_000_000) + .collect::>(); + let initial_supply_sub_reserves = initial_supply + .iter() + .zip(initial_reserves.iter()) + .map(|(supply, reserve)| supply - reserve) + .collect::>(); + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![18, 6, 6], + initial_supply.clone(), + 10_000, + 25, + 2000, + BOB, + ); + + _ = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + let err = stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + BOB, + 300000 * ONE_LPT, + vec![initial_reserves[0], 0, 0], + bob(), + ) + .expect_err("Liquidity withdraw should fail"); + + assert_eq!( + err, + StablePoolError::MathError(MathError::DivByZero(1)), + "Should return appropriate error" + ); + + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, bob()), + 300000 * ONE_LPT + ); + assert_eq!( + psp22_utils::total_supply(&mut session, stable_swap), + 300000 * ONE_LPT + ); + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, bob())) + .collect::>(); + assert_eq!( + balances, initial_supply_sub_reserves, + "Incorrect Users tokens balances" + ); +} + +/// Test withdrawing all liquidity with shares - 1 (with different initial reserves) +#[drink::test] +fn test_06(mut session: Session) { + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + + let initial_reserves = vec![543257 * ONE_DAI, 123123 * ONE_USDT, 32178139 * ONE_USDC]; + let initial_supply = initial_reserves + .iter() + .map(|amount| amount * 100_000_000_000) + .collect::>(); + let initial_supply_sub_reserves = initial_supply + .iter() + .zip(initial_reserves.iter()) + .map(|(supply, reserve)| supply - reserve) + .collect::>(); + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![18, 6, 6], + initial_supply.clone(), + 10_000, + 25, + 2000, + BOB, + ); + + let (shares, _) = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + let err = stable_swap::remove_liquidity_by_shares( + &mut session, + stable_swap, + BOB, + shares - 1, + initial_reserves.clone(), + bob(), + ) + .expect_err("Liquidity withdraw should fail"); + assert_eq!( + err, + StablePoolError::InsufficientOutputAmount(), + "Should return appropriate error" + ); + + let err = stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + BOB, + shares - 1, + initial_reserves, + bob(), + ) + .expect_err("Liquidity withdraw should fail"); + assert_eq!( + err, + StablePoolError::InsufficientLiquidityBurned(), + "Should return appropriate error" + ); + + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, bob()), + shares + ); + assert_eq!(psp22_utils::total_supply(&mut session, stable_swap), shares); + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, bob())) + .collect::>(); + assert_eq!( + balances, initial_supply_sub_reserves, + "Incorrect Users tokens balances" + ); +} + +/// Test withdrawing single token whole reserve (with different initial reserves) +#[drink::test] +fn test_07(mut session: Session) { + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + + let initial_reserves = vec![543257 * ONE_DAI, 123123 * ONE_USDT, 32178139 * ONE_USDC]; + let initial_supply = initial_reserves + .iter() + .map(|amount| amount * 100_000_000_000) + .collect::>(); + let initial_supply_sub_reserves = initial_supply + .iter() + .zip(initial_reserves.iter()) + .map(|(supply, reserve)| supply - reserve) + .collect::>(); + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![18, 6, 6], + initial_supply.clone(), + 10_000, + 25, + 2000, + BOB, + ); + + let (shares, _) = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + let err = stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + BOB, + shares, + vec![initial_reserves[0], 0, 0], + bob(), + ) + .expect_err("Liquidity withdraw should fail"); + assert_eq!( + err, + StablePoolError::MathError(MathError::DivByZero(1)), + "Should return appropriate error" + ); + + let err = stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + BOB, + shares, + vec![0, initial_reserves[1], 0], + bob(), + ) + .expect_err("Liquidity withdraw should fail"); + assert_eq!( + err, + StablePoolError::MathError(MathError::DivByZero(1)), + "Should return appropriate error" + ); + + let err = stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + BOB, + shares, + vec![0, 0, initial_reserves[2]], + bob(), + ) + .expect_err("Liquidity withdraw should fail"); + assert_eq!( + err, + StablePoolError::MathError(MathError::DivByZero(1)), + "Should return appropriate error" + ); + + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, bob()), + shares + ); + assert_eq!(psp22_utils::total_supply(&mut session, stable_swap), shares); + let balances: Vec = tokens + .iter() + .map(|&token| psp22_utils::balance_of(&mut session, token, bob())) + .collect::>(); + assert_eq!( + balances, initial_supply_sub_reserves, + "Incorrect Users tokens balances" + ); +} From e42549a0b2127bcff0a31f1bf856ca15f2fc68e6 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Sat, 6 Jul 2024 10:37:52 +0200 Subject: [PATCH 17/28] simplify share price helper --- amm/drink-tests/src/stable_swap_tests/mod.rs | 8 +- .../stable_swap_tests/tests_add_remove_lp.rs | 20 ++--- .../src/stable_swap_tests/tests_rated.rs | 85 ++++++------------- amm/drink-tests/src/utils.rs | 8 ++ 4 files changed, 44 insertions(+), 77 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/mod.rs b/amm/drink-tests/src/stable_swap_tests/mod.rs index df62165..38f32b2 100644 --- a/amm/drink-tests/src/stable_swap_tests/mod.rs +++ b/amm/drink-tests/src/stable_swap_tests/mod.rs @@ -96,15 +96,11 @@ pub fn setup_stable_swap_with_tokens( pub fn share_price_and_total_shares( session: &mut Session, stable_swap: AccountId, - token_rates: Option>, ) -> (u128, u128) { let total_shares = psp22_utils::total_supply(session, stable_swap); let reserves = stable_swap::reserves(session, stable_swap); - let token_rates: Vec = if let Some(rates) = token_rates { - rates - } else { - reserves.iter().map(|_| RATE_PRECISION).collect() - }; + let token_rates = stable_swap::token_rates(session, stable_swap); + let sum_token = stable_swap::tokens(session, stable_swap) .iter() .zip(reserves.iter()) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index 9ce64c0..d2ac6c9 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -35,7 +35,7 @@ fn test_01(mut session: Session) { .expect("Should successfully add liquidity"); let (last_share_price, last_total_shares) = - share_price_and_total_shares(&mut session, stable_swap, None); + share_price_and_total_shares(&mut session, stable_swap); transfer_and_increase_allowance( &mut session, @@ -58,7 +58,7 @@ fn test_01(mut session: Session) { .expect("Should successfully add liquidity"); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap, None), + share_price_and_total_shares(&mut session, stable_swap), (last_share_price, last_total_shares + 1500 * ONE_LPT) ); @@ -89,7 +89,7 @@ fn test_01(mut session: Session) { "Incorrect Users tokens balances" ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap, None), + share_price_and_total_shares(&mut session, stable_swap), (last_share_price, last_total_shares - 300 * ONE_LPT) ); let last_total_shares = last_total_shares - 300 * ONE_LPT; @@ -133,7 +133,7 @@ fn test_01(mut session: Session) { ); let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap, None); + share_price_and_total_shares(&mut session, stable_swap); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -194,7 +194,7 @@ fn test_01(mut session: Session) { 699699997426210330025, "Incorrect users share" ); - let (current_share_price, _) = share_price_and_total_shares(&mut session, stable_swap, None); + let (current_share_price, _) = share_price_and_total_shares(&mut session, stable_swap); assert!( current_share_price > last_share_price, "Incorrect share price" @@ -217,7 +217,7 @@ fn test_01(mut session: Session) { ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap, None), + share_price_and_total_shares(&mut session, stable_swap), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); @@ -240,7 +240,7 @@ fn test_01(mut session: Session) { ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap, None), + share_price_and_total_shares(&mut session, stable_swap), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); @@ -263,7 +263,7 @@ fn test_01(mut session: Session) { ); assert_eq!( - share_price_and_total_shares(&mut session, stable_swap, None), + share_price_and_total_shares(&mut session, stable_swap), (last_share_price, last_total_shares), "Incorrect share price and/or total shares" ); @@ -304,7 +304,7 @@ fn test_01(mut session: Session) { ); let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap, None); + share_price_and_total_shares(&mut session, stable_swap); assert_eq!( current_share_price, last_share_price, "Incorrect share price" @@ -344,7 +344,7 @@ fn test_01(mut session: Session) { let last_total_shares = last_total_shares - 498596320224035614380 + 119500087140112295; let (current_share_price, current_total_shares) = - share_price_and_total_shares(&mut session, stable_swap, None); + share_price_and_total_shares(&mut session, stable_swap); assert!( current_share_price > last_share_price, "Incorrect share price" diff --git a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs index cc0cfa1..2f61d16 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs @@ -137,11 +137,8 @@ fn test_01(mut session: Session) { 200000 * ONE_LPT, "Incorrect user share" ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), - ); + let (last_share_price, last_total_shares) = + share_price_and_total_shares(&mut session, rated_swap); assert_eq!( last_total_shares, 200000 * ONE_LPT, @@ -171,11 +168,8 @@ fn test_01(mut session: Session) { 200000 * ONE_LPT, "Incorrect user share" ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), - ); + let (last_share_price, last_total_shares) = + share_price_and_total_shares(&mut session, rated_swap); assert_eq!( last_total_shares, 400000 * ONE_LPT, @@ -197,11 +191,8 @@ fn test_01(mut session: Session) { 0, "Incorrect user share" ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), - ); + let (last_share_price, last_total_shares) = + share_price_and_total_shares(&mut session, rated_swap); assert_eq!( last_total_shares, 200000 * ONE_LPT, @@ -228,11 +219,8 @@ fn test_01(mut session: Session) { "Incorrect user share" ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![2 * RATE_PRECISION, RATE_PRECISION]), - ); + let (last_share_price, last_total_shares) = + share_price_and_total_shares(&mut session, rated_swap); // no shares left assert_eq!(last_total_shares, 0, "Incorrect total shares"); @@ -281,11 +269,8 @@ fn test_02(mut session: Session) { 300000 * ONE_LPT, "Incorrect user share" ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, RATE_PRECISION]), - ); + let (last_share_price, last_total_shares) = + share_price_and_total_shares(&mut session, rated_swap); assert_eq!( last_total_shares, 300000 * ONE_LPT, @@ -319,11 +304,8 @@ fn test_02(mut session: Session) { 300000 * ONE_LPT, "Incorrect user share" ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, RATE_PRECISION]), - ); + let (last_share_price, last_total_shares) = + share_price_and_total_shares(&mut session, rated_swap); assert_eq!( last_total_shares, 600000 * ONE_LPT, @@ -345,11 +327,8 @@ fn test_02(mut session: Session) { 0, "Incorrect user share" ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, RATE_PRECISION]), - ); + let (last_share_price, last_total_shares) = + share_price_and_total_shares(&mut session, rated_swap); assert_eq!( last_total_shares, 300000 * ONE_LPT, @@ -402,11 +381,8 @@ fn test_03(mut session: Session) { 300000 * ONE_LPT, "Incorrect user share" ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, 4 * RATE_PRECISION]), - ); + let (last_share_price, last_total_shares) = + share_price_and_total_shares(&mut session, rated_swap); assert_eq!( last_total_shares, 300000 * ONE_LPT, @@ -441,11 +417,8 @@ fn test_03(mut session: Session) { 300000 * ONE_LPT, "Incorrect user share" ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, 4 * RATE_PRECISION]), - ); + let (last_share_price, last_total_shares) = + share_price_and_total_shares(&mut session, rated_swap); assert_eq!( last_total_shares, 600000 * ONE_LPT, @@ -467,11 +440,8 @@ fn test_03(mut session: Session) { 0, "Incorrect user share" ); - let (last_share_price, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![RATE_PRECISION, 2 * RATE_PRECISION, 4 * RATE_PRECISION]), - ); + let (last_share_price, last_total_shares) = + share_price_and_total_shares(&mut session, rated_swap); assert_eq!( last_total_shares, 300000 * ONE_LPT, @@ -515,11 +485,7 @@ fn test_04(mut session: Session) { 200000 * ONE_LPT, "Incorrect user share" ); - let (_, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![RATE_PRECISION, RATE_PRECISION]), - ); + let (_, last_total_shares) = share_price_and_total_shares(&mut session, rated_swap); assert_eq!( last_total_shares, 200000 * ONE_LPT, @@ -554,7 +520,8 @@ fn test_04(mut session: Session) { 0, "Incorrect user token balance" ); - let (amount_out, fee) = stable_swap::swap_exact_in( + + _ = stable_swap::swap_exact_in( &mut session, rated_swap.into(), CHARLIE, @@ -576,11 +543,7 @@ fn test_04(mut session: Session) { "Incorrect user token balance" ); - let (_, last_total_shares) = share_price_and_total_shares( - &mut session, - rated_swap, - Some(vec![RATE_PRECISION, RATE_PRECISION]), - ); + let (_, last_total_shares) = share_price_and_total_shares(&mut session, rated_swap); assert_eq!( last_total_shares, 200000 * ONE_LPT + 499999994249708, // -- DIFF -- 499999994999720 [058346] diff --git a/amm/drink-tests/src/utils.rs b/amm/drink-tests/src/utils.rs index a0a1d68..589663d 100644 --- a/amm/drink-tests/src/utils.rs +++ b/amm/drink-tests/src/utils.rs @@ -247,6 +247,14 @@ pub mod stable_swap { ) } + pub fn token_rates(session: &mut Session, stable_pool: AccountId) -> Vec { + handle_ink_error( + session + .query(stable_pool_contract::Instance::from(stable_pool).token_rates()) + .unwrap(), + ) + } + pub fn tokens(session: &mut Session, stable_pool: AccountId) -> Vec { handle_ink_error( session From d6a668ece913a7ea5eb5ee1d18ad549774e89107 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Tue, 9 Jul 2024 15:34:06 +0200 Subject: [PATCH 18/28] adjust fees to new precision --- .../stable_swap_tests/tests_add_remove_lp.rs | 30 +++++------ .../src/stable_swap_tests/tests_getters.rs | 4 +- .../src/stable_swap_tests/tests_rated.rs | 20 +++---- .../stable_swap_tests/tests_swap_exact_in.rs | 32 ++++++------ .../stable_swap_tests/tests_swap_received.rs | 52 +++++++++---------- 5 files changed, 69 insertions(+), 69 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index d2ac6c9..57a2cb1 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -19,8 +19,8 @@ fn test_01(mut session: Session) { vec![18, 6, 6], initial_supply.clone(), 10_000, - 25, - 2000, + 2_500_000, + 200_000_000, BOB, ); @@ -104,7 +104,7 @@ fn test_01(mut session: Session) { ); // add more liquidity with imbalanced tokens (dave) - _ = stable_swap::add_liquidity( + let res = stable_swap::add_liquidity( &mut session, stable_swap, DAVE, @@ -418,8 +418,8 @@ fn test_02(mut session: Session) { vec![18, 6, 6], initial_supply.clone(), 10_000, - 25, - 2000, + 2_500_000, + 200_000_000, BOB, ); @@ -470,8 +470,8 @@ fn test_03(mut session: Session) { vec![18, 6, 6], initial_supply.clone(), 10_000, - 25, - 2000, + 2_500_000, + 200_000_000, BOB, ); @@ -526,8 +526,8 @@ fn test_04(mut session: Session) { vec![18, 6, 6], initial_supply.clone(), 10_000, - 25, - 2000, + 2_500_000, + 200_000_000, BOB, ); @@ -611,8 +611,8 @@ fn test_05(mut session: Session) { vec![18, 6, 6], initial_supply.clone(), 10_000, - 25, - 2000, + 2_500_000, + 200_000_000, BOB, ); @@ -682,8 +682,8 @@ fn test_06(mut session: Session) { vec![18, 6, 6], initial_supply.clone(), 10_000, - 25, - 2000, + 2_500_000, + 200_000_000, BOB, ); @@ -764,8 +764,8 @@ fn test_07(mut session: Session) { vec![18, 6, 6], initial_supply.clone(), 10_000, - 25, - 2000, + 2_500_000, + 200_000_000, BOB, ); diff --git a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs index cbdb90f..e476ab1 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs @@ -6,8 +6,8 @@ fn test_01(mut session: Session) { let initial_reserves = vec![100000 * ONE_DAI, 100000 * ONE_USDT, 100000 * ONE_USDC]; let initial_supply: Vec = initial_reserves.iter().map(|amount| amount * 10).collect(); let amp_coef = 10_000u128; - let trade_fee = 25u16; - let protocol_fee = 2000u16; + let trade_fee = 2_500_000u32; + let protocol_fee = 200_000_000u32; let (stable_swap, tokens) = setup_stable_swap_with_tokens( &mut session, vec![18, 6, 6], diff --git a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs index 2f61d16..8d026b1 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs @@ -34,8 +34,8 @@ fn setup_rated_swap_with_tokens( initial_token_supply: u128, init_amp_coef: u128, rate_expiration_duration_ms: u64, - trade_fee: u16, - protocol_fee: u16, + trade_fee: u32, + protocol_fee: u32, ) -> (AccountId, Vec) { let _ = session.set_actor(caller.clone()); @@ -115,8 +115,8 @@ fn test_01(mut session: Session) { initial_token_supply, 10000, EXPIRE_TS, - 25, - 2000, + 2_500_000, + 200_000_000, ); let [sazero, wazero]: [AccountId; 2] = tokens.try_into().unwrap(); @@ -248,8 +248,8 @@ fn test_02(mut session: Session) { initial_token_supply, 10000, EXPIRE_TS, - 25, - 2000, + 2_500_000, + 200_000_000, ); set_timestamp(&mut session, now + EXPIRE_TS); @@ -359,8 +359,8 @@ fn test_03(mut session: Session) { initial_token_supply, 10000, EXPIRE_TS, - 25, - 2000, + 2_500_000, + 200_000_000, ); set_timestamp(&mut session, now + EXPIRE_TS); @@ -467,8 +467,8 @@ fn test_04(mut session: Session) { initial_token_supply, 10000, EXPIRE_TS, - 25, - 2000, + 2_500_000, + 200_000_000, ); _ = stable_swap::add_liquidity( diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs index 1b72056..bdf2a8f 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs @@ -8,8 +8,8 @@ fn test_swap_exact_in( token_decimals: Vec, initial_reserves: Vec, amp_coef: u128, - fee_bps: u16, - protocol_fee_bps: u16, + trade_fee: u32, + protocol_fee: u32, swap_amount_in: u128, expected_swap_amount_out_total_result: Result, ) { @@ -19,8 +19,8 @@ fn test_swap_exact_in( token_decimals, initial_supply, amp_coef, - fee_bps, - protocol_fee_bps, + trade_fee, + protocol_fee, BOB, ); _ = stable_swap::add_liquidity( @@ -56,9 +56,9 @@ fn test_swap_exact_in( let (amount_out, fee) = swap_result.unwrap(); let expected_swap_amount_out_total = expected_swap_amount_out_total_result.unwrap(); - let expected_fee = expected_swap_amount_out_total * fee_bps as u128 / FEE_BPS_DENOM; + let expected_fee = expected_swap_amount_out_total * trade_fee as u128 / FEE_DENOM; let expected_swap_amount_out = expected_swap_amount_out_total - expected_fee; - let expected_protocol_fee_part = expected_fee * protocol_fee_bps as u128 / FEE_BPS_DENOM; + let expected_protocol_fee_part = expected_fee * protocol_fee as u128 / FEE_DENOM; // check returned amount swapped and fee assert_eq!(expected_swap_amount_out, amount_out, "Amount out mismatch"); @@ -119,7 +119,7 @@ fn test_01(mut session: Session) { vec![6, 6], // decimals vec![100000000000, 100000000000], // initial reserves 1000, // A - 6, // fee BPS + 600_000, // fee BPS 2000, // protocol fee BPS 10000000000, // swap_amount_in Ok(9999495232), // expected out (with fee) @@ -134,7 +134,7 @@ fn test_02(mut session: Session) { vec![12, 18], vec![100000000000000000, 100000000000000000000000], 1000, - 6, + 600_000, 2000, 10000000000000000, Ok(9999495232752197989995), @@ -149,7 +149,7 @@ fn test_03(mut session: Session) { vec![6, 6], vec![100000000000, 100000000000], 1000, - 6, + 600_000, 2000, 0, Err(StablePoolError::InsufficientInputAmount()), @@ -164,7 +164,7 @@ fn test_04(mut session: Session) { vec![12, 18], vec![100000000000000000, 100000000000000000000000], 1000, - 6, + 600_000, 2000, 0, Err(StablePoolError::InsufficientInputAmount()), @@ -179,7 +179,7 @@ fn test_05(mut session: Session) { vec![6, 6], vec![100000000000, 100000000000], 1000, - 6, + 600_000, 2000, 1, Ok(0), @@ -195,7 +195,7 @@ fn test_06_a(mut session: Session) { vec![18, 12], vec![100000000000000000000000, 100000000000000000], 1000, - 6, + 600_000, 2000, 1000000, Ok(0), @@ -240,7 +240,7 @@ fn test_07(mut session: Session) { vec![6, 6], vec![100000000000, 100000000000], 1000, - 6, + 600_000, 2000, 100000000000, Ok(98443663539), @@ -255,7 +255,7 @@ fn test_08(mut session: Session) { vec![12, 18], vec![100000000000000000, 100000000000000000000000], 1000, - 6, + 600_000, 2000, 100000000000000000, Ok(98443663539913153080656), @@ -270,7 +270,7 @@ fn test_09(mut session: Session) { vec![6, 6], vec![100000000000, 100000000000], 1000, - 6, + 600_000, 2000, 99999000000 + 1, // +1 because of accounting for fee rounding Ok(98443167413), @@ -285,7 +285,7 @@ fn test_10(mut session: Session) { vec![12, 18], vec![100000000000000000, 100000000000000000000000], 1000, - 6, + 600_000, 2000, 99999000000000000, Ok(98443167413204135506296), diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs index bf15a3c..313b1d4 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs @@ -8,8 +8,8 @@ fn test_swap_received( token_decimals: Vec, initial_reserves: Vec, amp_coef: u128, - fee_bps: u16, - protocol_fee_bps: u16, + trad_fee: u32, + protocol_fee: u32, swap_amount_in: u128, expected_swap_amount_out_total_result: Result, ) { @@ -19,8 +19,8 @@ fn test_swap_received( token_decimals, initial_supply, amp_coef, - fee_bps, - protocol_fee_bps, + trad_fee, + protocol_fee, BOB, ); _ = stable_swap::add_liquidity( @@ -57,9 +57,9 @@ fn test_swap_received( let (amount_out, fee) = swap_result.unwrap(); let expected_swap_amount_out_total = expected_swap_amount_out_total_result.unwrap(); - let expected_fee = expected_swap_amount_out_total * fee_bps as u128 / FEE_BPS_DENOM; + let expected_fee = expected_swap_amount_out_total * trad_fee as u128 / FEE_DENOM; let expected_swap_amount_out = expected_swap_amount_out_total - expected_fee; - let expected_protocol_fee_part = expected_fee * protocol_fee_bps as u128 / FEE_BPS_DENOM; + let expected_protocol_fee_part = expected_fee * protocol_fee as u128 / FEE_DENOM; // check returned amount swapped and fee assert_eq!(expected_swap_amount_out, amount_out, "Amount out mismatch"); @@ -120,8 +120,8 @@ fn test_01(mut session: Session) { vec![6, 6], // decimals vec![100000000000, 100000000000], // initial reserves 1000, // A - 6, // fee BPS - 2000, // protocol fee BPS + 600_000, // fee BPS + 200_000_000, // protocol fee BPS 10000000000, // swap_amount_in Ok(9999495232), // expected out (with fee) ); @@ -135,8 +135,8 @@ fn test_02(mut session: Session) { vec![12, 18], vec![100000000000000000, 100000000000000000000000], 1000, - 6, - 2000, + 600_000, + 200_000_000, 10000000000000000, Ok(9999495232752197989995), ); @@ -150,8 +150,8 @@ fn test_03(mut session: Session) { vec![6, 6], vec![100000000000, 100000000000], 1000, - 6, - 2000, + 600_000, + 200_000_000, 0, Err(StablePoolError::InsufficientInputAmount()), ); @@ -165,8 +165,8 @@ fn test_04(mut session: Session) { vec![12, 18], vec![100000000000000000, 100000000000000000000000], 1000, - 6, - 2000, + 600_000, + 200_000_000, 0, Err(StablePoolError::InsufficientInputAmount()), ); @@ -180,8 +180,8 @@ fn test_05(mut session: Session) { vec![6, 6], vec![100000000000, 100000000000], 1000, - 6, - 2000, + 600_000, + 200_000_000, 1, Ok(0), ); @@ -196,8 +196,8 @@ fn test_06_a(mut session: Session) { vec![18, 12], vec![100000000000000000000000, 100000000000000000], 1000, - 6, - 2000, + 600_000, + 200_000_000, 1000000, Ok(0), ); @@ -241,8 +241,8 @@ fn test_07(mut session: Session) { vec![6, 6], vec![100000000000, 100000000000], 1000, - 6, - 2000, + 600_000, + 200_000_000, 100000000000, Ok(98443663539), ); @@ -256,8 +256,8 @@ fn test_08(mut session: Session) { vec![12, 18], vec![100000000000000000, 100000000000000000000000], 1000, - 6, - 2000, + 600_000, + 200_000_000, 100000000000000000, Ok(98443663539913153080656), ); @@ -271,8 +271,8 @@ fn test_09(mut session: Session) { vec![6, 6], vec![100000000000, 100000000000], 1000, - 6, - 2000, + 600_000, + 200_000_000, 99999000000 + 1, // +1 because of accounting for fee rounding Ok(98443167413), ); @@ -286,8 +286,8 @@ fn test_10(mut session: Session) { vec![12, 18], vec![100000000000000000, 100000000000000000000000], 1000, - 6, - 2000, + 600_000, + 200_000_000, 99999000000000000, Ok(98443167413204135506296), ); From 3aaba7ca6a3c97634848bdea5f48b15feb7f73ed Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Tue, 9 Jul 2024 17:07:50 +0200 Subject: [PATCH 19/28] adjust expected results in test due to change in fee precision --- .../stable_swap_tests/tests_add_remove_lp.rs | 78 +++++++++---------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index 57a2cb1..ac54623 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -104,7 +104,7 @@ fn test_01(mut session: Session) { ); // add more liquidity with imbalanced tokens (dave) - let res = stable_swap::add_liquidity( + _ = stable_swap::add_liquidity( &mut session, stable_swap, DAVE, @@ -113,8 +113,15 @@ fn test_01(mut session: Session) { dave(), ) .expect("Should successfully add liquidity"); + // Ref // "Mint 699699997426210330025 shares for user2, fee is 299999998348895348 shares", // "Exchange swap got 59999999669779069 shares", + // -- DIFF -- + // Common + // "Mint 699687497426279107411 shares for dave, fee is 312499998280117962 shares", + // "Exchange swap got 62499999656023592 shares, No referral fee (not implemented)", + // + // The difference is due to the implemented fee precision (1e9 in Common vs 1e4 in Ref) assert_eq!( stable_swap::reserves(&mut session, stable_swap), @@ -123,12 +130,12 @@ fn test_01(mut session: Session) { ); assert_eq!( psp22_utils::total_supply(&mut session, stable_swap), - 301200 * ONE_LPT + 699699997426210330025 + 59999999669779069, + 301200 * ONE_LPT + 699687497426279107411 + 62499999656023592, "Incorrect total shares" ); assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, dave()), - 699699997426210330025, + 699687497426279107411, "Incorrect Users share" ); @@ -142,7 +149,7 @@ fn test_01(mut session: Session) { assert_eq!( current_total_shares, - last_total_shares + 699699997426210330025 + 59999999669779069 + last_total_shares + 699687497426279107411 + 62499999656023592 ); let last_total_shares = current_total_shares; @@ -156,11 +163,12 @@ fn test_01(mut session: Session) { charlie(), ) .expect("Should successfully remove liquidity. Err: {err:?}"); - // "LP charlie removed 502598511257512352631 shares by given tokens, and fee is 598899301432400519 shares", - // "Exchange swap got 119779860286480103 shares", + // "LP charlie removed 502623448746385017122 shares by given tokens, and fee is 623853418327862983 shares", + // "Exchange swap got 124770683665572596 shares, No referral fee (not implemented)", + assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), - 1200 * ONE_LPT - 502598511257512352631, + 1200 * ONE_LPT - 502623448746385017122, "Incorrect users share" ); @@ -181,17 +189,17 @@ fn test_01(mut session: Session) { ); assert_eq!( psp22_utils::total_supply(&mut session, stable_swap), - last_total_shares - 502598511257512352631 + 119779860286480103, + last_total_shares - 502623448746385017122 + 124770683665572596, "Incorrect total shares" ); assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), - 1200 * ONE_LPT - 502598511257512352631, + 1200 * ONE_LPT - 502623448746385017122, "Incorrect users share" ); assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, dave()), - 699699997426210330025, + 699687497426279107411, "Incorrect users share" ); let (current_share_price, _) = share_price_and_total_shares(&mut session, stable_swap); @@ -200,19 +208,19 @@ fn test_01(mut session: Session) { "Incorrect share price" ); let last_share_price = current_share_price; - let last_total_shares = last_total_shares - 502598511257512352631 + 119779860286480103; + let last_total_shares = last_total_shares - 502623448746385017122 + 124770683665572596; // transfer some LPT to from charlie to dave _ = psp22_utils::transfer(&mut session, stable_swap, dave(), 100 * ONE_LPT, CHARLIE); assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), - 1100 * ONE_LPT - 502598511257512352631, + 1100 * ONE_LPT - 502623448746385017122, "Incorrect user balance" ); assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, dave()), - 699699997426210330025 + 100 * ONE_LPT, + 699687497426279107411 + 100 * ONE_LPT, "Incorrect user balance" ); @@ -270,12 +278,12 @@ fn test_01(mut session: Session) { assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), - 1100 * ONE_LPT - 502598511257512352631, + 1100 * ONE_LPT - 502623448746385017122, "Incorrect user balance" ); assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, dave()), - 699699997426210330025 + 100 * ONE_LPT, + 699687497426279107411 + 100 * ONE_LPT, "Incorrect user balance" ); @@ -289,20 +297,17 @@ fn test_01(mut session: Session) { dave(), ) .expect("Should successfully remove liquidity"); - // "LP dave removed 498596320225563082252 shares by given tokens, and fee is 597500435701476809 shares", - // "Exchange swap got 119500087140295361 shares", assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), - 1100 * ONE_LPT - 502598511257512352631, + 1100 * ONE_LPT - 502623448746385017122, "Incorrect user balance" ); assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, dave()), - 699699997426210330025 - 200 * ONE_LPT, + 699687497426279107411 - 200 * ONE_LPT, "Incorrect user balance" ); - let (current_share_price, current_total_shares) = share_price_and_total_shares(&mut session, stable_swap); assert_eq!( @@ -325,24 +330,20 @@ fn test_01(mut session: Session) { dave(), ) .expect("Should successfully remove liquidity"); - // "LP user2 removed 498596320225563082252 shares by given tokens, and fee is 597500435701476809 shares", - // "Exchange swap got 119500087140295361 shares, No referral fee, from remove_liquidity_by_tokens", - // -- DIFF -- - // "LP dave removed 498596320224035614380 shares by given tokens, and fee is 597500435700561479 shares", - // "Exchange swap got 119500087140112295 shares, No referral fee (not implemented)", - // + // "LP dave removed 498621166533015126275 shares by given tokens, and fee is 622396225347309589 shares", + // "Exchange swap got 124479245069461917 shares, No referral fee (not implemented)", + assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, charlie()), - 1100 * ONE_LPT - 502598511257512352631, + 1100 * ONE_LPT - 502623448746385017122, "Incorrect user balance" ); assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, dave()), - 699699997426210330025 - 200 * ONE_LPT - 498596320224035614380, + 699687497426279107411 - 200 * ONE_LPT - 498621166533015126275, "Incorrect user balance" ); - - let last_total_shares = last_total_shares - 498596320224035614380 + 119500087140112295; + let last_total_shares = last_total_shares - 498621166533015126275 + 124479245069461917; let (current_share_price, current_total_shares) = share_price_and_total_shares(&mut session, stable_swap); assert!( @@ -366,8 +367,7 @@ fn test_01(mut session: Session) { ], BOB, ); - - stable_swap::add_liquidity( + _ = stable_swap::add_liquidity( &mut session, stable_swap, EVA, @@ -380,20 +380,16 @@ fn test_01(mut session: Session) { eva(), ) .expect("Should successfully add liquidity"); - // "Mint 299997911758886758506069372942 shares for user3, fee is 895808190595468286848457 shares", - // "Exchange swap got 179161638119093657369691 shares, No referral fee, from add_liquidity", - // -- DIFF -- - // "Mint 299997911757966485300035937427 shares for eva, fee is 895808191250701043141970 shares", - // "Exchange swap got 179161638250140208628394 shares, No referral fee (not implemented)", - // + // "Mint 299997824748271184577117019598 shares for eva, fee is 933133378066387864612868 shares", + // "Exchange swap got 186626675613277572922573 shares, No referral fee (not implemented)", + assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, eva()), - 299997911757966485300035937427, + 299997824748271184577117019598, "Incorrect user balance" ); - let last_total_shares = - last_total_shares + 299997911757966485300035937427 + 179161638250140208628394; + last_total_shares + 299997824748271184577117019598 + 186626675613277572922573; assert_eq!( psp22_utils::total_supply(&mut session, stable_swap), last_total_shares, From 35319567f437b9b6f370390755e9456a76a5cbf9 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 10 Jul 2024 13:03:43 +0200 Subject: [PATCH 20/28] allow salt in test contracts deployment --- amm/drink-tests/src/stable_swap_tests/mod.rs | 8 ++++++-- .../src/stable_swap_tests/tests_add_remove_lp.rs | 7 +++++++ amm/drink-tests/src/stable_swap_tests/tests_getters.rs | 1 + .../src/stable_swap_tests/tests_swap_exact_in.rs | 1 + .../src/stable_swap_tests/tests_swap_received.rs | 1 + 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/mod.rs b/amm/drink-tests/src/stable_swap_tests/mod.rs index 59376a7..af54777 100644 --- a/amm/drink-tests/src/stable_swap_tests/mod.rs +++ b/amm/drink-tests/src/stable_swap_tests/mod.rs @@ -2,6 +2,7 @@ mod tests_add_remove_lp; mod tests_getters; mod tests_rated; mod tests_swap_exact_in; +mod tests_swap_exact_out; mod tests_swap_received; use crate::stable_pool_contract; @@ -41,6 +42,7 @@ pub fn setup_stable_swap_with_tokens( trade_fee: u32, protocol_trade_fee: u32, caller: AccountId32, + salt: Vec, ) -> (AccountId, Vec) { let _ = session.set_actor(caller); @@ -50,6 +52,7 @@ pub fn setup_stable_swap_with_tokens( upload_all(session); + let salty_str = String::from_utf8(salt.clone()).unwrap_or("Test token".to_string()); // instantiate tokens let tokens: Vec = token_decimals .iter() @@ -58,7 +61,7 @@ pub fn setup_stable_swap_with_tokens( .map(|(id, (&decimals, &supply))| { psp22_utils::setup_with_amounts( session, - format!("Test Token {id}").to_string(), + format!("{salty_str} {id}").to_string(), decimals, supply, BOB, @@ -76,7 +79,8 @@ pub fn setup_stable_swap_with_tokens( trade_fee, protocol_trade_fee, Some(fee_receiver()), - ); + ) + .with_salt(salt); let stable_swap: stable_pool_contract::Instance = session .instantiate(instance) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index ac54623..1ebb9ae 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -22,6 +22,7 @@ fn test_01(mut session: Session) { 2_500_000, 200_000_000, BOB, + vec![], ); _ = stable_swap::add_liquidity( @@ -417,6 +418,7 @@ fn test_02(mut session: Session) { 2_500_000, 200_000_000, BOB, + vec![], ); _ = stable_swap::add_liquidity( @@ -469,6 +471,7 @@ fn test_03(mut session: Session) { 2_500_000, 200_000_000, BOB, + vec![], ); _ = stable_swap::add_liquidity( @@ -525,6 +528,7 @@ fn test_04(mut session: Session) { 2_500_000, 200_000_000, BOB, + vec![], ); _ = stable_swap::add_liquidity( @@ -610,6 +614,7 @@ fn test_05(mut session: Session) { 2_500_000, 200_000_000, BOB, + vec![], ); _ = stable_swap::add_liquidity( @@ -681,6 +686,7 @@ fn test_06(mut session: Session) { 2_500_000, 200_000_000, BOB, + vec![], ); let (shares, _) = stable_swap::add_liquidity( @@ -763,6 +769,7 @@ fn test_07(mut session: Session) { 2_500_000, 200_000_000, BOB, + vec![], ); let (shares, _) = stable_swap::add_liquidity( diff --git a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs index e476ab1..f27dd90 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs @@ -16,6 +16,7 @@ fn test_01(mut session: Session) { trade_fee, protocol_fee, BOB, + vec![], ); _ = stable_swap::add_liquidity( diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs index bdf2a8f..8e6bcc2 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs @@ -22,6 +22,7 @@ fn test_swap_exact_in( trade_fee, protocol_fee, BOB, + vec![], ); _ = stable_swap::add_liquidity( session, diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs index 313b1d4..452ad0e 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs @@ -22,6 +22,7 @@ fn test_swap_received( trad_fee, protocol_fee, BOB, + vec![], ); _ = stable_swap::add_liquidity( session, From 4b6d7658feb784e75175f4036670a44720bdcf8d Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Wed, 10 Jul 2024 16:25:41 +0200 Subject: [PATCH 21/28] cross tests for swap_exact_out --- .../stable_swap_tests/tests_swap_exact_out.rs | 306 ++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 amm/drink-tests/src/stable_swap_tests/tests_swap_exact_out.rs diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_out.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_out.rs new file mode 100644 index 0000000..732d056 --- /dev/null +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_out.rs @@ -0,0 +1,306 @@ +use std::ops::{Add, Sub}; + +use drink::{self, runtime::MinimalRuntime, session::Session}; + +use super::*; + +/// Assert if `a` and `b` are equal +/- `delta` +fn assert_approx(a: T, b: T, delta: T, message: &str) +where + T: Add + Sub + Copy + PartialEq + PartialOrd + Eq + Ord + std::fmt::Display, + ::Output: PartialOrd, +{ + if a > b { + if a - b > delta { + panic!("{}, {}, {}", a, b, message) + } + } else { + if b - a > delta { + panic!("{}, {}, {}", a, b, message) + } + } +} + +/// Cross test swap methods. +/// Tests if `swap_exact_out` performs a fair swap +/// and produces correct result. +/// Tests swap of the token at index 0 to token at index 1 +/// +/// NOTE: When token_decimals[0] > token_decimals[1], the method tests if +/// `swap_amount_out` is approximatelly correct (`+/- 10^(token_decimals[0] - token_decimals[1])`) and +/// always in the protocols favour. +fn test_swap_exact_out( + session: &mut Session, + token_decimals: Vec, + initial_reserves: Vec, + amp_coef: u128, + trade_fee: u32, + protocol_fee: u32, + swap_amount_out: u128, +) { + let initial_supply = vec![initial_reserves[0] * 2, initial_reserves[1] * 2]; + // setup two identical pools + let (stable_swap_1, tokens_1) = setup_stable_swap_with_tokens( + session, + token_decimals.clone(), + initial_supply.clone(), + amp_coef, + trade_fee, + protocol_fee, + BOB, + "foo".as_bytes().to_vec(), + ); + let (stable_swap_2, tokens_2) = setup_stable_swap_with_tokens( + session, + token_decimals.clone(), + initial_supply, + amp_coef, + trade_fee, + protocol_fee, + BOB, + "bar".as_bytes().to_vec(), + ); + _ = stable_swap::add_liquidity( + session, + stable_swap_1, + BOB, + 1, + initial_reserves.to_vec(), + bob(), + ); + _ = stable_swap::add_liquidity( + session, + stable_swap_2, + BOB, + 1, + initial_reserves.to_vec(), + bob(), + ); + + let swap_exact_out_result = stable_swap::swap_exact_out( + session, + stable_swap_1, + BOB, + tokens_1[0], // in + tokens_1[1], // out + swap_amount_out, // amount_out + u128::MAX, // max_token_in + bob(), + ) + .expect("swap_exact_out failed"); + + let swap_exact_in_result = stable_swap::swap_exact_in( + session, + stable_swap_2, + BOB, + tokens_2[0], // in + tokens_2[1], // out + swap_exact_out_result.0, // amount_in - cross test result + 0, // min_token_out + bob(), + ) + .expect("swap_exact_in failed"); + + // If token_out has more decimals than token_in, allow rounding error + // up to the difference in their precision. + // Otherwise the results should be exact. + let delta: u128 = if token_decimals[1] > token_decimals[0] { + 10u128.pow((token_decimals[1] - token_decimals[0]) as u32) + } else { + 0 + }; + + // check returned amount swapped and fee + assert_approx( + swap_amount_out, + swap_exact_in_result.0, + delta, + "Amount out mismatch", + ); + assert!( + swap_amount_out <= + swap_exact_in_result.0, + "Protocol at loss (amount out)", + ); + assert_approx( + swap_exact_out_result.1, + swap_exact_in_result.1, + delta, + "Fee mismatch", + ); + assert!( + swap_exact_out_result.1 <= + swap_exact_in_result.1, + "Protocol at loss (fee)", + ); + + // check if reserves were updated properly + let reserves = stable_swap::reserves(session, stable_swap_1); + assert_eq!( + reserves, + [ + initial_reserves[0] + swap_exact_out_result.0, + initial_reserves[1] - swap_amount_out + ], + "Reserves not updated properly" + ); + + // check if reserves are equal the actual balances + let balance_0 = psp22_utils::balance_of(session, tokens_1[0], stable_swap_1); + let balance_1 = psp22_utils::balance_of(session, tokens_1[1], stable_swap_1); + assert_eq!( + reserves, + vec![balance_0, balance_1], + "Balances - reserves mismatch" + ); + + // check bobs balances + let balance_0 = psp22_utils::balance_of(session, tokens_1[0], bob()); + let balance_1 = psp22_utils::balance_of(session, tokens_1[1], bob()); + assert_eq!( + [ + initial_reserves[0] - swap_exact_out_result.0, + initial_reserves[1] + swap_amount_out + ], + [balance_0, balance_1], + "Incorrect Bob's balances" + ); + + // check protocol fee + let expected_protocol_fee_part = swap_exact_out_result.1 * protocol_fee as u128 / FEE_DENOM; + let protocol_fee_lp = psp22_utils::balance_of(session, stable_swap_1, fee_receiver()); + let (total_lp_required, lp_fee_part) = stable_swap::remove_liquidity_by_amounts( + session, + stable_swap_1, + BOB, + protocol_fee_lp * 2, + [0, expected_protocol_fee_part].to_vec(), + bob(), + ) + .expect("Should remove lp"); + assert_eq!( + total_lp_required - lp_fee_part, + protocol_fee_lp, + "Incorrect protocol fee" + ); +} + +// test when tokens precisions are the same +#[drink::test] +fn test_01(mut session: Session) { +test_swap_exact_out( + &mut session, + vec![6, 6], // decimals + vec![100000000000, 100000000000], // initial reserves + 10000, // A + 600_000, // trade fee + 200_000_000, // protocol fee + 100000000, // expected amount out + ); +} + +#[drink::test] +fn test_02(mut session: Session) { + test_swap_exact_out( + &mut session, + vec![12, 12], + vec![100000000000000000, 100000000000000000], + 10000, + 600_000, + 200_000_000, + 100000000000000, + ); +} + +#[drink::test] +fn test_03(mut session: Session) { + test_swap_exact_out( + &mut session, + vec![18, 18], + vec![100000000000000000000000, 100000000000000000000000], + 10000, + 600_000, + 200_000_000, + 100000000000000000000, + ); +} + +// test when token_in precision is smaller than token_out precision +#[drink::test] +fn test_04(mut session: Session) { + test_swap_exact_out( + &mut session, + vec![6, 12], + vec![100000000000, 100000000000000000], + 10000, + 600_000, + 200_000_000, + 100000000000000, + ); +} + +#[drink::test] +fn test_05(mut session: Session) { + test_swap_exact_out( + &mut session, + vec![6, 18], + vec![100000000000, 100000000000000000000000], + 10000, + 600_000, + 200_000_000, + 100000000000000000000, + ); +} + +#[drink::test] +fn test_06(mut session: Session) { + test_swap_exact_out( + &mut session, + vec![12, 18], + vec![100000000000000000, 100000000000000000000000], + 10000, + 600_000, + 200_000_000, + 100000000000000000000, + ); +} + +// test when token_out precision is smaller than token_in precision +#[drink::test] +fn test_07(mut session: Session) { + test_swap_exact_out( + &mut session, + vec![12, 6], + vec![100000000000000000, 100000000000], + 10000, + 600_000, + 200_000_000, + 100000000, + ); +} + +#[drink::test] +fn test_08(mut session: Session) { + test_swap_exact_out( + &mut session, + vec![18, 6], + vec![100000000000000000000000, 100000000000], + 10000, + 600_000, + 200_000_000, + 100000000, + ); +} + +#[drink::test] +fn test_09(mut session: Session) { + test_swap_exact_out( + &mut session, + vec![18, 12], + vec![100000000000000000000000, 100000000000000000], + 10000, + 600_000, + 200_000_000, + 100000000000000, + ); +} From 23a946690496e3caf8134db0a24b1452a637e333 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Thu, 11 Jul 2024 14:40:35 +0200 Subject: [PATCH 22/28] wip - test lp withdraw getter --- .../src/stable_swap_tests/tests_getters.rs | 55 +++++++++++++++++ amm/drink-tests/src/utils.rs | 60 +++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs index f27dd90..253700e 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs @@ -133,3 +133,58 @@ fn test_01(mut session: Session) { "Incorrect LP token supply" ); } + +#[drink::test] +fn test_02(mut session: Session) { + let initial_reserves = vec![10000000 * ONE_USDT, 10000000 * ONE_USDC]; + let initial_supply: Vec = initial_reserves.iter().map(|amount| amount * 10).collect(); + let amp_coef = 10_000u128; + let trade_fee = 2_500_000u32; + let protocol_fee = 200_000_000u32; + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![6, 6], + initial_supply.clone(), + amp_coef, + trade_fee, + protocol_fee, + BOB, + vec![], + ); + + _ = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + // make a swap to the reserves are not equal anymore + _ = stable_swap::swap_exact_in( + &mut session, + stable_swap, + BOB, + tokens[0], // in USDT + tokens[1], // out USDC + ONE_USDT, // amount_in + 1, // min_token_out + bob(), + ) + .expect("Should successfully swap"); + + let total_shares = psp22_utils::total_supply(&mut session, stable_swap); + let share = total_shares / 20; // 4.999...% - 5% + let withdraw_amounts = + stable_swap::get_amounts_for_liquidity_burn(&mut session, stable_swap, share) + .expect("Should compute"); + let (share_burn_1, fee) = + stable_swap::get_burn_liquidity_for_amounts(&mut session, stable_swap, withdraw_amounts) + .expect("Should compute"); + // both methods should require burning the same amount lpt + assert_eq!(share, share_burn_1, "Shares amounts mismatch"); + // because `withdraw_amounts` are balanced, fee should be 0 + assert_eq!(fee, 0, "Fee should be 0"); +} diff --git a/amm/drink-tests/src/utils.rs b/amm/drink-tests/src/utils.rs index ade795b..5958c3c 100644 --- a/amm/drink-tests/src/utils.rs +++ b/amm/drink-tests/src/utils.rs @@ -262,6 +262,66 @@ pub mod stable_swap { .unwrap(), ) } + + pub fn get_amounts_for_liquidity_burn( + session: &mut Session, + stable_pool: AccountId, + liquidity: u128, + ) -> Result, StablePoolError> { + handle_ink_error( + session + .query( + stable_pool_contract::Instance::from(stable_pool) + .get_amounts_for_liquidity_burn(liquidity), + ) + .unwrap(), + ) + } + + pub fn get_amounts_for_liquidity_mint( + session: &mut Session, + stable_pool: AccountId, + liquidity: u128, + ) -> Result, StablePoolError> { + handle_ink_error( + session + .query( + stable_pool_contract::Instance::from(stable_pool) + .get_amounts_for_liquidity_mint(liquidity), + ) + .unwrap(), + ) + } + + pub fn get_burn_liquidity_for_amounts( + session: &mut Session, + stable_pool: AccountId, + amounts: Vec, + ) -> Result<(u128, u128), StablePoolError> { + handle_ink_error( + session + .query( + stable_pool_contract::Instance::from(stable_pool) + .get_burn_liquidity_for_amounts(amounts), + ) + .unwrap(), + ) + } + + pub fn get_mint_liquidity_for_amounts( + session: &mut Session, + stable_pool: AccountId, + amounts: Vec, + ) -> Result<(u128, u128), StablePoolError> { + handle_ink_error( + session + .query( + stable_pool_contract::Instance::from(stable_pool) + .get_mint_liquidity_for_amounts(amounts), + ) + .unwrap(), + ) + } } pub mod psp22_utils { From 0506eee4413b3a846c37b98568fc02227760c917 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Thu, 11 Jul 2024 17:25:03 +0200 Subject: [PATCH 23/28] tests expoit add-remove liqudity --- .../stable_swap_tests/tests_add_remove_lp.rs | 295 ++++++++++++++++++ .../src/stable_swap_tests/tests_getters.rs | 55 ---- 2 files changed, 295 insertions(+), 55 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index 1ebb9ae..3c48c69 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -841,3 +841,298 @@ fn test_07(mut session: Session) { "Incorrect Users tokens balances" ); } + +/// Tests that after depositing X tokens amounts for L shares, user cannot withdraw X tokens amounts for L - 1 shares +#[drink::test] +fn test_08(mut session: Session) { + let initial_reserves = vec![100000 * ONE_USDT, 100000 * ONE_USDC]; + let initial_supply: Vec = initial_reserves.iter().map(|amount| amount * 10).collect(); + let amp_coef = 10_000u128; + let trade_fee = 2_500_000u32; + let protocol_fee = 200_000_000u32; + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![12, 12], + initial_supply.clone(), + amp_coef, + trade_fee, + protocol_fee, + BOB, + vec![], + ); + + _ = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + _ = stable_swap::swap_exact_in( + &mut session, + stable_swap, + BOB, + tokens[0], // in USDT + tokens[1], // out USDC + 123 * ONE_USDT + 132312, // amount_in + 1, // min_token_out + bob(), + ) + .expect("Should successfully swap"); + + let total_shares = psp22_utils::total_supply(&mut session, stable_swap); + let share = total_shares / 20; // 4.999...% - 5% + + let deposit_amounts = + stable_swap::get_amounts_for_liquidity_mint(&mut session, stable_swap, share) + .expect("Should compute"); + + let (share_mint, _) = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + deposit_amounts.clone(), + bob(), + ) + .expect("Should mint LPT"); + + let err = stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + BOB, + share_mint - 1, + deposit_amounts, + bob(), + ) + .expect_err("Should fail to remove lpt"); + + assert_eq!( + StablePoolError::InsufficientLiquidityBurned(), + err, + "Should be insufficient" + ); +} + +/// Tests that after withdrawing X tokens amounts for L shares, user cannot deposit X tokens amounts for L + 1 shares +#[drink::test] +fn test_09(mut session: Session) { + let initial_reserves = vec![100000 * ONE_USDT * ONE_USDT, 100000 * ONE_USDC * ONE_USDC]; + let initial_supply: Vec = initial_reserves.iter().map(|amount| amount * 10).collect(); + let amp_coef = 10_000u128; + let trade_fee = 2_500_000u32; + let protocol_fee = 200_000_000u32; + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![12, 12], + initial_supply.clone(), + amp_coef, + trade_fee, + protocol_fee, + BOB, + vec![], + ); + + _ = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + _ = stable_swap::swap_exact_in( + &mut session, + stable_swap, + BOB, + tokens[0], // in USDT + tokens[1], // out USDC + 123 * ONE_USDT * ONE_USDC + 132312, // amount_in + 1, // min_token_out + bob(), + ) + .expect("Should successfully swap"); + + let total_shares = psp22_utils::total_supply(&mut session, stable_swap); + let share = total_shares / 20; // 4.999...% - 5% + + let withdraw_amounts = + stable_swap::get_amounts_for_liquidity_burn(&mut session, stable_swap, share) + .expect("Should compute"); + let (share_burn, _) = stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + BOB, + u128::MAX, + withdraw_amounts.clone(), + bob(), + ) + .expect("Should burn LPT"); + + let err = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + share_burn + 1, + withdraw_amounts.clone(), + bob(), + ) + .expect_err("Should fail to mint lpt"); + + assert_eq!( + StablePoolError::InsufficientLiquidityMinted(), + err, + "Should be insufficient" + ); +} + +/// Tests that after depositing X tokens amounts for L shares, user cannot withdraw X tokens amounts for L - 1 shares (using remove_by_shares method) +#[drink::test] +fn test_10(mut session: Session) { + let initial_reserves = vec![100000 * ONE_USDT, 100000 * ONE_USDC]; + let initial_supply: Vec = initial_reserves.iter().map(|amount| amount * 10).collect(); + let amp_coef = 10_000u128; + let trade_fee = 2_500_000u32; + let protocol_fee = 200_000_000u32; + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![12, 12], + initial_supply.clone(), + amp_coef, + trade_fee, + protocol_fee, + BOB, + vec![], + ); + + _ = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + _ = stable_swap::swap_exact_in( + &mut session, + stable_swap, + BOB, + tokens[0], // in USDT + tokens[1], // out USDC + 123 * ONE_USDT + 132312, // amount_in + 1, // min_token_out + bob(), + ) + .expect("Should successfully swap"); + + let total_shares = psp22_utils::total_supply(&mut session, stable_swap); + let share = total_shares / 20; // 4.999...% - 5% + + let deposit_amounts = + stable_swap::get_amounts_for_liquidity_mint(&mut session, stable_swap, share) + .expect("Should compute"); + + let (share_mint, _) = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + deposit_amounts.clone(), + bob(), + ) + .expect("Should mint LPT"); + + let err = stable_swap::remove_liquidity_by_shares( + &mut session, + stable_swap, + BOB, + share_mint - 1, + deposit_amounts, + bob(), + ) + .expect_err("Should fail to remove lpt"); + + assert_eq!( + StablePoolError::InsufficientOutputAmount(), + err, + "Should be insufficient" + ); +} + +/// Tests that after withdrawing X tokens amounts for L shares, user cannot deposit X tokens amounts for L + 1 shares (using remove_by_shares method) +#[drink::test] +fn test_11(mut session: Session) { + let initial_reserves = vec![100000 * ONE_USDT * ONE_USDT, 100000 * ONE_USDC * ONE_USDC]; + let initial_supply: Vec = initial_reserves.iter().map(|amount| amount * 10).collect(); + let amp_coef = 10_000u128; + let trade_fee = 2_500_000u32; + let protocol_fee = 200_000_000u32; + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![12, 12], + initial_supply.clone(), + amp_coef, + trade_fee, + protocol_fee, + BOB, + vec![], + ); + + _ = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + 1, + initial_reserves.clone(), + bob(), + ) + .expect("Should successfully add liquidity"); + + _ = stable_swap::swap_exact_in( + &mut session, + stable_swap, + BOB, + tokens[0], // in USDT + tokens[1], // out USDC + 123 * ONE_USDT * ONE_USDC + 132312, // amount_in + 1, // min_token_out + bob(), + ) + .expect("Should successfully swap"); + + let total_shares = psp22_utils::total_supply(&mut session, stable_swap); + let share = total_shares / 20; // 4.999...% - 5% + + let withdraw_amounts = stable_swap::remove_liquidity_by_shares( + &mut session, + stable_swap, + BOB, + share, + vec![1, 1], + bob(), + ) + .expect("Should burn LPT"); + + let err = stable_swap::add_liquidity( + &mut session, + stable_swap, + BOB, + share + 1, + withdraw_amounts.clone(), + bob(), + ) + .expect_err("Should fail to mint lpt"); + + assert_eq!( + StablePoolError::InsufficientLiquidityMinted(), + err, + "Should be insufficient" + ); +} diff --git a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs index 253700e..f27dd90 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs @@ -133,58 +133,3 @@ fn test_01(mut session: Session) { "Incorrect LP token supply" ); } - -#[drink::test] -fn test_02(mut session: Session) { - let initial_reserves = vec![10000000 * ONE_USDT, 10000000 * ONE_USDC]; - let initial_supply: Vec = initial_reserves.iter().map(|amount| amount * 10).collect(); - let amp_coef = 10_000u128; - let trade_fee = 2_500_000u32; - let protocol_fee = 200_000_000u32; - let (stable_swap, tokens) = setup_stable_swap_with_tokens( - &mut session, - vec![6, 6], - initial_supply.clone(), - amp_coef, - trade_fee, - protocol_fee, - BOB, - vec![], - ); - - _ = stable_swap::add_liquidity( - &mut session, - stable_swap, - BOB, - 1, - initial_reserves.clone(), - bob(), - ) - .expect("Should successfully add liquidity"); - - // make a swap to the reserves are not equal anymore - _ = stable_swap::swap_exact_in( - &mut session, - stable_swap, - BOB, - tokens[0], // in USDT - tokens[1], // out USDC - ONE_USDT, // amount_in - 1, // min_token_out - bob(), - ) - .expect("Should successfully swap"); - - let total_shares = psp22_utils::total_supply(&mut session, stable_swap); - let share = total_shares / 20; // 4.999...% - 5% - let withdraw_amounts = - stable_swap::get_amounts_for_liquidity_burn(&mut session, stable_swap, share) - .expect("Should compute"); - let (share_burn_1, fee) = - stable_swap::get_burn_liquidity_for_amounts(&mut session, stable_swap, withdraw_amounts) - .expect("Should compute"); - // both methods should require burning the same amount lpt - assert_eq!(share, share_burn_1, "Shares amounts mismatch"); - // because `withdraw_amounts` are balanced, fee should be 0 - assert_eq!(fee, 0, "Fee should be 0"); -} From 2dafd4a3ed3b52a1895723b3b178461b2d9a289d Mon Sep 17 00:00:00 2001 From: woocash2 Date: Fri, 12 Jul 2024 10:35:58 +0200 Subject: [PATCH 24/28] try exploit test --- .../stable_swap_tests/tests_add_remove_lp.rs | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index 1ebb9ae..a3b5476 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -841,3 +841,90 @@ fn test_07(mut session: Session) { "Incorrect Users tokens balances" ); } + +#[drink::test] +fn test_lp_withdraw_all_but_no_more() { + seed_account(&mut session, CHARLIE); + seed_account(&mut session, DAVE); + seed_account(&mut session, EVA); + + let charlie_input = vec![1_234_543 * ONE_USDT, 1_112_323 * ONE_USDC]; + let dave_input = vec![1131 * 105 * ONE_USDT, 1157 * 105 * ONE_USDC]; + let initial_supply: Vec = charlie_input.iter().map(|amount| amount * 10).collect(); + + let (stable_swap, tokens) = setup_stable_swap_with_tokens( + &mut session, + vec![6, 6], + initial_supply.clone(), + 10_000, + 0, + 0, + BOB, + vec![], + ); + + transfer_and_increase_allowance( + &mut session, + stable_swap, + tokens.clone(), + CHARLIE, + vec![1_434_543 * ONE_USDT, 1_112_323 * ONE_USDC], + BOB, + ); + transfer_and_increase_allowance( + &mut session, + stable_swap, + tokens, + DAVE, + vec![1131 * 105 * ONE_USDT, 1157 * 105 * ONE_USDC], + BOB, + ); + + _ = stable_swap::add_liquidity( + &mut session, + stable_swap, + CHARLIE, + 1, + charlie_input.clone(), + charlie(), + ) + .expect("Charlie should successfully add liquidity"); + + let (shares, _) = stable_swap::add_liquidity( + &mut session, + stable_swap, + DAVE, + 1, + dave_input.clone(), + dave(), + ) + .expect("Dave should successfully add liquidity"); + + for _ in 0..105 { + let withdraw = vec![1131 * ONE_USDT, 1157 * ONE_USDC]; // 1/105 of Dave's + _ = stable_swap::remove_liquidity_by_amounts( + &mut session, + stable_swap, + DAVE, + shares, // just an upper bound + withdraw, + dave(), + ) + .expect("Should successfully remove liquidity"); + } + + assert_eq!( + psp22_utils::balance_of(&mut session, stable_swap, dave()), + 0 + ); + + _ = stable_swap::remove_liquidity_by_shares( + &mut session, + stable_swap, + DAVE, + 10, + vec![1, 1], // at least withdraw something + dave(), + ) + .expect_err("Should not successfully remove liquidity"); +} From 62b4a243e3ef16ee943f0b77289ff0be6cc456e2 Mon Sep 17 00:00:00 2001 From: woocash2 Date: Fri, 12 Jul 2024 10:43:49 +0200 Subject: [PATCH 25/28] add some comments --- .../src/stable_swap_tests/tests_add_remove_lp.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs index a3b5476..bf94baf 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_add_remove_lp.rs @@ -848,8 +848,8 @@ fn test_lp_withdraw_all_but_no_more() { seed_account(&mut session, DAVE); seed_account(&mut session, EVA); - let charlie_input = vec![1_234_543 * ONE_USDT, 1_112_323 * ONE_USDC]; - let dave_input = vec![1131 * 105 * ONE_USDT, 1157 * 105 * ONE_USDC]; + let charlie_input = vec![1_434_543 * ONE_USDT, 1_112_323 * ONE_USDC]; + let dave_input = vec![1131 * 105 * ONE_USDT, 1157 * 105 * ONE_USDC]; // treat as 105 parts of (1131, 1157) let initial_supply: Vec = charlie_input.iter().map(|amount| amount * 10).collect(); let (stable_swap, tokens) = setup_stable_swap_with_tokens( @@ -900,6 +900,7 @@ fn test_lp_withdraw_all_but_no_more() { ) .expect("Dave should successfully add liquidity"); + // 105 times withdraw (1131, 1157) which should withdraw the whole Dave's share for _ in 0..105 { let withdraw = vec![1131 * ONE_USDT, 1157 * ONE_USDC]; // 1/105 of Dave's _ = stable_swap::remove_liquidity_by_amounts( @@ -915,7 +916,8 @@ fn test_lp_withdraw_all_but_no_more() { assert_eq!( psp22_utils::balance_of(&mut session, stable_swap, dave()), - 0 + 0, + "Dave shouldn't have any LPT left", ); _ = stable_swap::remove_liquidity_by_shares( From 28e6ac147c328d96bc739306723b185edc4ad48a Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Mon, 15 Jul 2024 15:02:19 +0200 Subject: [PATCH 26/28] fix typo in comment --- amm/drink-tests/src/stable_swap_tests/tests_getters.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs index f27dd90..3ac7cfd 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_getters.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_getters.rs @@ -91,7 +91,7 @@ fn test_01(mut session: Session) { stable_swap, BOB, tokens[0], // DAI - tokens[1], // USDC + tokens[1], // USDT ONE_DAI, // amount_in 1, // min_token_out charlie(), From c4c7b00e369d060d267d0dbf63d01457d027bf54 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Mon, 15 Jul 2024 21:11:17 +0200 Subject: [PATCH 27/28] update old comments --- .../src/stable_swap_tests/tests_rated.rs | 41 ++++++++++--------- .../stable_swap_tests/tests_swap_exact_in.rs | 4 +- .../stable_swap_tests/tests_swap_exact_out.rs | 22 +++++----- .../stable_swap_tests/tests_swap_received.rs | 4 +- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs index 8d026b1..83acb14 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_rated.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_rated.rs @@ -15,7 +15,8 @@ const ONE_LPT: u128 = 10u128.pow(18); const ONE_WAZERO: u128 = 10u128.pow(WAZERO_DEC as u32); const ONE_SAZERO: u128 = 10u128.pow(SAZERO_DEC as u32); -const EXPIRE_TS: u64 = 24 * 3600 * 1000; // 24h +/// Cached token rate expiry time in milliseconds +const EXPIRE_TIME_MILLIS: u64 = 24 * 3600 * 1000; // 24h fn deploy_rate_provider(session: &mut Session, salt: Vec) -> AccountId { let instance = mock_sazero_rate_contract::Instance::new().with_salt(salt); @@ -114,13 +115,13 @@ fn test_01(mut session: Session) { vec![Some(mock_sazero_rate), None], initial_token_supply, 10000, - EXPIRE_TS, + EXPIRE_TIME_MILLIS, 2_500_000, 200_000_000, ); let [sazero, wazero]: [AccountId; 2] = tokens.try_into().unwrap(); - set_timestamp(&mut session, now + EXPIRE_TS + 1); + set_timestamp(&mut session, now + EXPIRE_TIME_MILLIS + 1); set_mock_rate(&mut session, mock_sazero_rate, 2 * RATE_PRECISION); _ = stable_swap::add_liquidity( @@ -131,7 +132,7 @@ fn test_01(mut session: Session) { vec![50000 * ONE_SAZERO, 100000 * ONE_WAZERO], bob(), ) - .expect("Should successfully add LP"); + .expect("Should successfully add liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, rated_swap, bob()), 200000 * ONE_LPT, @@ -162,7 +163,7 @@ fn test_01(mut session: Session) { vec![50000 * ONE_SAZERO, 100000 * ONE_WAZERO], charlie(), ) - .expect("Should successfully swap"); + .expect("Should successfully add liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, rated_swap, charlie()), 200000 * ONE_LPT, @@ -185,7 +186,7 @@ fn test_01(mut session: Session) { vec![1 * ONE_SAZERO, 1 * ONE_WAZERO], charlie(), ) - .expect("Should successfully swap"); + .expect("Should successfully remove liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, rated_swap, charlie()), 0, @@ -247,12 +248,12 @@ fn test_02(mut session: Session) { vec![None, Some(mock_token_2_rate), None], initial_token_supply, 10000, - EXPIRE_TS, + EXPIRE_TIME_MILLIS, 2_500_000, 200_000_000, ); - set_timestamp(&mut session, now + EXPIRE_TS); + set_timestamp(&mut session, now + EXPIRE_TIME_MILLIS); set_mock_rate(&mut session, mock_token_2_rate, 2 * RATE_PRECISION); _ = stable_swap::add_liquidity( @@ -263,7 +264,7 @@ fn test_02(mut session: Session) { vec![100000 * ONE_WAZERO, 50000 * ONE_WAZERO, 100000 * ONE_WAZERO], bob(), ) - .expect("Should successfully add LP"); + .expect("Should successfully add liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, rated_swap, bob()), 300000 * ONE_LPT, @@ -298,7 +299,7 @@ fn test_02(mut session: Session) { vec![100000 * ONE_WAZERO, 50000 * ONE_WAZERO, 100000 * ONE_WAZERO], charlie(), ) - .expect("Should successfully add LP"); + .expect("Should successfully add liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, rated_swap, charlie()), 300000 * ONE_LPT, @@ -321,7 +322,7 @@ fn test_02(mut session: Session) { vec![1 * ONE_WAZERO, 1 * ONE_WAZERO, 1 * ONE_WAZERO], charlie(), ) - .expect("Should successfully remove LP"); + .expect("Should successfully remove liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, rated_swap, charlie()), 0, @@ -358,12 +359,12 @@ fn test_03(mut session: Session) { vec![None, Some(mock_token_2_rate), Some(mock_token_3_rate)], initial_token_supply, 10000, - EXPIRE_TS, + EXPIRE_TIME_MILLIS, 2_500_000, 200_000_000, ); - set_timestamp(&mut session, now + EXPIRE_TS); + set_timestamp(&mut session, now + EXPIRE_TIME_MILLIS); set_mock_rate(&mut session, mock_token_2_rate, 2 * RATE_PRECISION); set_mock_rate(&mut session, mock_token_3_rate, 4 * RATE_PRECISION); @@ -375,7 +376,7 @@ fn test_03(mut session: Session) { vec![100000 * ONE_WAZERO, 50000 * ONE_WAZERO, 25000 * ONE_WAZERO], bob(), ) - .expect("Should successfully add LP"); + .expect("Should successfully add liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, rated_swap, bob()), 300000 * ONE_LPT, @@ -411,7 +412,7 @@ fn test_03(mut session: Session) { vec![100000 * ONE_WAZERO, 50000 * ONE_WAZERO, 25000 * ONE_WAZERO], charlie(), ) - .expect("Should successfully add LP"); + .expect("Should successfully add liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, rated_swap, charlie()), 300000 * ONE_LPT, @@ -434,7 +435,7 @@ fn test_03(mut session: Session) { vec![1 * ONE_WAZERO, 1 * ONE_WAZERO, 1 * ONE_WAZERO], charlie(), ) - .expect("Should successfully remove LP"); + .expect("Should successfully remove liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, rated_swap, charlie()), 0, @@ -466,7 +467,7 @@ fn test_04(mut session: Session) { vec![None, None], initial_token_supply, 10000, - EXPIRE_TS, + EXPIRE_TIME_MILLIS, 2_500_000, 200_000_000, ); @@ -479,7 +480,7 @@ fn test_04(mut session: Session) { vec![100000 * ONE_WAZERO, 100000 * ONE_WAZERO], bob(), ) - .expect("Should successfully add LP"); + .expect("Should successfully add liquidity"); assert_eq!( psp22_utils::balance_of(&mut session, rated_swap, bob()), 200000 * ONE_LPT, @@ -539,7 +540,7 @@ fn test_04(mut session: Session) { ); assert_eq!( psp22_utils::balance_of(&mut session, tokens[1], charlie()), - 997499999501, + 997499999501, // -- DIFF -- 997499999501 [274936452669] "Incorrect user token balance" ); @@ -551,7 +552,7 @@ fn test_04(mut session: Session) { ); assert_eq!( stable_swap::reserves(&mut session, rated_swap), - vec![100001 * ONE_WAZERO, 99999 * ONE_WAZERO + 2500000499], + vec![100001 * ONE_WAZERO, 99999 * ONE_WAZERO + 2500000499], // DIFF -- 2500000498 [725063547331] "Incorrect reserves" ); } diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs index 8e6bcc2..010ced3 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs @@ -120,8 +120,8 @@ fn test_01(mut session: Session) { vec![6, 6], // decimals vec![100000000000, 100000000000], // initial reserves 1000, // A - 600_000, // fee BPS - 2000, // protocol fee BPS + 600_000, // trade fee in 1e9 precision + 2000, // protocol fee in 1e9 precision 10000000000, // swap_amount_in Ok(9999495232), // expected out (with fee) ); diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_out.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_out.rs index 732d056..a199bba 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_out.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_out.rs @@ -25,7 +25,7 @@ where /// Tests if `swap_exact_out` performs a fair swap /// and produces correct result. /// Tests swap of the token at index 0 to token at index 1 -/// +/// /// NOTE: When token_decimals[0] > token_decimals[1], the method tests if /// `swap_amount_out` is approximatelly correct (`+/- 10^(token_decimals[0] - token_decimals[1])`) and /// always in the protocols favour. @@ -118,8 +118,7 @@ fn test_swap_exact_out( "Amount out mismatch", ); assert!( - swap_amount_out <= - swap_exact_in_result.0, + swap_amount_out <= swap_exact_in_result.0, "Protocol at loss (amount out)", ); assert_approx( @@ -129,8 +128,7 @@ fn test_swap_exact_out( "Fee mismatch", ); assert!( - swap_exact_out_result.1 <= - swap_exact_in_result.1, + swap_exact_out_result.1 <= swap_exact_in_result.1, "Protocol at loss (fee)", ); @@ -188,14 +186,14 @@ fn test_swap_exact_out( // test when tokens precisions are the same #[drink::test] fn test_01(mut session: Session) { -test_swap_exact_out( + test_swap_exact_out( &mut session, - vec![6, 6], // decimals - vec![100000000000, 100000000000], // initial reserves - 10000, // A - 600_000, // trade fee - 200_000_000, // protocol fee - 100000000, // expected amount out + vec![6, 6], // decimals + vec![100000000000, 100000000000], // initial reserves + 10000, // A + 600_000, // trade fee + 200_000_000, // protocol fee + 100000000, // expected amount out ); } diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs index 452ad0e..9de9653 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs @@ -121,8 +121,8 @@ fn test_01(mut session: Session) { vec![6, 6], // decimals vec![100000000000, 100000000000], // initial reserves 1000, // A - 600_000, // fee BPS - 200_000_000, // protocol fee BPS + 600_000, // trade fee in 1e9 precision + 200_000_000, // protocol fee in 1e9 precision 10000000000, // swap_amount_in Ok(9999495232), // expected out (with fee) ); From 6b4bed89a81e062c7ab06232e95321185c3758a2 Mon Sep 17 00:00:00 2001 From: JanKuczma Date: Mon, 15 Jul 2024 21:40:24 +0200 Subject: [PATCH 28/28] combine swap_exact_in and swap_received tests --- amm/drink-tests/src/stable_swap_tests/mod.rs | 3 +- ..._in.rs => tests_swap_exact_in_received.rs} | 151 ++++++--- .../stable_swap_tests/tests_swap_received.rs | 295 ------------------ 3 files changed, 115 insertions(+), 334 deletions(-) rename amm/drink-tests/src/stable_swap_tests/{tests_swap_exact_in.rs => tests_swap_exact_in_received.rs} (63%) delete mode 100644 amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs diff --git a/amm/drink-tests/src/stable_swap_tests/mod.rs b/amm/drink-tests/src/stable_swap_tests/mod.rs index 2ac0b68..143e50d 100644 --- a/amm/drink-tests/src/stable_swap_tests/mod.rs +++ b/amm/drink-tests/src/stable_swap_tests/mod.rs @@ -1,9 +1,8 @@ mod tests_add_remove_lp; mod tests_getters; mod tests_rated; -mod tests_swap_exact_in; +mod tests_swap_exact_in_received; mod tests_swap_exact_out; -mod tests_swap_received; use crate::stable_pool_contract; pub use crate::utils::*; diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in_received.rs similarity index 63% rename from amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs rename to amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in_received.rs index 010ced3..b4ec0d4 100644 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in.rs +++ b/amm/drink-tests/src/stable_swap_tests/tests_swap_exact_in_received.rs @@ -3,6 +3,7 @@ use drink::{self, runtime::MinimalRuntime, session::Session}; use super::*; /// Tests swap of token at index 0 to token at index 1. +/// Tests two ways of swapping: swap_exact_in and swap_received fn test_swap_exact_in( session: &mut Session, token_decimals: Vec, @@ -14,101 +15,177 @@ fn test_swap_exact_in( expected_swap_amount_out_total_result: Result, ) { let initial_supply = vec![initial_reserves[0] + swap_amount_in, initial_reserves[1]]; - let (stable_swap, tokens) = setup_stable_swap_with_tokens( + // setup two identical pools + let (stable_swap_1, tokens_1) = setup_stable_swap_with_tokens( session, - token_decimals, + token_decimals.clone(), + initial_supply.clone(), + amp_coef, + trade_fee, + protocol_fee, + BOB, + "foo".as_bytes().to_vec(), + ); + let (stable_swap_2, tokens_2) = setup_stable_swap_with_tokens( + session, + token_decimals.clone(), initial_supply, amp_coef, trade_fee, protocol_fee, BOB, - vec![], + "bar".as_bytes().to_vec(), + ); + _ = stable_swap::add_liquidity( + session, + stable_swap_1, + BOB, + 1, + initial_reserves.to_vec(), + bob(), ); _ = stable_swap::add_liquidity( session, - stable_swap, + stable_swap_2, BOB, 1, initial_reserves.to_vec(), bob(), ); - let swap_result = stable_swap::swap_exact_in( + let swap_result_1 = stable_swap::swap_exact_in( session, - stable_swap, + stable_swap_1, BOB, - tokens[0], // in - tokens[1], // out + tokens_1[0], // in + tokens_1[1], // out swap_amount_in, // amount_in 0, // min_token_out bob(), ); + let _ = psp22_utils::transfer(session, tokens_2[0], stable_swap_2, swap_amount_in, BOB); + + let swap_result_2 = stable_swap::swap_received( + session, + stable_swap_2, + BOB, + tokens_2[0], // in + tokens_2[1], // out + 0, // min_token_out + bob(), + ); + if expected_swap_amount_out_total_result.is_err() { - match swap_result { - Err(ref err) => { - let wrapped_error: Result = Err(err.clone()); - assert_eq!(expected_swap_amount_out_total_result, wrapped_error); - return; - } - Ok(val) => panic!("Should return an error. Return val: {val:?}"), - } + let swap_err_1 = swap_result_1.expect_err("swap_exact_in: Should return an error."); + let swap_err_2 = swap_result_2.expect_err("swap_received: Should return an error."); + let expected_err = expected_swap_amount_out_total_result.err().unwrap(); + assert_eq!(expected_err, swap_err_1); + assert_eq!(expected_err, swap_err_2); + return; } - let (amount_out, fee) = swap_result.unwrap(); let expected_swap_amount_out_total = expected_swap_amount_out_total_result.unwrap(); let expected_fee = expected_swap_amount_out_total * trade_fee as u128 / FEE_DENOM; let expected_swap_amount_out = expected_swap_amount_out_total - expected_fee; let expected_protocol_fee_part = expected_fee * protocol_fee as u128 / FEE_DENOM; + let (amount_out_1, fee_1) = swap_result_1.unwrap(); + let (amount_out_2, fee_2) = swap_result_2.unwrap(); + // check returned amount swapped and fee - assert_eq!(expected_swap_amount_out, amount_out, "Amount out mismatch"); - assert_eq!(expected_fee, fee, "Fee mismatch"); + assert_eq!( + expected_swap_amount_out, amount_out_1, + "swap_exact_in: Amount out mismatch" + ); + assert_eq!(expected_fee, fee_1, "swap_exact_in: Fee mismatch"); + + assert_eq!( + expected_swap_amount_out, amount_out_2, + "swap_received: Amount out mismatch" + ); + assert_eq!(expected_fee, fee_2, "swap_received: Fee mismatch"); // check if reserves were updated properly - let reserves = stable_swap::reserves(session, stable_swap); + let expected_reserves = [ + initial_reserves[0] + swap_amount_in, + initial_reserves[1] - expected_swap_amount_out, + ]; + let reserves_1 = stable_swap::reserves(session, stable_swap_1); + assert_eq!( + reserves_1, expected_reserves, + "swap_exact_in: Reserves not updated properly" + ); + + let reserves_2 = stable_swap::reserves(session, stable_swap_1); assert_eq!( - reserves, - [ - initial_reserves[0] + swap_amount_in, - initial_reserves[1] - expected_swap_amount_out - ], - "Reserves not updated properly" + reserves_2, expected_reserves, + "swap_received: Reserves not updated properly" ); // check if reserves are equal the actual balances - let balance_0 = psp22_utils::balance_of(session, tokens[0], stable_swap); - let balance_1 = psp22_utils::balance_of(session, tokens[1], stable_swap); + let balance_0 = psp22_utils::balance_of(session, tokens_1[0], stable_swap_1); + let balance_1 = psp22_utils::balance_of(session, tokens_1[1], stable_swap_1); + assert_eq!( + reserves_1, + vec![balance_0, balance_1], + "swap_exact_in: Balances - reserves mismatch" + ); + let balance_0 = psp22_utils::balance_of(session, tokens_2[0], stable_swap_2); + let balance_1 = psp22_utils::balance_of(session, tokens_2[1], stable_swap_2); assert_eq!( - reserves, + reserves_2, vec![balance_0, balance_1], - "Balances - reserves mismatch" + "swap_received: Balances - reserves mismatch" ); // check bobs balances - let balance_0 = psp22_utils::balance_of(session, tokens[0], bob()); - let balance_1 = psp22_utils::balance_of(session, tokens[1], bob()); + let balance_0 = psp22_utils::balance_of(session, tokens_1[0], bob()); + let balance_1 = psp22_utils::balance_of(session, tokens_1[1], bob()); + assert_eq!( + [0, expected_swap_amount_out], + [balance_0, balance_1], + "swap_exact_in: Incorrect Bob's balances" + ); + let balance_0 = psp22_utils::balance_of(session, tokens_2[0], bob()); + let balance_1 = psp22_utils::balance_of(session, tokens_2[1], bob()); assert_eq!( [0, expected_swap_amount_out], [balance_0, balance_1], - "Incorrect Bob's balances" + "swap_received: Incorrect Bob's balances" ); // check protocol fee - let protocol_fee_lp = psp22_utils::balance_of(session, stable_swap, fee_receiver()); + let protocol_fee_lp = psp22_utils::balance_of(session, stable_swap_1, fee_receiver()); + let (total_lp_required, lp_fee_part) = stable_swap::remove_liquidity_by_amounts( + session, + stable_swap_1, + BOB, + protocol_fee_lp * 2, + [0, expected_protocol_fee_part].to_vec(), + bob(), + ) + .expect("swap_exact_in: Should remove liquidity"); + assert_eq!( + total_lp_required - lp_fee_part, + protocol_fee_lp, + "swap_exact_in: Incorrect protocol fee" + ); + + let protocol_fee_lp = psp22_utils::balance_of(session, stable_swap_2, fee_receiver()); let (total_lp_required, lp_fee_part) = stable_swap::remove_liquidity_by_amounts( session, - stable_swap, + stable_swap_2, BOB, protocol_fee_lp * 2, [0, expected_protocol_fee_part].to_vec(), bob(), ) - .expect("Should remove lp"); + .expect("swap_received: Should remove liquidity"); assert_eq!( total_lp_required - lp_fee_part, protocol_fee_lp, - "Incorrect protocol fee" + "swap_received: Incorrect protocol fee" ); } diff --git a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs b/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs deleted file mode 100644 index 9de9653..0000000 --- a/amm/drink-tests/src/stable_swap_tests/tests_swap_received.rs +++ /dev/null @@ -1,295 +0,0 @@ -use drink::{self, runtime::MinimalRuntime, session::Session}; - -use super::*; - -/// Tests swap of token at index 0 to token at index 1. -fn test_swap_received( - session: &mut Session, - token_decimals: Vec, - initial_reserves: Vec, - amp_coef: u128, - trad_fee: u32, - protocol_fee: u32, - swap_amount_in: u128, - expected_swap_amount_out_total_result: Result, -) { - let initial_supply = vec![initial_reserves[0] + swap_amount_in, initial_reserves[1]]; - let (stable_swap, tokens) = setup_stable_swap_with_tokens( - session, - token_decimals, - initial_supply, - amp_coef, - trad_fee, - protocol_fee, - BOB, - vec![], - ); - _ = stable_swap::add_liquidity( - session, - stable_swap, - BOB, - 1, - initial_reserves.to_vec(), - bob(), - ); - - let _ = psp22_utils::transfer(session, tokens[0], stable_swap, swap_amount_in, BOB); - - let swap_result = stable_swap::swap_received( - session, - stable_swap, - BOB, - tokens[0], // in - tokens[1], // out - 0, // min_token_out - bob(), - ); - - if expected_swap_amount_out_total_result.is_err() { - match swap_result { - Err(err) => { - let wrapped_error: Result = Err(err); - assert_eq!(expected_swap_amount_out_total_result, wrapped_error); - return; - } - Ok(val) => panic!("Should return an error. Return val: {val:?}"), - } - } - - let (amount_out, fee) = swap_result.unwrap(); - let expected_swap_amount_out_total = expected_swap_amount_out_total_result.unwrap(); - let expected_fee = expected_swap_amount_out_total * trad_fee as u128 / FEE_DENOM; - let expected_swap_amount_out = expected_swap_amount_out_total - expected_fee; - let expected_protocol_fee_part = expected_fee * protocol_fee as u128 / FEE_DENOM; - - // check returned amount swapped and fee - assert_eq!(expected_swap_amount_out, amount_out, "Amount out mismatch"); - assert_eq!(expected_fee, fee, "Fee mismatch"); - - // check if reserves were updated properly - let reserves = stable_swap::reserves(session, stable_swap); - assert_eq!( - reserves, - [ - initial_reserves[0] + swap_amount_in, - initial_reserves[1] - expected_swap_amount_out - ], - "Reserves not updated properly" - ); - - // check if reserves are equal the actual balances - let balance_0 = psp22_utils::balance_of(session, tokens[0], stable_swap); - let balance_1 = psp22_utils::balance_of(session, tokens[1], stable_swap); - assert_eq!( - reserves, - vec![balance_0, balance_1], - "Balances - reserves mismatch" - ); - - // check bobs balances - let balance_0 = psp22_utils::balance_of(session, tokens[0], bob()); - let balance_1 = psp22_utils::balance_of(session, tokens[1], bob()); - assert_eq!( - [0, expected_swap_amount_out], - [balance_0, balance_1], - "Incorrect Bob's balances" - ); - - // check protocol fee - let protocol_fee_lp = psp22_utils::balance_of(session, stable_swap.into(), fee_receiver()); - let (total_lp_required, lp_fee_part) = stable_swap::remove_liquidity_by_amounts( - session, - stable_swap.into(), - BOB, - protocol_fee_lp * 2, - [0, expected_protocol_fee_part].to_vec(), - bob(), - ) - .expect("Should remove lp"); - assert_eq!( - total_lp_required - lp_fee_part, - protocol_fee_lp, - "Incorrect protocol fee" - ); -} - -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L744 -#[drink::test] -fn test_01(mut session: Session) { - test_swap_received( - &mut session, - vec![6, 6], // decimals - vec![100000000000, 100000000000], // initial reserves - 1000, // A - 600_000, // trade fee in 1e9 precision - 200_000_000, // protocol fee in 1e9 precision - 10000000000, // swap_amount_in - Ok(9999495232), // expected out (with fee) - ); -} - -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L763 -#[drink::test] -fn test_02(mut session: Session) { - test_swap_received( - &mut session, - vec![12, 18], - vec![100000000000000000, 100000000000000000000000], - 1000, - 600_000, - 200_000_000, - 10000000000000000, - Ok(9999495232752197989995), - ); -} - -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L782 -#[drink::test] -fn test_03(mut session: Session) { - test_swap_received( - &mut session, - vec![6, 6], - vec![100000000000, 100000000000], - 1000, - 600_000, - 200_000_000, - 0, - Err(StablePoolError::InsufficientInputAmount()), - ); -} - -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L801 -#[drink::test] -fn test_04(mut session: Session) { - test_swap_received( - &mut session, - vec![12, 18], - vec![100000000000000000, 100000000000000000000000], - 1000, - 600_000, - 200_000_000, - 0, - Err(StablePoolError::InsufficientInputAmount()), - ); -} - -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L820 -#[drink::test] -fn test_05(mut session: Session) { - test_swap_received( - &mut session, - vec![6, 6], - vec![100000000000, 100000000000], - 1000, - 600_000, - 200_000_000, - 1, - Ok(0), - ); -} - -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L839 -// Test that swapping 0.000000000001000000 gives 0.000000000000 (token precision cut) -#[drink::test] -fn test_06_a(mut session: Session) { - test_swap_received( - &mut session, - vec![18, 12], - vec![100000000000000000000000, 100000000000000000], - 1000, - 600_000, - 200_000_000, - 1000000, - Ok(0), - ); -} - -// Test that swapping (with disabled fees) 0.000000000001000000 gives 0.000000000000 -#[drink::test] -fn test_06_b(mut session: Session) { - test_swap_received( - &mut session, - vec![18, 12], - vec![100000000000000000000000, 100000000000000000], - 1000, - 0, - 0, - 1000000, - Ok(0), - ); -} - -/// Test that swapping (with disabled fees) 0.000000000001000001 gives 0.000000000001 -#[drink::test] -fn test_06_c(mut session: Session) { - test_swap_received( - &mut session, - vec![18, 12], - vec![100000000000000000000000, 100000000000000000], - 1000, - 0, - 0, - 1000001, - Ok(1), - ); -} - -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L858 -#[drink::test] -fn test_07(mut session: Session) { - test_swap_received( - &mut session, - vec![6, 6], - vec![100000000000, 100000000000], - 1000, - 600_000, - 200_000_000, - 100000000000, - Ok(98443663539), - ); -} - -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L877 -#[drink::test] -fn test_08(mut session: Session) { - test_swap_received( - &mut session, - vec![12, 18], - vec![100000000000000000, 100000000000000000000000], - 1000, - 600_000, - 200_000_000, - 100000000000000000, - Ok(98443663539913153080656), - ); -} - -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L896 -#[drink::test] -fn test_09(mut session: Session) { - test_swap_received( - &mut session, - vec![6, 6], - vec![100000000000, 100000000000], - 1000, - 600_000, - 200_000_000, - 99999000000 + 1, // +1 because of accounting for fee rounding - Ok(98443167413), - ); -} - -// ref https://github.com/ref-finance/ref-contracts/blob/d241d7aeaa6250937b160d56e5c4b5b48d9d97f7/ref-exchange/src/stable_swap/mod.rs#L915 -#[drink::test] -fn test_10(mut session: Session) { - test_swap_received( - &mut session, - vec![12, 18], - vec![100000000000000000, 100000000000000000000000], - 1000, - 600_000, - 200_000_000, - 99999000000000000, - Ok(98443167413204135506296), - ); -}