From ff1b1bf0faebb17c3ab940dc5756b675d4627976 Mon Sep 17 00:00:00 2001 From: Sniezka Date: Tue, 28 Nov 2023 19:23:23 +0100 Subject: [PATCH 1/7] Refactored creating fee tiers --- src/lib.rs | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 98cc2c3b..fafc0bdf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1228,10 +1228,11 @@ pub mod contract { mint_with_aprove_for_bob!(client, TokenRef, token_x, dex, amount); approve!(client, TokenRef, token_y, dex, u64::MAX as u128, bob); - let fee = Percentage::from_scale(6, 3); - let tick_spacing = 1; + let fee_tier = FeeTier { + fee: Percentage::from_scale(6, 3), + tick_spacing: 1, + }; - let fee_tier = FeeTier { fee, tick_spacing }; create_fee_tier!(client, ContractRef, dex, fee_tier, alice); let init_tick = 0; @@ -1367,13 +1368,13 @@ pub mod contract { approve!(client, TokenRef, token_x, dex, u128::MAX, alice); approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - let fee = Percentage::from_scale(6, 3); - let tick_spacing = 1; - - let fee_tier = FeeTier { fee, tick_spacing }; + let fee_tier = FeeTier { + fee: Percentage::from_scale(6, 3), + tick_spacing: 1, + }; create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - let init_tick = get_max_tick(tick_spacing); + let init_tick = get_max_tick(1); create_pool!( client, ContractRef, @@ -1417,13 +1418,13 @@ pub mod contract { approve!(client, TokenRef, token_x, dex, u128::MAX, alice); approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - let fee = Percentage::from_scale(6, 3); - let tick_spacing = 1; - - let fee_tier = FeeTier { fee, tick_spacing }; + let fee_tier = FeeTier { + fee: Percentage::from_scale(6, 3), + tick_spacing: 1, + }; create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - let init_tick = get_max_tick(tick_spacing); + let init_tick = get_max_tick(1); create_pool!( client, ContractRef, @@ -1690,6 +1691,7 @@ pub mod contract { approve!(client, TokenRef, token_y, dex, mint_amount, alice); let liquidity = Liquidity::from_integer(10000000); + let fee_tier = FeeTier { fee: Percentage::from_scale(6, 3), tick_spacing: 10, @@ -2575,8 +2577,6 @@ pub mod contract { ); let second_position = get_position!(client, ContractRef, dex, 4, alice).unwrap(); - println!("First position = {:?}", first_position); - println!("Seconds position = {:?}", second_position); // Check second position assert!(second_position.pool_key == pool_key); @@ -3710,12 +3710,12 @@ pub mod contract { assert_eq!(pool.liquidity, liquidity_delta); - let limit_wihtout_cross_tick_amount = TokenAmount(10_068); + let limit_without_cross_tick_amount = TokenAmount(10_068); let not_cross_amount = TokenAmount(1); let min_amount_to_cross_from_tick_price = TokenAmount(3); let crossing_amount_by_amount_out = TokenAmount(20136101434); - let mint_amount = limit_wihtout_cross_tick_amount.get() + let mint_amount = limit_without_cross_tick_amount.get() + not_cross_amount.get() + min_amount_to_cross_from_tick_price.get() + crossing_amount_by_amount_out.get(); @@ -3737,7 +3737,7 @@ pub mod contract { dex, pool_key, true, - limit_wihtout_cross_tick_amount, + limit_without_cross_tick_amount, true, limit_sqrt_price, alice @@ -3943,12 +3943,12 @@ pub mod contract { assert_eq!(pool.liquidity, liquidity_delta); - let limit_wihtout_cross_tick_amount = TokenAmount(10_068); + let limit_without_cross_tick_amount = TokenAmount(10_068); let not_cross_amount = TokenAmount(1); let min_amount_to_cross_from_tick_price = TokenAmount(3); let crossing_amount_by_amount_out = TokenAmount(20136101434); - let mint_amount = limit_wihtout_cross_tick_amount.get() + let mint_amount = limit_without_cross_tick_amount.get() + not_cross_amount.get() + min_amount_to_cross_from_tick_price.get() + crossing_amount_by_amount_out.get(); @@ -3970,7 +3970,7 @@ pub mod contract { dex, pool_key, true, - limit_wihtout_cross_tick_amount, + limit_without_cross_tick_amount, true, limit_sqrt_price, alice From 85973f429faca8fb8895892910edadb8c4a7155e Mon Sep 17 00:00:00 2001 From: Sniezka Date: Tue, 28 Nov 2023 19:40:59 +0100 Subject: [PATCH 2/7] Added assertions at the end of full range test --- src/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index fafc0bdf..64380d55 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1406,6 +1406,15 @@ pub mod contract { slippage_limit_upper, alice ); + + let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); + let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); + println!("X = {:?} | Y = {:?}", contract_amount_x, contract_amount_y); + + let expected_x = 0; + let expected_y = 42534896005851865508212194815854; + assert_eq!(contract_amount_x, expected_x); + assert_eq!(contract_amount_y, expected_y); } #[ink_e2e::test] From 2fba71c327c2a378a7ecea95320096382069e7ba Mon Sep 17 00:00:00 2001 From: Sniezka Date: Tue, 28 Nov 2023 21:07:50 +0100 Subject: [PATCH 3/7] Added fee tier constructor and found max tick crosses --- src/contracts/storage/fee_tier.rs | 6 ++ src/lib.rs | 151 +++++++----------------------- 2 files changed, 42 insertions(+), 115 deletions(-) diff --git a/src/contracts/storage/fee_tier.rs b/src/contracts/storage/fee_tier.rs index ec7c7e73..1babbdfd 100644 --- a/src/contracts/storage/fee_tier.rs +++ b/src/contracts/storage/fee_tier.rs @@ -8,3 +8,9 @@ pub struct FeeTier { pub fee: Percentage, pub tick_spacing: u16, } + +impl FeeTier { + pub fn new(fee: Percentage, tick_spacing: u16) -> FeeTier { + FeeTier { fee, tick_spacing } + } +} diff --git a/src/lib.rs b/src/lib.rs index 64380d55..a0762836 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1228,10 +1228,7 @@ pub mod contract { mint_with_aprove_for_bob!(client, TokenRef, token_x, dex, amount); approve!(client, TokenRef, token_y, dex, u64::MAX as u128, bob); - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 1, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); create_fee_tier!(client, ContractRef, dex, fee_tier, alice); @@ -1368,10 +1365,7 @@ pub mod contract { approve!(client, TokenRef, token_x, dex, u128::MAX, alice); approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 1, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); create_fee_tier!(client, ContractRef, dex, fee_tier, alice); let init_tick = get_max_tick(1); @@ -1409,7 +1403,6 @@ pub mod contract { let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); - println!("X = {:?} | Y = {:?}", contract_amount_x, contract_amount_y); let expected_x = 0; let expected_y = 42534896005851865508212194815854; @@ -1418,7 +1411,7 @@ pub mod contract { } #[ink_e2e::test] - async fn limits_swap_at_upper_limit(mut client: ink_e2e::Client) -> E2EResult<()> { + async fn deposit_limits_at_upper_limit(mut client: ink_e2e::Client) -> E2EResult<()> { let (dex, token_x, token_y) = init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); @@ -1427,10 +1420,7 @@ pub mod contract { approve!(client, TokenRef, token_x, dex, u128::MAX, alice); approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 1, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); create_fee_tier!(client, ContractRef, dex, fee_tier, alice); let init_tick = get_max_tick(1); @@ -1490,10 +1480,7 @@ pub mod contract { approve!(client, TokenRef, token_x, dex, u128::MAX, alice); approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 1, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); create_fee_tier!(client, ContractRef, dex, fee_tier, alice); let init_tick = 0; @@ -1623,10 +1610,8 @@ pub mod contract { approve!(client, TokenRef, token_x, dex, u128::MAX, alice); approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 1, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); let init_tick = 0; @@ -1694,20 +1679,18 @@ pub mod contract { let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - let mint_amount = 10u128.pow(10); + let mint_amount = u128::MAX; let alice = ink_e2e::alice(); approve!(client, TokenRef, token_x, dex, mint_amount, alice); approve!(client, TokenRef, token_y, dex, mint_amount, alice); let liquidity = Liquidity::from_integer(10000000); - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - for i in (-200..20).step_by(10) { + for i in (-2560..20).step_by(10) { let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); let slippage_limit_lower = pool.sqrt_price; @@ -1730,7 +1713,7 @@ pub mod contract { let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); assert_eq!(pool.liquidity, liquidity); - let amount = 95000; + let amount = 760_000; let bob = ink_e2e::bob(); mint!(TokenRef, client, token_x, Bob, amount); let amount_x = balance_of!(TokenRef, client, token_x, Bob); @@ -1775,7 +1758,7 @@ pub mod contract { let crosses_after_quote = ((pool_after_quote.current_tick_index - pool_before.current_tick_index) / 10).abs(); assert_eq!(crosses_after_quote, 0); - assert_eq!(quote_result.3.len() - 1, 19); + assert_eq!(quote_result.3.len() - 1, 146); swap!( client, @@ -1801,7 +1784,7 @@ pub mod contract { let crosses = ((pool_after.current_tick_index - pool_before.current_tick_index) / 10).abs(); - assert_eq!(crosses, 19); + assert_eq!(crosses, 146); assert_eq!( pool_after.current_tick_index, get_tick_at_sqrt_price(quote_result.2, 10).unwrap() @@ -1816,10 +1799,8 @@ pub mod contract { init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); let amount = 1000; @@ -1851,10 +1832,7 @@ pub mod contract { init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); let alice = ink_e2e::alice(); let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); @@ -1966,10 +1944,7 @@ pub mod contract { init_cross_position!(client, ContractRef, TokenRef, dex, token_x, token_y); init_cross_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); let alice = ink_e2e::alice(); @@ -2023,10 +1998,7 @@ pub mod contract { init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); let alice = ink_e2e::alice(); withdraw_protocol_fee!(client, ContractRef, dex, pool_key, alice); @@ -2156,10 +2128,7 @@ pub mod contract { let alice = ink_e2e::alice(); - let fee_tier = FeeTier { - fee: Percentage::new(0), - tick_spacing: 1, - }; + let fee_tier = FeeTier::new(Percentage::new(0), 1); create_fee_tier!(client, ContractRef, dex, fee_tier, alice); @@ -2189,10 +2158,7 @@ pub mod contract { #[ink_e2e::test] async fn create_fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let fee_tier = FeeTier { - fee: Percentage::new(0), - tick_spacing: 10u16, - }; + let fee_tier = FeeTier::new(Percentage::new(0), 10u16); let alice = ink_e2e::alice(); create_fee_tier!(client, ContractRef, dex, fee_tier, alice); let fee_tier = get_fee_tier!(client, ContractRef, dex, Percentage::new(0), 10u16); @@ -2220,10 +2186,7 @@ pub mod contract { let dex = create_dex!(client, ContractRef, Percentage::new(0)); let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); - let fee_tier = FeeTier { - fee: Percentage::from_scale(5, 1), - tick_spacing: 100, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); let init_tick = 0; let alice = ink_e2e::alice(); @@ -2249,10 +2212,7 @@ pub mod contract { async fn fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { let dex = create_dex!(client, ContractRef, Percentage::new(0)); let admin = ink_e2e::alice(); - let fee_tier = FeeTier { - fee: Percentage::from_scale(5, 1), - tick_spacing: 100, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); let result = create_fee_tier!(client, ContractRef, dex, fee_tier, admin); assert!(result.is_ok()); Ok(()) @@ -2263,10 +2223,7 @@ pub mod contract { let dex = create_dex!(client, ContractRef, Percentage::new(0)); let admin = ink_e2e::alice(); // 0 tick spacing | should fail - let fee_tier = FeeTier { - fee: Percentage::from_scale(5, 1), - tick_spacing: 0, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 0); let result = create_fee_tier!(client, ContractRef, dex, fee_tier, admin); } @@ -2276,10 +2233,7 @@ pub mod contract { let dex = create_dex!(client, ContractRef, Percentage::new(0)); let user = ink_e2e::bob(); // not-admin - let fee_tier = FeeTier { - fee: Percentage::from_scale(5, 1), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 10); let result = create_fee_tier!(client, ContractRef, dex, fee_tier, user); } @@ -2296,10 +2250,7 @@ pub mod contract { let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - let fee_tier = FeeTier { - fee: Percentage::from_scale(2, 4), - tick_spacing: 4, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); create_fee_tier!(client, ContractRef, dex, fee_tier, alice); @@ -2403,10 +2354,7 @@ pub mod contract { let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - let fee_tier = FeeTier { - fee: Percentage::from_scale(2, 4), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 10); create_fee_tier!(client, ContractRef, dex, fee_tier, alice); @@ -2684,10 +2632,7 @@ pub mod contract { let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - let fee_tier = FeeTier { - fee: Percentage::from_scale(2, 4), - tick_spacing: 4, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); create_fee_tier!(client, ContractRef, dex, fee_tier, alice); @@ -2791,10 +2736,7 @@ pub mod contract { let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - let fee_tier = FeeTier { - fee: Percentage::from_scale(2, 4), - tick_spacing: 4, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); create_fee_tier!(client, ContractRef, dex, fee_tier, alice); @@ -2891,10 +2833,7 @@ pub mod contract { let dex = create_dex!(client, ContractRef, Percentage::new(0)); let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); - let fee_tier = FeeTier { - fee: Percentage::from_scale(5, 1), - tick_spacing: 1, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 1); let init_tick = 0; let alice = ink_e2e::alice(); @@ -2928,10 +2867,7 @@ pub mod contract { let dex = create_dex!(client, ContractRef, Percentage::new(0)); let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); - let fee_tier = FeeTier { - fee: Percentage::from_scale(5, 1), - tick_spacing: 100, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); let init_tick = 0; let admin = ink_e2e::alice(); @@ -2957,10 +2893,7 @@ pub mod contract { #[ink_e2e::test] async fn remove_position_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); let alice = ink_e2e::alice(); let bob = ink_e2e::bob(); let init_tick = 0; @@ -3294,10 +3227,7 @@ pub mod contract { #[ink_e2e::test] #[should_panic] async fn no_liquidity_swap(mut client: ink_e2e::Client) -> () { - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); let alice = ink_e2e::alice(); let bob = ink_e2e::bob(); let init_tick = 0; @@ -3449,10 +3379,7 @@ pub mod contract { #[ink_e2e::test] async fn liquidity_gap_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); let alice = ink_e2e::alice(); let bob = ink_e2e::bob(); let init_tick = 0; @@ -3646,10 +3573,7 @@ pub mod contract { #[ink_e2e::test] async fn cross_both_side_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); let alice = ink_e2e::alice(); let bob = ink_e2e::bob(); let init_tick = 0; @@ -3879,10 +3803,7 @@ pub mod contract { #[ink_e2e::test] #[should_panic] async fn cross_both_side_not_cross_case_test(mut client: ink_e2e::Client) -> () { - let fee_tier = FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 10, - }; + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); let alice = ink_e2e::alice(); let bob = ink_e2e::bob(); let init_tick = 0; From 414d4cb518a41572f416b9d00cd948aea37f2413 Mon Sep 17 00:00:00 2001 From: Sniezka Date: Tue, 28 Nov 2023 21:42:23 +0100 Subject: [PATCH 4/7] Added missing test --- src/lib.rs | 5473 +++++++++++++++++++++++++++------------------------- 1 file changed, 2810 insertions(+), 2663 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a0762836..1b1a944d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1214,2406 +1214,32 @@ pub mod contract { type E2EResult = Result>; #[ink_e2e::test] - async fn swap_route(mut client: ink_e2e::Client) -> E2EResult<()> { - let (dex, token_x, token_y, token_z) = - init_dex_and_3_tokens!(client, ContractRef, TokenRef); - - let alice = ink_e2e::alice(); - approve!(client, TokenRef, token_x, dex, u64::MAX as u128, alice); - approve!(client, TokenRef, token_y, dex, u64::MAX as u128, alice); - approve!(client, TokenRef, token_z, dex, u64::MAX as u128, alice); - - let amount = 1000; - let bob = ink_e2e::bob(); - mint_with_aprove_for_bob!(client, TokenRef, token_x, dex, amount); - approve!(client, TokenRef, token_y, dex, u64::MAX as u128, bob); - - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let init_tick = 0; - create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - let init_tick = 0; - create_pool!( - client, - ContractRef, - dex, - token_y, - token_z, - fee_tier, - init_tick - ); - - let pool_key_1 = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let pool_key_2 = PoolKey::new(token_y, token_z, fee_tier).unwrap(); - - let liquidity_delta = Liquidity::new(2u128.pow(63) - 1); - - let pool_1 = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let slippage_limit_lower = pool_1.sqrt_price; - let slippage_limit_upper = pool_1.sqrt_price; - create_position!( - client, - ContractRef, - dex, - pool_key_1, - -1, - 1, - liquidity_delta, - slippage_limit_lower, - slippage_limit_upper, - alice - ); - - let pool_2 = get_pool!(client, ContractRef, dex, token_y, token_z, fee_tier).unwrap(); - let slippage_limit_lower = pool_2.sqrt_price; - let slippage_limit_upper = pool_2.sqrt_price; - create_position!( - client, - ContractRef, - dex, - pool_key_2, - -1, - 1, - liquidity_delta, - slippage_limit_lower, - slippage_limit_upper, - alice - ); - - let amount_in = TokenAmount(1000); - let expected_amount_out = TokenAmount(1000); - let slippage = Percentage::new(0); - let swaps = vec![ - Hop { - pool_key: pool_key_1, - x_to_y: true, - }, - Hop { - pool_key: pool_key_2, - x_to_y: true, - }, - ]; - - let expected_token_amount = - quote_route!(client, ContractRef, dex, amount_in, swaps.clone(), bob).unwrap(); - - swap_route!( - client, - ContractRef, - dex, - amount_in, - expected_token_amount, - slippage, - swaps.clone(), - bob - ); - - let bob_amount_x = balance_of!(TokenRef, client, token_x, Bob); - let bob_amount_y = balance_of!(TokenRef, client, token_y, Bob); - let bob_amount_z = balance_of!(TokenRef, client, token_z, Bob); - - assert_eq!(bob_amount_x, 0); - assert_eq!(bob_amount_y, 0); - assert_eq!(bob_amount_z, 986); - - let pool_1_after = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - assert_eq!(pool_1_after.fee_protocol_token_x, TokenAmount(1)); - assert_eq!(pool_1_after.fee_protocol_token_y, TokenAmount(0)); - - let pool_2_after = - get_pool!(client, ContractRef, dex, token_y, token_z, fee_tier).unwrap(); - assert_eq!(pool_2_after.fee_protocol_token_x, TokenAmount(1)); - assert_eq!(pool_2_after.fee_protocol_token_y, TokenAmount(0)); - - let alice_amount_x_before = balance_of!(TokenRef, client, token_x, Alice); - let alice_amount_y_before = balance_of!(TokenRef, client, token_y, Alice); - let alice_amount_z_before = balance_of!(TokenRef, client, token_z, Alice); - - claim_fee!(client, ContractRef, dex, 0, alice); - claim_fee!(client, ContractRef, dex, 1, alice); - - let alice_amount_x_after = balance_of!(TokenRef, client, token_x, Alice); - let alice_amount_y_after = balance_of!(TokenRef, client, token_y, Alice); - let alice_amount_z_after = balance_of!(TokenRef, client, token_z, Alice); - - assert_eq!(alice_amount_x_after - alice_amount_x_before, 4); - assert_eq!(alice_amount_y_after - alice_amount_y_before, 4); - assert_eq!(alice_amount_z_after - alice_amount_z_before, 0); - - Ok(()) - } - - #[ink_e2e::test] - async fn limits_full_range_with_max_liquidity(mut client: ink_e2e::Client) -> () { - let (dex, token_x, token_y) = - init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); - - let mint_amount = u128::MAX; - let alice = ink_e2e::alice(); - approve!(client, TokenRef, token_x, dex, u128::MAX, alice); - approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let init_tick = get_max_tick(1); - create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let current_sqrt_price = pool.sqrt_price; - assert_eq!(pool.current_tick_index, init_tick); - assert_eq!(pool.sqrt_price, calculate_sqrt_price(init_tick).unwrap()); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let liquidity_delta = Liquidity::new(2u128.pow(109) - 1); - let slippage_limit_lower = pool.sqrt_price; - let slippage_limit_upper = pool.sqrt_price; - create_position!( - client, - ContractRef, - dex, - pool_key, - -MAX_TICK, - MAX_TICK, - liquidity_delta, - slippage_limit_lower, - slippage_limit_upper, - alice - ); - - let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); - let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); - - let expected_x = 0; - let expected_y = 42534896005851865508212194815854; - assert_eq!(contract_amount_x, expected_x); - assert_eq!(contract_amount_y, expected_y); - } - - #[ink_e2e::test] - async fn deposit_limits_at_upper_limit(mut client: ink_e2e::Client) -> E2EResult<()> { - let (dex, token_x, token_y) = - init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); - - let mint_amount = 2u128.pow(105) - 1; - let alice = ink_e2e::alice(); - approve!(client, TokenRef, token_x, dex, u128::MAX, alice); - approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let init_tick = get_max_tick(1); - create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let current_sqrt_price = pool.sqrt_price; - assert_eq!(pool.current_tick_index, init_tick); - assert_eq!(pool.sqrt_price, calculate_sqrt_price(init_tick).unwrap()); - - let position_amount = mint_amount - 1; - - let liquidity_delta = get_liquidity_by_y( - TokenAmount(position_amount), - 0, - MAX_TICK, - pool.sqrt_price, - false, - ) - .unwrap() - .l; - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let slippage_limit_lower = pool.sqrt_price; - let slippage_limit_upper = pool.sqrt_price; - create_position!( - client, - ContractRef, - dex, - pool_key, - 0, - MAX_TICK, - liquidity_delta, - slippage_limit_lower, - slippage_limit_upper, - alice - ); - - Ok(()) - } - - #[ink_e2e::test] - async fn limits_big_deposit_and_swaps(mut client: ink_e2e::Client) -> E2EResult<()> { - let (dex, token_x, token_y) = - init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); - - let mint_amount = 2u128.pow(76) - 1; - let alice = ink_e2e::alice(); - approve!(client, TokenRef, token_x, dex, u128::MAX, alice); - approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let init_tick = 0; - create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - let pos_amount = mint_amount / 2; - let lower_tick = -(fee_tier.tick_spacing as i32); - let upper_tick = fee_tier.tick_spacing as i32; - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - let liquidity_delta = get_liquidity_by_x( - TokenAmount(pos_amount), - lower_tick, - upper_tick, - pool.sqrt_price, - false, - ) - .unwrap() - .l; - - let y = get_delta_y( - calculate_sqrt_price(lower_tick).unwrap(), - pool.sqrt_price, - liquidity_delta, - true, - ) - .unwrap(); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let slippage_limit_lower = pool.sqrt_price; - let slippage_limit_upper = pool.sqrt_price; - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick, - upper_tick, - liquidity_delta, - slippage_limit_lower, - slippage_limit_upper, - alice - ); - - let user_amount_x = balance_of!(TokenRef, client, token_x, Alice); - let user_amount_y = balance_of!(TokenRef, client, token_y, Alice); - assert_eq!(user_amount_x, u128::MAX - pos_amount); - assert_eq!(user_amount_y, u128::MAX - y.get()); - - let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); - let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); - assert_eq!(contract_amount_x, pos_amount); - assert_eq!(contract_amount_y, y.get()); - - let swap_amount = TokenAmount(mint_amount / 8); - - for i in 1..=4 { - let (x_to_y, sqrt_price_limit) = if i % 2 == 0 { - (true, SqrtPrice::new(MIN_SQRT_PRICE)) - } else { - (false, SqrtPrice::new(MAX_SQRT_PRICE)) - }; - - swap!( - client, - ContractRef, - dex, - pool_key, - i % 2 == 0, - swap_amount, - true, - sqrt_price_limit, - alice - ); - } - - Ok(()) - } - - #[ink_e2e::test] - async fn multiple_swap_x_to_y(mut client: ink_e2e::Client) -> E2EResult<()> { - multiple_swap!(client, ContractRef, TokenRef, true); - Ok(()) - } - - #[ink_e2e::test] - async fn limits_big_deposit_x_and_swap_y( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - big_deposit_and_swap!(client, ContractRef, TokenRef, true); - - Ok(()) - } - - #[ink_e2e::test] - async fn multiple_swap_y_to_x(mut client: ink_e2e::Client) -> E2EResult<()> { - multiple_swap!(client, ContractRef, TokenRef, false); - Ok(()) - } - - #[ink_e2e::test] - async fn limits_big_deposit_y_and_swap_x( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - big_deposit_and_swap!(client, ContractRef, TokenRef, false); - - Ok(()) - } - - #[ink_e2e::test] - async fn limits_big_deposit_both_tokens( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - let (dex, token_x, token_y) = - init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); - - let mint_amount = 2u128.pow(75) - 1; - let alice = ink_e2e::alice(); - approve!(client, TokenRef, token_x, dex, u128::MAX, alice); - approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let init_tick = 0; - create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - let lower_tick = -(fee_tier.tick_spacing as i32); - let upper_tick = fee_tier.tick_spacing as i32; - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let liquidity_delta = get_liquidity_by_x( - TokenAmount(mint_amount), - lower_tick, - upper_tick, - pool.sqrt_price, - false, - ) - .unwrap() - .l; - let y = get_delta_y( - calculate_sqrt_price(lower_tick).unwrap(), - pool.sqrt_price, - liquidity_delta, - true, - ) - .unwrap(); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let slippage_limit_lower = pool.sqrt_price; - let slippage_limit_upper = pool.sqrt_price; - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick, - upper_tick, - liquidity_delta, - slippage_limit_lower, - slippage_limit_upper, - alice - ); - - let user_amount_x = balance_of!(TokenRef, client, token_x, Alice); - let user_amount_y = balance_of!(TokenRef, client, token_y, Alice); - assert_eq!(user_amount_x, u128::MAX - mint_amount); - assert_eq!(user_amount_y, u128::MAX - y.get()); - - let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); - let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); - assert_eq!(contract_amount_x, mint_amount); - assert_eq!(contract_amount_y, y.get()); - - Ok(()) - } - - #[ink_e2e::test] - async fn max_tick_cross(mut client: ink_e2e::Client) -> E2EResult<()> { - let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - - let mint_amount = u128::MAX; - let alice = ink_e2e::alice(); - approve!(client, TokenRef, token_x, dex, mint_amount, alice); - approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - let liquidity = Liquidity::from_integer(10000000); - - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - for i in (-2560..20).step_by(10) { - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - let slippage_limit_lower = pool.sqrt_price; - let slippage_limit_upper = pool.sqrt_price; - - create_position!( - client, - ContractRef, - dex, - pool_key, - i, - i + 10, - liquidity, - slippage_limit_lower, - slippage_limit_upper, - alice - ); - } - - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - assert_eq!(pool.liquidity, liquidity); - - let amount = 760_000; - let bob = ink_e2e::bob(); - mint!(TokenRef, client, token_x, Bob, amount); - let amount_x = balance_of!(TokenRef, client, token_x, Bob); - assert_eq!(amount_x, amount); - approve!(client, TokenRef, token_x, dex, amount, bob); - - let pool_before = get_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - pool_key.fee_tier - ) - .unwrap(); - - let swap_amount = TokenAmount::new(amount); - let slippage = SqrtPrice::new(MIN_SQRT_PRICE); - let quote_result = quote!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - slippage, - bob - ) - .unwrap(); - - let pool_after_quote = get_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - pool_key.fee_tier - ) - .unwrap(); - - let crosses_after_quote = - ((pool_after_quote.current_tick_index - pool_before.current_tick_index) / 10).abs(); - assert_eq!(crosses_after_quote, 0); - assert_eq!(quote_result.3.len() - 1, 146); - - swap!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - slippage, - bob - ); - - let pool_after = get_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - pool_key.fee_tier - ) - .unwrap(); - - let crosses = - ((pool_after.current_tick_index - pool_before.current_tick_index) / 10).abs(); - assert_eq!(crosses, 146); - assert_eq!( - pool_after.current_tick_index, - get_tick_at_sqrt_price(quote_result.2, 10).unwrap() - ); - - Ok(()) - } - - #[ink_e2e::test] - async fn swap_exact_limit(mut client: ink_e2e::Client) -> E2EResult<()> { - let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - let amount = 1000; - let bob = ink_e2e::bob(); - mint!(TokenRef, client, token_x, Bob, amount); - let amount_x = balance_of!(TokenRef, client, token_x, Bob); - assert_eq!(amount_x, amount); - approve!(client, TokenRef, token_x, dex, amount, bob); - - let swap_amount = TokenAmount::new(amount); - swap_exact_limit!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - bob - ); - - Ok(()) - } - - #[ink_e2e::test] - async fn claim(mut client: ink_e2e::Client) -> E2EResult<()> { - let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let alice = ink_e2e::alice(); - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let user_amount_before_claim = balance_of!(TokenRef, client, token_x, Alice); - let dex_amount_before_claim = dex_balance!(TokenRef, client, token_x, dex); - - claim_fee!(client, ContractRef, dex, 0, alice); - - let user_amount_after_claim = balance_of!(TokenRef, client, token_x, Alice); - let dex_amount_after_claim = dex_balance!(TokenRef, client, token_x, dex); - let position = get_position!(client, ContractRef, dex, 0, alice).unwrap(); - let expected_tokens_claimed = 5; - - assert_eq!( - user_amount_after_claim - expected_tokens_claimed, - user_amount_before_claim - ); - assert_eq!( - dex_amount_after_claim + expected_tokens_claimed, - dex_amount_before_claim - ); - assert_eq!(position.fee_growth_inside_x, pool.fee_growth_global_x); - assert_eq!(position.tokens_owed_x, TokenAmount(0)); - - Ok(()) - } - - #[ink_e2e::test] - async fn basic_slippage_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let alice = ink_e2e::alice(); - let (dex, token_x, token_y) = - init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); - let pool_key = create_slippage_pool_with_liquidity!( - client, - ContractRef, - TokenRef, - dex, - token_x, - token_y - ); - let amount = 10u128.pow(8); - let swap_amount = TokenAmount::new(amount); - approve!(client, TokenRef, token_x, dex, amount, alice); - - let target_sqrt_price = SqrtPrice::new(1009940000000000000000001); - swap!( - client, - ContractRef, - dex, - pool_key, - false, - swap_amount, - true, - target_sqrt_price, - alice - ); - let expected_sqrt_price = SqrtPrice::new(1009940000000000000000000); - let pool = get_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - pool_key.fee_tier - ) - .unwrap(); - - assert_eq!(expected_sqrt_price, pool.sqrt_price); - Ok(()) - } - - #[ink_e2e::test] - #[should_panic] - async fn swap_close_to_limit_test(mut client: ink_e2e::Client) -> () { - let alice = ink_e2e::alice(); - let (dex, token_x, token_y) = - init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); - let pool_key = create_slippage_pool_with_liquidity!( - client, - ContractRef, - TokenRef, - dex, - token_x, - token_y - ); - let amount = 10u128.pow(8); - let swap_amount = TokenAmount::new(amount); - approve!(client, TokenRef, token_x, dex, amount, alice); - - let target_sqrt_price = calculate_sqrt_price(-98).unwrap(); - swap!( - client, - ContractRef, - dex, - pool_key, - false, - swap_amount, - true, - target_sqrt_price, - alice - ); - } - - #[ink_e2e::test] - async fn cross(mut client: ink_e2e::Client) -> E2EResult<()> { - let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - init_cross_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - init_cross_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let alice = ink_e2e::alice(); - - let upper_tick_index = 10; - let middle_tick_index = -10; - let lower_tick_index = -20; - - let upper_tick = - get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); - let middle_tick = - get_tick!(client, ContractRef, dex, middle_tick_index, pool_key, alice).unwrap(); - let lower_tick = - get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); - - assert_eq!( - upper_tick.liquidity_change, - Liquidity::from_integer(1000000) - ); - assert_eq!( - middle_tick.liquidity_change, - Liquidity::from_integer(1000000) - ); - assert_eq!( - lower_tick.liquidity_change, - Liquidity::from_integer(1000000) - ); - - assert_eq!(upper_tick.fee_growth_outside_x, FeeGrowth::new(0)); - assert_eq!( - middle_tick.fee_growth_outside_x, - FeeGrowth::new(30000000000000000000000) - ); - assert_eq!(lower_tick.fee_growth_outside_x, FeeGrowth::new(0)); - - Ok(()) - } - - #[ink_e2e::test] - async fn swap(mut client: ink_e2e::Client) -> E2EResult<()> { - let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - Ok(()) - } - - #[ink_e2e::test] - async fn protocol_fee(mut client: ink_e2e::Client) -> E2EResult<()> { - let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let alice = ink_e2e::alice(); - withdraw_protocol_fee!(client, ContractRef, dex, pool_key, alice); - - let amount_x = balance_of!(TokenRef, client, token_x, Alice); - let amount_y = balance_of!(TokenRef, client, token_y, Alice); - assert_eq!(amount_x, 9999999501); - assert_eq!(amount_y, 9999999000); - - let amount_x = dex_balance!(TokenRef, client, token_x, dex); - let amount_y = dex_balance!(TokenRef, client, token_y, dex); - assert_eq!(amount_x, 1499); - assert_eq!(amount_y, 7); - - let pool_after_withdraw = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - assert_eq!( - pool_after_withdraw.fee_protocol_token_x, - TokenAmount::new(0) - ); - assert_eq!( - pool_after_withdraw.fee_protocol_token_y, - TokenAmount::new(0) - ); - - Ok(()) - } - - #[ink_e2e::test] - #[should_panic] - async fn protocol_fee_should_panic(mut client: ink_e2e::Client) -> () { - let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - - let pool_key = PoolKey::new( - token_x, - token_y, - FeeTier { - fee: Percentage::from_scale(6, 3), - tick_spacing: 10, - }, - ) - .unwrap(); - let bob = ink_e2e::bob(); - withdraw_protocol_fee!(client, ContractRef, dex, pool_key, bob); - } - - #[ink_e2e::test] - async fn constructor_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let constructor = TokenRef::new(500, None, None, 0); - let _token: AccountId = client - .instantiate("token", &ink_e2e::alice(), constructor, 0, None) - .await - .expect("Instantiate failed") - .account_id; - - let constructor = ContractRef::new(Percentage::new(0)); - - let _contract: AccountId = client - .instantiate("contract", &ink_e2e::alice(), constructor, 0, None) - .await - .expect("Instantiate failed") - .account_id; - Ok(()) - } - - #[ink_e2e::test] - async fn change_protocol_fee(mut client: ink_e2e::Client) -> E2EResult<()> { - let contract = create_dex!(client, ContractRef, Percentage::new(0)); - - let protocol_fee = { - let _msg = build_message::(contract.clone()) - .call(|contract| contract.get_protocol_fee()); - client - .call(&ink_e2e::alice(), _msg, 0, None) - .await - .expect("getting protocol fee failed") - } - .return_value(); - - assert_eq!(protocol_fee, Percentage::new(0)); - - let _result = { - let _msg = build_message::(contract.clone()) - .call(|contract| contract.change_protocol_fee(Percentage::new(1))); - client - .call(&ink_e2e::alice(), _msg, 0, None) - .await - .expect("changing protocol fee failed") - }; - - let protocol_fee = { - let _msg = build_message::(contract.clone()) - .call(|contract| contract.get_protocol_fee()); - client - .call(&ink_e2e::alice(), _msg, 0, None) - .await - .expect("getting protocol fee failed") - } - .return_value(); - - assert_eq!(protocol_fee, Percentage::new(1)); - - Ok(()) - } - - #[ink_e2e::test] - #[should_panic] - async fn change_protocol_fee_should_panic(mut client: ink_e2e::Client) -> () { - let contract = create_dex!(client, ContractRef, Percentage::new(0)); - - let result = { - let _msg = build_message::(contract.clone()) - .call(|contract| contract.change_protocol_fee(Percentage::new(1))); - client - .call(&ink_e2e::bob(), _msg, 0, None) - .await - .expect("changing protocol fee failed") - }; - } - - #[ink_e2e::test] - async fn create_position(mut client: ink_e2e::Client) -> E2EResult<()> { - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); - - let alice = ink_e2e::alice(); - - let fee_tier = FeeTier::new(Percentage::new(0), 1); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let pool = create_pool!(client, ContractRef, dex, token_x, token_y, fee_tier, 10); - - approve!(client, TokenRef, token_x, dex, 500, alice); - approve!(client, TokenRef, token_y, dex, 500, alice); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - let position = create_position!( - client, - ContractRef, - dex, - pool_key, - -10, - 10, - Liquidity::new(10), - SqrtPrice::new(0), - SqrtPrice::max_instance(), - alice - ); - - Ok(()) - } - - #[ink_e2e::test] - async fn create_fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let fee_tier = FeeTier::new(Percentage::new(0), 10u16); - let alice = ink_e2e::alice(); - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - let fee_tier = get_fee_tier!(client, ContractRef, dex, Percentage::new(0), 10u16); - assert!(fee_tier.is_some()); - Ok(()) - } - - #[ink_e2e::test] - async fn create_standard_fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - create_standard_fee_tiers!(client, ContractRef, dex); - let fee_tier = get_fee_tier!( - client, - ContractRef, - dex, - Percentage::from_scale(5, 2), - 100u16 - ); - assert!(fee_tier.is_some()); - Ok(()) - } - - #[ink_e2e::test] - async fn create_pool_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); - - let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); - let init_tick = 0; - - let alice = ink_e2e::alice(); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let result = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - assert!(result.is_ok()); - - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - Ok(()) - } - - #[ink_e2e::test] - async fn fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let admin = ink_e2e::alice(); - let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); - let result = create_fee_tier!(client, ContractRef, dex, fee_tier, admin); - assert!(result.is_ok()); - Ok(()) - } - #[ink_e2e::test] - #[should_panic] - async fn invalid_spacing_fee_tier_test(mut client: ink_e2e::Client) -> () { - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let admin = ink_e2e::alice(); - // 0 tick spacing | should fail - let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 0); - let result = create_fee_tier!(client, ContractRef, dex, fee_tier, admin); - } - - #[ink_e2e::test] - #[should_panic] - async fn non_admin_fee_tier_caller_test(mut client: ink_e2e::Client) -> () { - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let user = ink_e2e::bob(); - // not-admin - let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 10); - let result = create_fee_tier!(client, ContractRef, dex, fee_tier, user); - } - - #[ink_e2e::test] - async fn position_above_current_tick_test( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - let alice = ink_e2e::alice(); - let init_tick = -23028; - - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let initial_balance = 10_000_000_000; - - let (token_x, token_y) = - create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - - let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let pool = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - approve!(client, TokenRef, token_x, dex, initial_balance, alice); - approve!(client, TokenRef, token_y, dex, initial_balance, alice); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let lower_tick_index = -22980; - let upper_tick_index = 0; - let liquidity_delta = Liquidity::new(initial_balance); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - SqrtPrice::max_instance(), - alice - ); - - // Load states - let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let lower_tick = - get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); - let upper_tick = - get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); - let lower_tick_bit = - tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - let upper_tick_bit = - tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - let alice_x = balance_of!(TokenRef, client, token_x, Alice); - let alice_y = balance_of!(TokenRef, client, token_y, Alice); - let dex_x = dex_balance!(TokenRef, client, token_x, dex); - let dex_y = dex_balance!(TokenRef, client, token_y, dex); - - let zero_fee = FeeGrowth::new(0); - let expected_x_increase = 21549; - let expected_y_increase = 0; - - // Check ticks - assert!(lower_tick.index == lower_tick_index); - assert!(upper_tick.index == upper_tick_index); - assert_eq!(lower_tick.liquidity_gross, liquidity_delta); - assert_eq!(upper_tick.liquidity_gross, liquidity_delta); - assert_eq!(lower_tick.liquidity_change, liquidity_delta); - assert_eq!(upper_tick.liquidity_change, liquidity_delta); - assert!(lower_tick.sign); - assert!(!upper_tick.sign); - - // Check pool - assert!(pool_state.liquidity == Liquidity::new(0)); - assert!(pool_state.current_tick_index == init_tick); - - // Check position - assert!(position_state.pool_key == pool_key); - assert!(position_state.liquidity == liquidity_delta); - assert!(position_state.lower_tick_index == lower_tick_index); - assert!(position_state.upper_tick_index == upper_tick_index); - assert!(position_state.fee_growth_inside_x == zero_fee); - assert!(position_state.fee_growth_inside_y == zero_fee); - - // Check balances - assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); - assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); - - assert_eq!(dex_x, expected_x_increase); - assert_eq!(dex_y, expected_y_increase); - - Ok(()) - } - - #[ink_e2e::test] - async fn multiple_positions_on_same_tick( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - let alice = ink_e2e::alice(); - let init_tick = 0; - - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let initial_balance = 100_000_000; - - let (token_x, token_y) = - create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - - let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 10); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let pool = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - approve!(client, TokenRef, token_x, dex, initial_balance, alice); - approve!(client, TokenRef, token_y, dex, initial_balance, alice); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // Three position on same lower and upper tick - { - let lower_tick_index = -10; - let upper_tick_index = 10; - - let liquidity_delta = Liquidity::new(100); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - SqrtPrice::max_instance(), - alice - ); - - let first_position = get_position!(client, ContractRef, dex, 0, alice).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - SqrtPrice::max_instance(), - alice - ); - - let second_position = get_position!(client, ContractRef, dex, 1, alice).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - SqrtPrice::max_instance(), - alice - ); - - let third_position = get_position!(client, ContractRef, dex, 2, alice).unwrap(); - - assert!(first_position.lower_tick_index == second_position.lower_tick_index); - assert!(first_position.upper_tick_index == second_position.upper_tick_index); - assert!(first_position.lower_tick_index == third_position.lower_tick_index); - assert!(first_position.upper_tick_index == third_position.upper_tick_index); - - // Load states - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let lower_tick = - get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); - let upper_tick = - get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); - let lower_tick_bit = - tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - let upper_tick_bit = - tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - let expected_liquidity = Liquidity::new(liquidity_delta.get() * 3); - let zero_fee = FeeGrowth::new(0); - - // Check ticks - assert!(lower_tick.index == lower_tick_index); - assert!(upper_tick.index == upper_tick_index); - assert_eq!(lower_tick.liquidity_gross, expected_liquidity); - assert_eq!(upper_tick.liquidity_gross, expected_liquidity); - assert_eq!(lower_tick.liquidity_change, expected_liquidity); - assert_eq!(upper_tick.liquidity_change, expected_liquidity); - assert!(lower_tick.sign); - assert!(!upper_tick.sign); - - // Check pool - assert_eq!(pool_state.liquidity, expected_liquidity); - assert!(pool_state.current_tick_index == init_tick); - - // Check first position - assert!(first_position.pool_key == pool_key); - assert!(first_position.liquidity == liquidity_delta); - assert!(first_position.lower_tick_index == lower_tick_index); - assert!(first_position.upper_tick_index == upper_tick_index); - assert!(first_position.fee_growth_inside_x == zero_fee); - assert!(first_position.fee_growth_inside_y == zero_fee); - - // Check second position - assert!(second_position.pool_key == pool_key); - assert!(second_position.liquidity == liquidity_delta); - assert!(second_position.lower_tick_index == lower_tick_index); - assert!(second_position.upper_tick_index == upper_tick_index); - assert!(second_position.fee_growth_inside_x == zero_fee); - assert!(second_position.fee_growth_inside_y == zero_fee); - - // Check third position - assert!(third_position.pool_key == pool_key); - assert!(third_position.liquidity == liquidity_delta); - assert!(third_position.lower_tick_index == lower_tick_index); - assert!(third_position.upper_tick_index == upper_tick_index); - assert!(third_position.fee_growth_inside_x == zero_fee); - assert!(third_position.fee_growth_inside_y == zero_fee); - } - { - let lower_tick_index = -10; - let upper_tick_index = 10; - let zero_fee = FeeGrowth::new(0); - - let liquidity_delta = Liquidity::new(100); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - SqrtPrice::max_instance(), - alice - ); - - let first_position = get_position!(client, ContractRef, dex, 3, alice).unwrap(); - - // Check first position - assert!(first_position.pool_key == pool_key); - assert!(first_position.liquidity == liquidity_delta); - assert!(first_position.lower_tick_index == lower_tick_index); - assert!(first_position.upper_tick_index == upper_tick_index); - assert!(first_position.fee_growth_inside_x == zero_fee); - assert!(first_position.fee_growth_inside_y == zero_fee); - - let lower_tick_index = -20; - let upper_tick_index = -10; - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - SqrtPrice::max_instance(), - alice - ); - - let second_position = get_position!(client, ContractRef, dex, 4, alice).unwrap(); - - // Check second position - assert!(second_position.pool_key == pool_key); - assert!(second_position.liquidity == liquidity_delta); - assert!(second_position.lower_tick_index == lower_tick_index); - assert!(second_position.upper_tick_index == upper_tick_index); - assert!(second_position.fee_growth_inside_x == zero_fee); - assert!(second_position.fee_growth_inside_y == zero_fee); - - let lower_tick_index = 10; - let upper_tick_index = 20; - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - SqrtPrice::max_instance(), - alice - ); - - let third_position = get_position!(client, ContractRef, dex, 5, alice).unwrap(); - - // Check third position - assert!(third_position.pool_key == pool_key); - assert!(third_position.liquidity == liquidity_delta); - assert!(third_position.lower_tick_index == lower_tick_index); - assert!(third_position.upper_tick_index == upper_tick_index); - assert!(third_position.fee_growth_inside_x == zero_fee); - assert!(third_position.fee_growth_inside_y == zero_fee); - - // Load states - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let tick_n20 = get_tick!(client, ContractRef, dex, -20, pool_key, alice).unwrap(); - let tick_n10 = get_tick!(client, ContractRef, dex, -10, pool_key, alice).unwrap(); - let tick_10 = get_tick!(client, ContractRef, dex, 10, pool_key, alice).unwrap(); - let tick_20 = get_tick!(client, ContractRef, dex, 20, pool_key, alice).unwrap(); - let tick_n20_bit = tickmap_bit!(client, ContractRef, dex, -20, pool_key, alice); - let tick_n10_bit = tickmap_bit!(client, ContractRef, dex, -10, pool_key, alice); - let tick_10_bit = tickmap_bit!(client, ContractRef, dex, 10, pool_key, alice); - let tick_20_bit = tickmap_bit!(client, ContractRef, dex, 20, pool_key, alice); - - let expected_active_liquidity = Liquidity::new(400); - - // Check tick -20 - assert_eq!(tick_n20.index, -20); - assert_eq!(tick_n20.liquidity_gross, Liquidity::new(100)); - assert_eq!(tick_n20.liquidity_change, Liquidity::new(100)); - assert!(tick_n20.sign); - assert!(tick_n20_bit); - - // Check tick -10 - assert_eq!(tick_n10.index, -10); - assert_eq!(tick_n10.liquidity_gross, Liquidity::new(500)); - assert_eq!(tick_n10.liquidity_change, Liquidity::new(300)); - assert!(tick_n10.sign); - assert!(tick_n10_bit); - - // Check tick 10 - assert_eq!(tick_10.index, 10); - assert_eq!(tick_10.liquidity_gross, Liquidity::new(500)); - assert_eq!(tick_10.liquidity_change, Liquidity::new(300)); - assert!(!tick_10.sign); - assert!(tick_20_bit); - - // Check tick 20 - assert_eq!(tick_20.index, 20); - assert_eq!(tick_20.liquidity_gross, Liquidity::new(100)); - assert_eq!(tick_20.liquidity_change, Liquidity::new(100)); - assert!(!tick_20.sign); - assert!(tick_20_bit); - - // Check pool - assert_eq!(pool_state.liquidity, expected_active_liquidity); - assert!(pool_state.current_tick_index == init_tick); - } - Ok(()) - } - - #[ink_e2e::test] - async fn position_within_current_tick_test( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - let MAX_TICK_TEST = 177_450; // for tickSpacing 4 - let MIN_TICK_TEST = -MAX_TICK_TEST; - let alice = ink_e2e::alice(); - let init_tick = -23028; - - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let initial_balance = 100_000_000; - - let (token_x, token_y) = - create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - - let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let pool = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - approve!(client, TokenRef, token_x, dex, initial_balance, alice); - approve!(client, TokenRef, token_y, dex, initial_balance, alice); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let lower_tick_index = MIN_TICK_TEST + 10; - let upper_tick_index = MAX_TICK_TEST - 10; - - let liquidity_delta = Liquidity::new(initial_balance); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - SqrtPrice::max_instance(), - alice - ); - - // Load states - let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let lower_tick = - get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); - let upper_tick = - get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); - let lower_tick_bit = - tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - let upper_tick_bit = - tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - let alice_x = balance_of!(TokenRef, client, token_x, Alice); - let alice_y = balance_of!(TokenRef, client, token_y, Alice); - let dex_x = dex_balance!(TokenRef, client, token_x, dex); - let dex_y = dex_balance!(TokenRef, client, token_y, dex); - - let zero_fee = FeeGrowth::new(0); - let expected_x_increase = 317; - let expected_y_increase = 32; - - // Check ticks - assert!(lower_tick.index == lower_tick_index); - assert!(upper_tick.index == upper_tick_index); - assert_eq!(lower_tick.liquidity_gross, liquidity_delta); - assert_eq!(upper_tick.liquidity_gross, liquidity_delta); - assert_eq!(lower_tick.liquidity_change, liquidity_delta); - assert_eq!(upper_tick.liquidity_change, liquidity_delta); - assert!(lower_tick.sign); - assert!(!upper_tick.sign); - - // Check pool - assert!(pool_state.liquidity == liquidity_delta); - assert!(pool_state.current_tick_index == init_tick); - - // Check position - assert!(position_state.pool_key == pool_key); - assert!(position_state.liquidity == liquidity_delta); - assert!(position_state.lower_tick_index == lower_tick_index); - assert!(position_state.upper_tick_index == upper_tick_index); - assert!(position_state.fee_growth_inside_x == zero_fee); - assert!(position_state.fee_growth_inside_y == zero_fee); - - // Check balances - assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); - assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); - assert_eq!(dex_x, expected_x_increase); - assert_eq!(dex_y, expected_y_increase); - - Ok(()) - } - - #[ink_e2e::test] - async fn position_below_current_tick_test( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - let alice = ink_e2e::alice(); - let init_tick = -23028; - - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let initial_balance = 100_000_000_00; - - let (token_x, token_y) = - create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - - let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let pool = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - approve!(client, TokenRef, token_x, dex, initial_balance, alice); - approve!(client, TokenRef, token_y, dex, initial_balance, alice); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let lower_tick_index = -46080; - let upper_tick_index = -23040; - - let liquidity_delta = Liquidity::new(initial_balance); - - let pool_state_before = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state_before.sqrt_price, - SqrtPrice::max_instance(), - alice - ); - - // Load states - let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let lower_tick = - get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); - let upper_tick = - get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); - let lower_tick_bit = - tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - let upper_tick_bit = - tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - let alice_x = balance_of!(TokenRef, client, token_x, Alice); - let alice_y = balance_of!(TokenRef, client, token_y, Alice); - let dex_x = dex_balance!(TokenRef, client, token_x, dex); - let dex_y = dex_balance!(TokenRef, client, token_y, dex); - - let zero_fee = FeeGrowth::new(0); - let expected_x_increase = 0; - let expected_y_increase = 2162; - - // Check ticks - assert!(lower_tick.index == lower_tick_index); - assert!(upper_tick.index == upper_tick_index); - assert_eq!(lower_tick.liquidity_gross, liquidity_delta); - assert_eq!(upper_tick.liquidity_gross, liquidity_delta); - assert_eq!(lower_tick.liquidity_change, liquidity_delta); - assert_eq!(upper_tick.liquidity_change, liquidity_delta); - assert!(lower_tick.sign); - assert!(!upper_tick.sign); - - // Check pool - assert!(pool_state.liquidity == pool_state_before.liquidity); - assert!(pool_state.current_tick_index == init_tick); - - // Check position - assert!(position_state.pool_key == pool_key); - assert!(position_state.liquidity == liquidity_delta); - assert!(position_state.lower_tick_index == lower_tick_index); - assert!(position_state.upper_tick_index == upper_tick_index); - assert!(position_state.fee_growth_inside_x == zero_fee); - assert!(position_state.fee_growth_inside_y == zero_fee); - - // Check balances - assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); - assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); - - assert_eq!(dex_x, expected_x_increase); - assert_eq!(dex_y, expected_y_increase); - - Ok(()) - } - - #[ink_e2e::test] - async fn change_fee_reciever_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); - - let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 1); - let init_tick = 0; - - let alice = ink_e2e::alice(); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let result = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - assert!(result.is_ok()); - - let admin = ink_e2e::alice(); - let alice = address_of!(Alice); - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - change_fee_receiver!(client, ContractRef, dex, pool_key, alice, admin); - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - assert_eq!(pool.fee_receiver, alice); - - Ok(()) - } - - #[ink_e2e::test] - #[should_panic] - async fn not_admin_change_fee_reciever_test(mut client: ink_e2e::Client) -> () { - let dex = create_dex!(client, ContractRef, Percentage::new(0)); - let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); - - let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); - let init_tick = 0; - - let admin = ink_e2e::alice(); - - create_fee_tier!(client, ContractRef, dex, fee_tier, admin); - - let result = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - assert!(result.is_ok()); - - let user = ink_e2e::bob(); - let bob = address_of!(Bob); - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - change_fee_receiver!(client, ContractRef, dex, pool_key, bob, user); - } - - #[ink_e2e::test] - async fn remove_position_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - let alice = ink_e2e::alice(); - let bob = ink_e2e::bob(); - let init_tick = 0; - let remove_position_index = 0; - - let initial_mint = 10u128.pow(10); - - let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); - let (token_x, token_y) = - create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let pool = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - let lower_tick_index = -20; - let upper_tick_index = 10; - let liquidity_delta = Liquidity::from_integer(1_000_000); - - approve!(client, TokenRef, token_x, dex, initial_mint, alice); - approve!(client, TokenRef, token_y, dex, initial_mint, alice); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - pool_state.sqrt_price, - alice - ); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - assert_eq!(pool_state.liquidity, liquidity_delta); - - let liquidity_delta = Liquidity::new(liquidity_delta.get() * 1_000_000); - { - let incorrect_lower_tick_index = lower_tick_index - 50; - let incorrect_upper_tick_index = upper_tick_index + 50; - - approve!(client, TokenRef, token_x, dex, liquidity_delta.get(), alice); - approve!(client, TokenRef, token_y, dex, liquidity_delta.get(), alice); - - create_position!( - client, - ContractRef, - dex, - pool_key, - incorrect_lower_tick_index, - incorrect_upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - pool_state.sqrt_price, - alice - ); - - let position_state = get_position!(client, ContractRef, dex, 1, alice).unwrap(); - // Check position - assert!(position_state.lower_tick_index == incorrect_lower_tick_index); - assert!(position_state.upper_tick_index == incorrect_upper_tick_index); - } - - let amount = 1000; - mint!(TokenRef, client, token_x, Bob, amount); - let amount_x = balance_of!(TokenRef, client, token_x, Bob); - assert_eq!(amount_x, amount); - - approve!(client, TokenRef, token_x, dex, amount, bob); - - let pool_state_before = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - let swap_amount = TokenAmount::new(amount); - let slippage = SqrtPrice::new(MIN_SQRT_PRICE); - swap!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - slippage, - bob - ); - - let pool_state_after = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - assert_eq!( - pool_state_after.fee_growth_global_x, - FeeGrowth::new(49999950000049999) - ); - assert_eq!(pool_state_after.fee_protocol_token_x, TokenAmount(1)); - assert_eq!(pool_state_after.fee_protocol_token_y, TokenAmount(0)); - - assert!(pool_state_after - .sqrt_price - .lt(&pool_state_before.sqrt_price)); - - assert_eq!(pool_state_after.liquidity, pool_state_before.liquidity); - assert_eq!(pool_state_after.current_tick_index, -10); - assert_ne!(pool_state_after.sqrt_price, pool_state_before.sqrt_price); - - let amount_x = balance_of!(TokenRef, client, token_x, Bob); - let amount_y = balance_of!(TokenRef, client, token_y, Bob); - assert_eq!(amount_x, 0); - assert_eq!(amount_y, 993); - - // pre load dex balances - let dex_x_before_remove = dex_balance!(TokenRef, client, token_x, dex); - let dex_y_before_remove = dex_balance!(TokenRef, client, token_y, dex); - - // Remove position - let remove_result = - remove_position!(client, ContractRef, dex, remove_position_index, alice); - - // Load states - let position_state = - get_position!(client, ContractRef, dex, remove_position_index, alice); - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let lower_tick = get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - let upper_tick = get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - let lower_tick_bit = - tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - let upper_tick_bit = - tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - let alice_x = balance_of!(TokenRef, client, token_x, Alice); - let alice_y = balance_of!(TokenRef, client, token_y, Alice); - let dex_x = dex_balance!(TokenRef, client, token_x, dex); - let dex_y = dex_balance!(TokenRef, client, token_y, dex); - let expected_withdrawn_x = 499; - let expected_withdrawn_y = 999; - let expected_fee_x = 0; - - assert_eq!( - dex_x_before_remove - dex_x, - expected_withdrawn_x + expected_fee_x - ); - assert_eq!(dex_y_before_remove - dex_y, expected_withdrawn_y); - - // Check ticks - assert_eq!(lower_tick, Err(InvariantError::TickNotFound)); - assert_eq!(upper_tick, Err(InvariantError::TickNotFound)); - - // Check tickmap - assert!(!lower_tick_bit); - assert!(!upper_tick_bit); - - // Check pool - assert!(pool_state.liquidity == liquidity_delta); - assert!(pool_state.current_tick_index == -10); - - Ok(()) - } - - #[ink_e2e::test] - async fn position_slippage_zero_slippage_and_inside_range( - mut client: ink_e2e::Client, - ) -> E2EResult<()> { - let alice = ink_e2e::alice(); - let (dex, token_x, token_y) = - init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); - let pool_key = create_slippage_pool_with_liquidity!( - client, - ContractRef, - TokenRef, - dex, - token_x, - token_y - ); - - let pool = get_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - pool_key.fee_tier - ) - .unwrap(); - - // zero slippage - { - let liquidity_delta = Liquidity::from_integer(1_000_000); - let known_price = pool.sqrt_price; - let tick = pool_key.fee_tier.tick_spacing as i32; - create_position!( - client, - ContractRef, - dex, - pool_key, - -tick, - tick, - liquidity_delta, - known_price, - known_price, - alice - ); - } - // inside range - { - let liquidity_delta = Liquidity::from_integer(1_000_000); - let known_price = SqrtPrice::new(1010000000000000000000000); - let limit_lower = SqrtPrice::new(994734637981406576896367); - let limit_upper = SqrtPrice::new(1025038048074314166333500); - - let tick = pool_key.fee_tier.tick_spacing as i32; - - create_position!( - client, - ContractRef, - dex, - pool_key, - -tick, - tick, - liquidity_delta, - limit_lower, - limit_upper, - alice - ); - } - - Ok(()) - } - #[ink_e2e::test] - #[should_panic] - async fn position_slippage_below_range(mut client: ink_e2e::Client) -> () { - let alice = ink_e2e::alice(); - let (dex, token_x, token_y) = - init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); - let pool_key = create_slippage_pool_with_liquidity!( - client, - ContractRef, - TokenRef, - dex, - token_x, - token_y - ); - - let pool = get_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - pool_key.fee_tier - ) - .unwrap(); - - let liquidity_delta = Liquidity::from_integer(1_000_000); - let known_price = SqrtPrice::new(1030000000000000000000000); - let limit_lower = SqrtPrice::new(1014432353584998786339859); - let limit_upper = SqrtPrice::new(1045335831204498605270797); - let tick = pool_key.fee_tier.tick_spacing as i32; - create_position!( - client, - ContractRef, - dex, - pool_key, - -tick, - tick, - liquidity_delta, - limit_lower, - limit_upper, - alice - ); - } - #[ink_e2e::test] - #[should_panic] - async fn position_slippage_above_range(mut client: ink_e2e::Client) -> () { - let alice = ink_e2e::alice(); - let (dex, token_x, token_y) = - init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); - let pool_key = create_slippage_pool_with_liquidity!( - client, - ContractRef, - TokenRef, - dex, - token_x, - token_y - ); - - let pool = get_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - pool_key.fee_tier - ) - .unwrap(); - - let liquidity_delta = Liquidity::from_integer(1_000_000); - let known_price = pool.sqrt_price; - let limit_lower = SqrtPrice::new(955339206774222158009382); - let limit_upper = SqrtPrice::new(984442481813945288458906); - let tick = pool_key.fee_tier.tick_spacing as i32; - create_position!( - client, - ContractRef, - dex, - pool_key, - -tick, - tick, - liquidity_delta, - limit_lower, - limit_upper, - alice - ); - } - - #[ink_e2e::test] - #[should_panic] - async fn no_liquidity_swap(mut client: ink_e2e::Client) -> () { - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - let alice = ink_e2e::alice(); - let bob = ink_e2e::bob(); - let init_tick = 0; - - let initial_mint = 10u128.pow(10); - - let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); - let (token_x, token_y) = - create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let pool = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - let lower_tick_index = -10; - let upper_tick_index = 10; - - let mint_amount = 10u128.pow(10); - mint!(TokenRef, client, token_x, Alice, mint_amount); - mint!(TokenRef, client, token_y, Alice, mint_amount); - - approve!(client, TokenRef, token_x, dex, mint_amount, alice); - approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - let liquidity_delta = Liquidity::from_integer(20_006_000); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - pool_state.sqrt_price, - alice - ); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - assert_eq!(pool_state.liquidity, liquidity_delta); - - let mint_amount = 10067; - mint!(TokenRef, client, token_x, Bob, mint_amount); - - approve!(client, TokenRef, token_x, dex, mint_amount, bob); - - let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); - let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); - - let swap_amount = TokenAmount::new(10067); - let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - let quoted_target_sqrt_price = quote!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - target_sqrt_price, - alice - ) - .unwrap() - .2; - - swap!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - quoted_target_sqrt_price, - bob - ); - - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let expected_price = calculate_sqrt_price(-10).unwrap(); - let expected_y_amount_out = 9999; - - assert_eq!(pool.liquidity, liquidity_delta); - assert_eq!(pool.current_tick_index, lower_tick_index); - assert_eq!(pool.sqrt_price, expected_price); - - let bob_x = balance_of!(TokenRef, client, token_x, Bob); - let bob_y = balance_of!(TokenRef, client, token_y, Bob); - let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); - let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); - - let delta_dex_x = dex_x_after - dex_x_before; - let delta_dex_y = dex_y_before - dex_y_after; - - assert_eq!(bob_x, 0); - assert_eq!(bob_y, expected_y_amount_out); - assert_eq!(delta_dex_x, swap_amount.get()); - assert_eq!(delta_dex_y, expected_y_amount_out); - assert_eq!( - pool.fee_growth_global_x, - FeeGrowth::new(29991002699190242927121) - ); - assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); - assert_eq!(pool.fee_protocol_token_x, TokenAmount::new(1)); - assert_eq!(pool.fee_protocol_token_y, TokenAmount::new(0)); - - let swap_amount = TokenAmount(1); - let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - let quoted_target_sqrt_price = quote!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - target_sqrt_price, - alice - ) - .unwrap() - .2; - swap!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - quoted_target_sqrt_price, - bob - ); - } - - #[ink_e2e::test] - async fn liquidity_gap_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - let alice = ink_e2e::alice(); - let bob = ink_e2e::bob(); - let init_tick = 0; - - let initial_mint = 10u128.pow(10); - - let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); - let (token_x, token_y) = - create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let pool = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - let lower_tick_index = -10; - let upper_tick_index = 10; - - let mint_amount = 10u128.pow(10); - mint!(TokenRef, client, token_x, Alice, mint_amount); - mint!(TokenRef, client, token_y, Alice, mint_amount); - - approve!(client, TokenRef, token_x, dex, mint_amount, alice); - approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - let liquidity_delta = Liquidity::from_integer(20_006_000); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - pool_state.sqrt_price, - alice - ); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - assert_eq!(pool_state.liquidity, liquidity_delta); - - let mint_amount = 10067; - mint!(TokenRef, client, token_x, Bob, mint_amount); - - approve!(client, TokenRef, token_x, dex, mint_amount, bob); - - let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); - let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); - - let swap_amount = TokenAmount::new(10067); - let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - let quoted_target_sqrt_price = quote!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - target_sqrt_price, - alice - ) - .unwrap() - .2; - - swap!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - quoted_target_sqrt_price, - bob - ); - - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let expected_price = calculate_sqrt_price(-10).unwrap(); - let expected_y_amount_out = 9999; - - assert_eq!(pool.liquidity, liquidity_delta); - assert_eq!(pool.current_tick_index, lower_tick_index); - assert_eq!(pool.sqrt_price, expected_price); - - let bob_x = balance_of!(TokenRef, client, token_x, Bob); - let bob_y = balance_of!(TokenRef, client, token_y, Bob); - let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); - let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); - - let delta_dex_x = dex_x_after - dex_x_before; - let delta_dex_y = dex_y_before - dex_y_after; - - assert_eq!(bob_x, 0); - assert_eq!(bob_y, expected_y_amount_out); - assert_eq!(delta_dex_x, swap_amount.get()); - assert_eq!(delta_dex_y, expected_y_amount_out); - assert_eq!( - pool.fee_growth_global_x, - FeeGrowth::new(29991002699190242927121) - ); - assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); - assert_eq!(pool.fee_protocol_token_x, TokenAmount::new(1)); - assert_eq!(pool.fee_protocol_token_y, TokenAmount::new(0)); - - // Should skip gap and then swap - let lower_tick_after_swap = -90; - let upper_tick_after_swap = -50; - let liquidity_delta = Liquidity::from_integer(20008000); - - approve!(client, TokenRef, token_x, dex, liquidity_delta.get(), alice); - approve!(client, TokenRef, token_y, dex, liquidity_delta.get(), alice); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_after_swap, - upper_tick_after_swap, - liquidity_delta, - pool_state.sqrt_price, - pool_state.sqrt_price, - alice - ); - - let swap_amount = TokenAmount::new(5000); - mint!(TokenRef, client, token_x, Bob, swap_amount.get()); - - approve!(client, TokenRef, token_x, dex, swap_amount.get(), bob); - - let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); - let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); - - let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - let quoted_target_sqrt_price = quote!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - target_sqrt_price, - alice - ) - .unwrap() - .2; - - swap!( - client, - ContractRef, - dex, - pool_key, - true, - swap_amount, - true, - quoted_target_sqrt_price, - bob - ); - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - let bob_x = balance_of!(TokenRef, client, token_x, Bob); - let bob_y = balance_of!(TokenRef, client, token_y, Bob); - let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); - let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); - - let delta_dex_x = dex_x_after - dex_x_before; - let delta_dex_y = dex_y_before - dex_y_after; - Ok(()) - } + async fn reversed(mut client: ink_e2e::Client) -> E2EResult<()> { + let dex = create_dex!(client, ContractRef, Percentage::from_scale(6, 3)); + let initial_amount = 10u128.pow(10); + let (token_x, token_y) = + create_tokens!(client, TokenRef, TokenRef, initial_amount, initial_amount); - #[ink_e2e::test] - async fn cross_both_side_test(mut client: ink_e2e::Client) -> E2EResult<()> { - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); let alice = ink_e2e::alice(); - let bob = ink_e2e::bob(); - let init_tick = 0; - - let initial_mint = 10u128.pow(10); - - let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); - let (token_x, token_y) = - create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - let pool = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - let lower_tick_index = -10; - let upper_tick_index = 10; + let pool = create_pool!(client, ContractRef, dex, token_x, token_y, fee_tier, 0); - let mint_amount = 10u128.pow(5); - mint!(TokenRef, client, token_x, Alice, mint_amount); - mint!(TokenRef, client, token_y, Alice, mint_amount); + approve!(client, TokenRef, token_x, dex, initial_amount, alice); + approve!(client, TokenRef, token_y, dex, initial_amount, alice); - approve!(client, TokenRef, token_x, dex, mint_amount, alice); - approve!(client, TokenRef, token_y, dex, mint_amount, alice); + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - let liquidity_delta = Liquidity::new(20006000000000); + let lower_tick_index = -10; + let middle_tick_index = 10; + let upper_tick_index = 20; - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let liquidity_delta = Liquidity::from_integer(1000000); - create_position!( + let position = create_position!( client, ContractRef, dex, @@ -3621,21 +1247,21 @@ pub mod contract { lower_tick_index, upper_tick_index, liquidity_delta, - pool_state.sqrt_price, - pool_state.sqrt_price, + SqrtPrice::new(0), + SqrtPrice::max_instance(), alice ); - create_position!( + let position = create_position!( client, ContractRef, dex, pool_key, - -20, - lower_tick_index, + middle_tick_index, + upper_tick_index + 20, liquidity_delta, - pool_state.sqrt_price, - pool_state.sqrt_price, + SqrtPrice::new(0), + SqrtPrice::max_instance(), alice ); @@ -3643,105 +1269,29 @@ pub mod contract { assert_eq!(pool.liquidity, liquidity_delta); - let limit_without_cross_tick_amount = TokenAmount(10_068); - let not_cross_amount = TokenAmount(1); - let min_amount_to_cross_from_tick_price = TokenAmount(3); - let crossing_amount_by_amount_out = TokenAmount(20136101434); - - let mint_amount = limit_without_cross_tick_amount.get() - + not_cross_amount.get() - + min_amount_to_cross_from_tick_price.get() - + crossing_amount_by_amount_out.get(); - - mint!(TokenRef, client, token_x, Alice, mint_amount); - mint!(TokenRef, client, token_y, Alice, mint_amount); - - approve!(client, TokenRef, token_x, dex, mint_amount, alice); - approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - let pool_before = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - let limit_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - - swap!( - client, - ContractRef, - dex, - pool_key, - true, - limit_without_cross_tick_amount, - true, - limit_sqrt_price, - alice - ); - - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let expected_tick = -10; - let expected_price = calculate_sqrt_price(expected_tick).unwrap(); - - assert_eq!(pool.current_tick_index, expected_tick); - assert_eq!(pool.liquidity, pool_before.liquidity); - assert_eq!(pool.sqrt_price, expected_price); + let amount = 1000; + let swap_amount = TokenAmount(amount); + let bob = ink_e2e::bob(); + mint_with_aprove_for_bob!(client, TokenRef, token_y, dex, amount); - swap!( - client, - ContractRef, - dex, - pool_key, - true, - min_amount_to_cross_from_tick_price, - true, - limit_sqrt_price, - alice - ); + let target_sqrt_price = SqrtPrice::new(MAX_SQRT_PRICE); - swap!( + let target_sqrt_price = quote!( client, ContractRef, dex, pool_key, false, - min_amount_to_cross_from_tick_price, + swap_amount, true, - SqrtPrice::new(MAX_SQRT_PRICE), - alice - ); - - let massive_x = 10u128.pow(19); - let massive_y = 10u128.pow(19); - - mint!(TokenRef, client, token_x, Alice, massive_x); - mint!(TokenRef, client, token_y, Alice, massive_y); - approve!(client, TokenRef, token_x, dex, massive_x, alice); - approve!(client, TokenRef, token_y, dex, massive_y, alice); - - let massive_liquidity_delta = Liquidity::new(19996000399699881985603000000); - - create_position!( - client, - ContractRef, - dex, - pool_key, - -20, - 0, - massive_liquidity_delta, - SqrtPrice::new(MIN_SQRT_PRICE), - SqrtPrice::new(MAX_SQRT_PRICE), - alice - ); + target_sqrt_price, + bob + ) + .unwrap() + .2; - swap!( - client, - ContractRef, - dex, - pool_key, - true, - TokenAmount(1), - false, - limit_sqrt_price, - alice - ); + let before_dex_x = dex_balance!(TokenRef, client, token_x, dex); + let before_dex_y = dex_balance!(TokenRef, client, token_y, dex); swap!( client, @@ -3749,197 +1299,2794 @@ pub mod contract { dex, pool_key, false, - TokenAmount(2), + swap_amount, true, - SqrtPrice::new(MAX_SQRT_PRICE), - alice + target_sqrt_price, + bob ); + // Load states let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - assert_eq!(pool.current_tick_index, -20); - assert_eq!( - pool.fee_growth_global_x, - FeeGrowth::new(29991002699190242927121) - ); - assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); - assert_eq!(pool.fee_protocol_token_x, TokenAmount(4)); - assert_eq!(pool.fee_protocol_token_y, TokenAmount(2)); - assert_eq!( - pool.liquidity, - Liquidity::new(19996000399699901991603000000) - ); - assert_eq!(pool.sqrt_price, SqrtPrice::new(999500149964999999999999)); + let lower_tick = + get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + let middle_tick = + get_tick!(client, ContractRef, dex, middle_tick_index, pool_key, alice).unwrap(); + let upper_tick = + get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + let lower_tick_bit = + tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + let middle_tick_bit = + tickmap_bit!(client, ContractRef, dex, middle_tick_index, pool_key, alice); + let upper_tick_bit = + tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + let bob_x = balance_of!(TokenRef, client, token_x, Bob); + let bob_y = balance_of!(TokenRef, client, token_y, Bob); + let dex_x = dex_balance!(TokenRef, client, token_x, dex); + let dex_y = dex_balance!(TokenRef, client, token_y, dex); + let delta_dex_x = before_dex_x - dex_x; + let delta_dex_y = dex_y - before_dex_y; + let expected_x = amount - 10; + let expected_y = 0; - let final_last_tick = - get_tick!(client, ContractRef, dex, -20, pool_key, alice).unwrap(); - assert_eq!(final_last_tick.fee_growth_outside_x, FeeGrowth::new(0)); - assert_eq!(final_last_tick.fee_growth_outside_y, FeeGrowth::new(0)); - assert_eq!( - final_last_tick.liquidity_change, - Liquidity::new(19996000399699901991603000000) - ); + // Check balances + assert_eq!(bob_x, expected_x); + assert_eq!(bob_y, expected_y); + assert_eq!(delta_dex_x, expected_x); + assert_eq!(delta_dex_y, amount); - let final_lower_tick = - get_tick!(client, ContractRef, dex, -10, pool_key, alice).unwrap(); + // Check Pool + assert_eq!(pool.fee_growth_global_x, FeeGrowth::new(0)); assert_eq!( - final_lower_tick.fee_growth_outside_x, - FeeGrowth::new(29991002699190242927121) + pool.fee_growth_global_y, + FeeGrowth::new(40000000000000000000000) ); - assert_eq!(final_lower_tick.fee_growth_outside_y, FeeGrowth::new(0)); - assert_eq!(final_lower_tick.liquidity_change, Liquidity::new(0)); + assert_eq!(pool.fee_protocol_token_x, TokenAmount(0)); + assert_eq!(pool.fee_protocol_token_y, TokenAmount(2)); - let final_upper_tick = - get_tick!(client, ContractRef, dex, 10, pool_key, alice).unwrap(); - assert_eq!(final_upper_tick.fee_growth_outside_x, FeeGrowth::new(0)); - assert_eq!(final_upper_tick.fee_growth_outside_y, FeeGrowth::new(0)); + // Check Ticks + assert_eq!(lower_tick.liquidity_change, liquidity_delta); + assert_eq!(middle_tick.liquidity_change, liquidity_delta); + assert_eq!(upper_tick.liquidity_change, liquidity_delta); + assert_eq!(upper_tick.fee_growth_outside_y, FeeGrowth::new(0)); assert_eq!( - final_upper_tick.liquidity_change, - Liquidity::new(20006000000000) + middle_tick.fee_growth_outside_y, + FeeGrowth::new(30000000000000000000000) ); + assert_eq!(lower_tick.fee_growth_outside_y, FeeGrowth::new(0)); + assert!(lower_tick_bit); + assert!(middle_tick_bit); + assert!(upper_tick_bit); Ok(()) } - #[ink_e2e::test] - #[should_panic] - async fn cross_both_side_not_cross_case_test(mut client: ink_e2e::Client) -> () { - let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - let alice = ink_e2e::alice(); - let bob = ink_e2e::bob(); - let init_tick = 0; - - let initial_mint = 10u128.pow(10); - - let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); - let (token_x, token_y) = - create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); - - let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - let pool = create_pool!( - client, - ContractRef, - dex, - token_x, - token_y, - fee_tier, - init_tick - ); - - let lower_tick_index = -10; - let upper_tick_index = 10; - - let mint_amount = 10u128.pow(5); - mint!(TokenRef, client, token_x, Alice, mint_amount); - mint!(TokenRef, client, token_y, Alice, mint_amount); - - approve!(client, TokenRef, token_x, dex, mint_amount, alice); - approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - let liquidity_delta = Liquidity::new(20006000000000); - - let pool_state = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - create_position!( - client, - ContractRef, - dex, - pool_key, - lower_tick_index, - upper_tick_index, - liquidity_delta, - pool_state.sqrt_price, - pool_state.sqrt_price, - alice - ); - - create_position!( - client, - ContractRef, - dex, - pool_key, - -20, - lower_tick_index, - liquidity_delta, - pool_state.sqrt_price, - pool_state.sqrt_price, - alice - ); - - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - assert_eq!(pool.liquidity, liquidity_delta); - - let limit_without_cross_tick_amount = TokenAmount(10_068); - let not_cross_amount = TokenAmount(1); - let min_amount_to_cross_from_tick_price = TokenAmount(3); - let crossing_amount_by_amount_out = TokenAmount(20136101434); - - let mint_amount = limit_without_cross_tick_amount.get() - + not_cross_amount.get() - + min_amount_to_cross_from_tick_price.get() - + crossing_amount_by_amount_out.get(); - - mint!(TokenRef, client, token_x, Alice, mint_amount); - mint!(TokenRef, client, token_y, Alice, mint_amount); - - approve!(client, TokenRef, token_x, dex, mint_amount, alice); - approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - let pool_before = - get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - let limit_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - - swap!( - client, - ContractRef, - dex, - pool_key, - true, - limit_without_cross_tick_amount, - true, - limit_sqrt_price, - alice - ); - - let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - let expected_tick = -10; - let expected_price = calculate_sqrt_price(expected_tick).unwrap(); - - assert_eq!(pool.current_tick_index, expected_tick); - assert_eq!(pool.liquidity, pool_before.liquidity); - assert_eq!(pool.sqrt_price, expected_price); - - let slippage = SqrtPrice::new(MIN_SQRT_PRICE); - let target_sqrt_price = quote!( - client, - ContractRef, - dex, - pool_key, - true, - not_cross_amount, - true, - slippage, - alice - ) - .unwrap() - .2; - - swap!( - client, - ContractRef, - dex, - pool_key, - true, - not_cross_amount, - true, - target_sqrt_price, - alice - ); - } + // #[ink_e2e::test] + // async fn swap_route(mut client: ink_e2e::Client) -> E2EResult<()> { + // let (dex, token_x, token_y, token_z) = + // init_dex_and_3_tokens!(client, ContractRef, TokenRef); + + // let alice = ink_e2e::alice(); + // approve!(client, TokenRef, token_x, dex, u64::MAX as u128, alice); + // approve!(client, TokenRef, token_y, dex, u64::MAX as u128, alice); + // approve!(client, TokenRef, token_z, dex, u64::MAX as u128, alice); + + // let amount = 1000; + // let bob = ink_e2e::bob(); + // mint_with_aprove_for_bob!(client, TokenRef, token_x, dex, amount); + // approve!(client, TokenRef, token_y, dex, u64::MAX as u128, bob); + + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let init_tick = 0; + // create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // let init_tick = 0; + // create_pool!( + // client, + // ContractRef, + // dex, + // token_y, + // token_z, + // fee_tier, + // init_tick + // ); + + // let pool_key_1 = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // let pool_key_2 = PoolKey::new(token_y, token_z, fee_tier).unwrap(); + + // let liquidity_delta = Liquidity::new(2u128.pow(63) - 1); + + // let pool_1 = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let slippage_limit_lower = pool_1.sqrt_price; + // let slippage_limit_upper = pool_1.sqrt_price; + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key_1, + // -1, + // 1, + // liquidity_delta, + // slippage_limit_lower, + // slippage_limit_upper, + // alice + // ); + + // let pool_2 = get_pool!(client, ContractRef, dex, token_y, token_z, fee_tier).unwrap(); + // let slippage_limit_lower = pool_2.sqrt_price; + // let slippage_limit_upper = pool_2.sqrt_price; + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key_2, + // -1, + // 1, + // liquidity_delta, + // slippage_limit_lower, + // slippage_limit_upper, + // alice + // ); + + // let amount_in = TokenAmount(1000); + // let expected_amount_out = TokenAmount(1000); + // let slippage = Percentage::new(0); + // let swaps = vec![ + // Hop { + // pool_key: pool_key_1, + // x_to_y: true, + // }, + // Hop { + // pool_key: pool_key_2, + // x_to_y: true, + // }, + // ]; + + // let expected_token_amount = + // quote_route!(client, ContractRef, dex, amount_in, swaps.clone(), bob).unwrap(); + + // swap_route!( + // client, + // ContractRef, + // dex, + // amount_in, + // expected_token_amount, + // slippage, + // swaps.clone(), + // bob + // ); + + // let bob_amount_x = balance_of!(TokenRef, client, token_x, Bob); + // let bob_amount_y = balance_of!(TokenRef, client, token_y, Bob); + // let bob_amount_z = balance_of!(TokenRef, client, token_z, Bob); + + // assert_eq!(bob_amount_x, 0); + // assert_eq!(bob_amount_y, 0); + // assert_eq!(bob_amount_z, 986); + + // let pool_1_after = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // assert_eq!(pool_1_after.fee_protocol_token_x, TokenAmount(1)); + // assert_eq!(pool_1_after.fee_protocol_token_y, TokenAmount(0)); + + // let pool_2_after = + // get_pool!(client, ContractRef, dex, token_y, token_z, fee_tier).unwrap(); + // assert_eq!(pool_2_after.fee_protocol_token_x, TokenAmount(1)); + // assert_eq!(pool_2_after.fee_protocol_token_y, TokenAmount(0)); + + // let alice_amount_x_before = balance_of!(TokenRef, client, token_x, Alice); + // let alice_amount_y_before = balance_of!(TokenRef, client, token_y, Alice); + // let alice_amount_z_before = balance_of!(TokenRef, client, token_z, Alice); + + // claim_fee!(client, ContractRef, dex, 0, alice); + // claim_fee!(client, ContractRef, dex, 1, alice); + + // let alice_amount_x_after = balance_of!(TokenRef, client, token_x, Alice); + // let alice_amount_y_after = balance_of!(TokenRef, client, token_y, Alice); + // let alice_amount_z_after = balance_of!(TokenRef, client, token_z, Alice); + + // assert_eq!(alice_amount_x_after - alice_amount_x_before, 4); + // assert_eq!(alice_amount_y_after - alice_amount_y_before, 4); + // assert_eq!(alice_amount_z_after - alice_amount_z_before, 0); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn limits_full_range_with_max_liquidity(mut client: ink_e2e::Client) -> () { + // let (dex, token_x, token_y) = + // init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); + + // let mint_amount = u128::MAX; + // let alice = ink_e2e::alice(); + // approve!(client, TokenRef, token_x, dex, u128::MAX, alice); + // approve!(client, TokenRef, token_y, dex, u128::MAX, alice); + + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let init_tick = get_max_tick(1); + // create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let current_sqrt_price = pool.sqrt_price; + // assert_eq!(pool.current_tick_index, init_tick); + // assert_eq!(pool.sqrt_price, calculate_sqrt_price(init_tick).unwrap()); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // let liquidity_delta = Liquidity::new(2u128.pow(109) - 1); + // let slippage_limit_lower = pool.sqrt_price; + // let slippage_limit_upper = pool.sqrt_price; + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // -MAX_TICK, + // MAX_TICK, + // liquidity_delta, + // slippage_limit_lower, + // slippage_limit_upper, + // alice + // ); + + // let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); + // let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); + + // let expected_x = 0; + // let expected_y = 42534896005851865508212194815854; + // assert_eq!(contract_amount_x, expected_x); + // assert_eq!(contract_amount_y, expected_y); + // } + + // #[ink_e2e::test] + // async fn deposit_limits_at_upper_limit(mut client: ink_e2e::Client) -> E2EResult<()> { + // let (dex, token_x, token_y) = + // init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); + + // let mint_amount = 2u128.pow(105) - 1; + // let alice = ink_e2e::alice(); + // approve!(client, TokenRef, token_x, dex, u128::MAX, alice); + // approve!(client, TokenRef, token_y, dex, u128::MAX, alice); + + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let init_tick = get_max_tick(1); + // create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let current_sqrt_price = pool.sqrt_price; + // assert_eq!(pool.current_tick_index, init_tick); + // assert_eq!(pool.sqrt_price, calculate_sqrt_price(init_tick).unwrap()); + + // let position_amount = mint_amount - 1; + + // let liquidity_delta = get_liquidity_by_y( + // TokenAmount(position_amount), + // 0, + // MAX_TICK, + // pool.sqrt_price, + // false, + // ) + // .unwrap() + // .l; + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // let slippage_limit_lower = pool.sqrt_price; + // let slippage_limit_upper = pool.sqrt_price; + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // 0, + // MAX_TICK, + // liquidity_delta, + // slippage_limit_lower, + // slippage_limit_upper, + // alice + // ); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn limits_big_deposit_and_swaps(mut client: ink_e2e::Client) -> E2EResult<()> { + // let (dex, token_x, token_y) = + // init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); + + // let mint_amount = 2u128.pow(76) - 1; + // let alice = ink_e2e::alice(); + // approve!(client, TokenRef, token_x, dex, u128::MAX, alice); + // approve!(client, TokenRef, token_y, dex, u128::MAX, alice); + + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let init_tick = 0; + // create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // let pos_amount = mint_amount / 2; + // let lower_tick = -(fee_tier.tick_spacing as i32); + // let upper_tick = fee_tier.tick_spacing as i32; + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // let liquidity_delta = get_liquidity_by_x( + // TokenAmount(pos_amount), + // lower_tick, + // upper_tick, + // pool.sqrt_price, + // false, + // ) + // .unwrap() + // .l; + + // let y = get_delta_y( + // calculate_sqrt_price(lower_tick).unwrap(), + // pool.sqrt_price, + // liquidity_delta, + // true, + // ) + // .unwrap(); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // let slippage_limit_lower = pool.sqrt_price; + // let slippage_limit_upper = pool.sqrt_price; + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick, + // upper_tick, + // liquidity_delta, + // slippage_limit_lower, + // slippage_limit_upper, + // alice + // ); + + // let user_amount_x = balance_of!(TokenRef, client, token_x, Alice); + // let user_amount_y = balance_of!(TokenRef, client, token_y, Alice); + // assert_eq!(user_amount_x, u128::MAX - pos_amount); + // assert_eq!(user_amount_y, u128::MAX - y.get()); + + // let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); + // let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); + // assert_eq!(contract_amount_x, pos_amount); + // assert_eq!(contract_amount_y, y.get()); + + // let swap_amount = TokenAmount(mint_amount / 8); + + // for i in 1..=4 { + // let (x_to_y, sqrt_price_limit) = if i % 2 == 0 { + // (true, SqrtPrice::new(MIN_SQRT_PRICE)) + // } else { + // (false, SqrtPrice::new(MAX_SQRT_PRICE)) + // }; + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // i % 2 == 0, + // swap_amount, + // true, + // sqrt_price_limit, + // alice + // ); + // } + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn multiple_swap_x_to_y(mut client: ink_e2e::Client) -> E2EResult<()> { + // multiple_swap!(client, ContractRef, TokenRef, true); + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn limits_big_deposit_x_and_swap_y( + // mut client: ink_e2e::Client, + // ) -> E2EResult<()> { + // big_deposit_and_swap!(client, ContractRef, TokenRef, true); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn multiple_swap_y_to_x(mut client: ink_e2e::Client) -> E2EResult<()> { + // multiple_swap!(client, ContractRef, TokenRef, false); + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn limits_big_deposit_y_and_swap_x( + // mut client: ink_e2e::Client, + // ) -> E2EResult<()> { + // big_deposit_and_swap!(client, ContractRef, TokenRef, false); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn limits_big_deposit_both_tokens( + // mut client: ink_e2e::Client, + // ) -> E2EResult<()> { + // let (dex, token_x, token_y) = + // init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); + + // let mint_amount = 2u128.pow(75) - 1; + // let alice = ink_e2e::alice(); + // approve!(client, TokenRef, token_x, dex, u128::MAX, alice); + // approve!(client, TokenRef, token_y, dex, u128::MAX, alice); + + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let init_tick = 0; + // create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // let lower_tick = -(fee_tier.tick_spacing as i32); + // let upper_tick = fee_tier.tick_spacing as i32; + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let liquidity_delta = get_liquidity_by_x( + // TokenAmount(mint_amount), + // lower_tick, + // upper_tick, + // pool.sqrt_price, + // false, + // ) + // .unwrap() + // .l; + // let y = get_delta_y( + // calculate_sqrt_price(lower_tick).unwrap(), + // pool.sqrt_price, + // liquidity_delta, + // true, + // ) + // .unwrap(); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // let slippage_limit_lower = pool.sqrt_price; + // let slippage_limit_upper = pool.sqrt_price; + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick, + // upper_tick, + // liquidity_delta, + // slippage_limit_lower, + // slippage_limit_upper, + // alice + // ); + + // let user_amount_x = balance_of!(TokenRef, client, token_x, Alice); + // let user_amount_y = balance_of!(TokenRef, client, token_y, Alice); + // assert_eq!(user_amount_x, u128::MAX - mint_amount); + // assert_eq!(user_amount_y, u128::MAX - y.get()); + + // let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); + // let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); + // assert_eq!(contract_amount_x, mint_amount); + // assert_eq!(contract_amount_y, y.get()); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn max_tick_cross(mut client: ink_e2e::Client) -> E2EResult<()> { + // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + + // let mint_amount = u128::MAX; + // let alice = ink_e2e::alice(); + // approve!(client, TokenRef, token_x, dex, mint_amount, alice); + // approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + // let liquidity = Liquidity::from_integer(10000000); + + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + // for i in (-2560..20).step_by(10) { + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // let slippage_limit_lower = pool.sqrt_price; + // let slippage_limit_upper = pool.sqrt_price; + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // i, + // i + 10, + // liquidity, + // slippage_limit_lower, + // slippage_limit_upper, + // alice + // ); + // } + + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // assert_eq!(pool.liquidity, liquidity); + + // let amount = 760_000; + // let bob = ink_e2e::bob(); + // mint!(TokenRef, client, token_x, Bob, amount); + // let amount_x = balance_of!(TokenRef, client, token_x, Bob); + // assert_eq!(amount_x, amount); + // approve!(client, TokenRef, token_x, dex, amount, bob); + + // let pool_before = get_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // pool_key.fee_tier + // ) + // .unwrap(); + + // let swap_amount = TokenAmount::new(amount); + // let slippage = SqrtPrice::new(MIN_SQRT_PRICE); + // let quote_result = quote!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // slippage, + // bob + // ) + // .unwrap(); + + // let pool_after_quote = get_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // pool_key.fee_tier + // ) + // .unwrap(); + + // let crosses_after_quote = + // ((pool_after_quote.current_tick_index - pool_before.current_tick_index) / 10).abs(); + // assert_eq!(crosses_after_quote, 0); + // assert_eq!(quote_result.3.len() - 1, 146); + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // slippage, + // bob + // ); + + // let pool_after = get_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // pool_key.fee_tier + // ) + // .unwrap(); + + // let crosses = + // ((pool_after.current_tick_index - pool_before.current_tick_index) / 10).abs(); + // assert_eq!(crosses, 146); + // assert_eq!( + // pool_after.current_tick_index, + // get_tick_at_sqrt_price(quote_result.2, 10).unwrap() + // ); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn swap_exact_limit(mut client: ink_e2e::Client) -> E2EResult<()> { + // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + // let amount = 1000; + // let bob = ink_e2e::bob(); + // mint!(TokenRef, client, token_x, Bob, amount); + // let amount_x = balance_of!(TokenRef, client, token_x, Bob); + // assert_eq!(amount_x, amount); + // approve!(client, TokenRef, token_x, dex, amount, bob); + + // let swap_amount = TokenAmount::new(amount); + // swap_exact_limit!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // bob + // ); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn claim(mut client: ink_e2e::Client) -> E2EResult<()> { + // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + // init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); + + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // let alice = ink_e2e::alice(); + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let user_amount_before_claim = balance_of!(TokenRef, client, token_x, Alice); + // let dex_amount_before_claim = dex_balance!(TokenRef, client, token_x, dex); + + // claim_fee!(client, ContractRef, dex, 0, alice); + + // let user_amount_after_claim = balance_of!(TokenRef, client, token_x, Alice); + // let dex_amount_after_claim = dex_balance!(TokenRef, client, token_x, dex); + // let position = get_position!(client, ContractRef, dex, 0, alice).unwrap(); + // let expected_tokens_claimed = 5; + + // assert_eq!( + // user_amount_after_claim - expected_tokens_claimed, + // user_amount_before_claim + // ); + // assert_eq!( + // dex_amount_after_claim + expected_tokens_claimed, + // dex_amount_before_claim + // ); + // assert_eq!(position.fee_growth_inside_x, pool.fee_growth_global_x); + // assert_eq!(position.tokens_owed_x, TokenAmount(0)); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn basic_slippage_test(mut client: ink_e2e::Client) -> E2EResult<()> { + // let alice = ink_e2e::alice(); + // let (dex, token_x, token_y) = + // init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); + // let pool_key = create_slippage_pool_with_liquidity!( + // client, + // ContractRef, + // TokenRef, + // dex, + // token_x, + // token_y + // ); + // let amount = 10u128.pow(8); + // let swap_amount = TokenAmount::new(amount); + // approve!(client, TokenRef, token_x, dex, amount, alice); + + // let target_sqrt_price = SqrtPrice::new(1009940000000000000000001); + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // false, + // swap_amount, + // true, + // target_sqrt_price, + // alice + // ); + // let expected_sqrt_price = SqrtPrice::new(1009940000000000000000000); + // let pool = get_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // pool_key.fee_tier + // ) + // .unwrap(); + + // assert_eq!(expected_sqrt_price, pool.sqrt_price); + // Ok(()) + // } + + // #[ink_e2e::test] + // #[should_panic] + // async fn swap_close_to_limit_test(mut client: ink_e2e::Client) -> () { + // let alice = ink_e2e::alice(); + // let (dex, token_x, token_y) = + // init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); + // let pool_key = create_slippage_pool_with_liquidity!( + // client, + // ContractRef, + // TokenRef, + // dex, + // token_x, + // token_y + // ); + // let amount = 10u128.pow(8); + // let swap_amount = TokenAmount::new(amount); + // approve!(client, TokenRef, token_x, dex, amount, alice); + + // let target_sqrt_price = calculate_sqrt_price(-98).unwrap(); + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // false, + // swap_amount, + // true, + // target_sqrt_price, + // alice + // ); + // } + + // #[ink_e2e::test] + // async fn cross(mut client: ink_e2e::Client) -> E2EResult<()> { + // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + // init_cross_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + // init_cross_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); + + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // let alice = ink_e2e::alice(); + + // let upper_tick_index = 10; + // let middle_tick_index = -10; + // let lower_tick_index = -20; + + // let upper_tick = + // get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + // let middle_tick = + // get_tick!(client, ContractRef, dex, middle_tick_index, pool_key, alice).unwrap(); + // let lower_tick = + // get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + + // assert_eq!( + // upper_tick.liquidity_change, + // Liquidity::from_integer(1000000) + // ); + // assert_eq!( + // middle_tick.liquidity_change, + // Liquidity::from_integer(1000000) + // ); + // assert_eq!( + // lower_tick.liquidity_change, + // Liquidity::from_integer(1000000) + // ); + + // assert_eq!(upper_tick.fee_growth_outside_x, FeeGrowth::new(0)); + // assert_eq!( + // middle_tick.fee_growth_outside_x, + // FeeGrowth::new(30000000000000000000000) + // ); + // assert_eq!(lower_tick.fee_growth_outside_x, FeeGrowth::new(0)); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn swap(mut client: ink_e2e::Client) -> E2EResult<()> { + // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + // init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn protocol_fee(mut client: ink_e2e::Client) -> E2EResult<()> { + // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + // init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); + + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // let alice = ink_e2e::alice(); + // withdraw_protocol_fee!(client, ContractRef, dex, pool_key, alice); + + // let amount_x = balance_of!(TokenRef, client, token_x, Alice); + // let amount_y = balance_of!(TokenRef, client, token_y, Alice); + // assert_eq!(amount_x, 9999999501); + // assert_eq!(amount_y, 9999999000); + + // let amount_x = dex_balance!(TokenRef, client, token_x, dex); + // let amount_y = dex_balance!(TokenRef, client, token_y, dex); + // assert_eq!(amount_x, 1499); + // assert_eq!(amount_y, 7); + + // let pool_after_withdraw = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // assert_eq!( + // pool_after_withdraw.fee_protocol_token_x, + // TokenAmount::new(0) + // ); + // assert_eq!( + // pool_after_withdraw.fee_protocol_token_y, + // TokenAmount::new(0) + // ); + + // Ok(()) + // } + + // #[ink_e2e::test] + // #[should_panic] + // async fn protocol_fee_should_panic(mut client: ink_e2e::Client) -> () { + // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + // init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); + + // let pool_key = PoolKey::new( + // token_x, + // token_y, + // FeeTier { + // fee: Percentage::from_scale(6, 3), + // tick_spacing: 10, + // }, + // ) + // .unwrap(); + // let bob = ink_e2e::bob(); + // withdraw_protocol_fee!(client, ContractRef, dex, pool_key, bob); + // } + + // #[ink_e2e::test] + // async fn constructor_test(mut client: ink_e2e::Client) -> E2EResult<()> { + // let constructor = TokenRef::new(500, None, None, 0); + // let _token: AccountId = client + // .instantiate("token", &ink_e2e::alice(), constructor, 0, None) + // .await + // .expect("Instantiate failed") + // .account_id; + + // let constructor = ContractRef::new(Percentage::new(0)); + + // let _contract: AccountId = client + // .instantiate("contract", &ink_e2e::alice(), constructor, 0, None) + // .await + // .expect("Instantiate failed") + // .account_id; + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn change_protocol_fee(mut client: ink_e2e::Client) -> E2EResult<()> { + // let contract = create_dex!(client, ContractRef, Percentage::new(0)); + + // let protocol_fee = { + // let _msg = build_message::(contract.clone()) + // .call(|contract| contract.get_protocol_fee()); + // client + // .call(&ink_e2e::alice(), _msg, 0, None) + // .await + // .expect("getting protocol fee failed") + // } + // .return_value(); + + // assert_eq!(protocol_fee, Percentage::new(0)); + + // let _result = { + // let _msg = build_message::(contract.clone()) + // .call(|contract| contract.change_protocol_fee(Percentage::new(1))); + // client + // .call(&ink_e2e::alice(), _msg, 0, None) + // .await + // .expect("changing protocol fee failed") + // }; + + // let protocol_fee = { + // let _msg = build_message::(contract.clone()) + // .call(|contract| contract.get_protocol_fee()); + // client + // .call(&ink_e2e::alice(), _msg, 0, None) + // .await + // .expect("getting protocol fee failed") + // } + // .return_value(); + + // assert_eq!(protocol_fee, Percentage::new(1)); + + // Ok(()) + // } + + // #[ink_e2e::test] + // #[should_panic] + // async fn change_protocol_fee_should_panic(mut client: ink_e2e::Client) -> () { + // let contract = create_dex!(client, ContractRef, Percentage::new(0)); + + // let result = { + // let _msg = build_message::(contract.clone()) + // .call(|contract| contract.change_protocol_fee(Percentage::new(1))); + // client + // .call(&ink_e2e::bob(), _msg, 0, None) + // .await + // .expect("changing protocol fee failed") + // }; + // } + + // #[ink_e2e::test] + // async fn create_position(mut client: ink_e2e::Client) -> E2EResult<()> { + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); + + // let alice = ink_e2e::alice(); + + // let fee_tier = FeeTier::new(Percentage::new(0), 1); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let pool = create_pool!(client, ContractRef, dex, token_x, token_y, fee_tier, 10); + + // approve!(client, TokenRef, token_x, dex, 500, alice); + // approve!(client, TokenRef, token_y, dex, 500, alice); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + // let position = create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // -10, + // 10, + // Liquidity::new(10), + // SqrtPrice::new(0), + // SqrtPrice::max_instance(), + // alice + // ); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn create_fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let fee_tier = FeeTier::new(Percentage::new(0), 10u16); + // let alice = ink_e2e::alice(); + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + // let fee_tier = get_fee_tier!(client, ContractRef, dex, Percentage::new(0), 10u16); + // assert!(fee_tier.is_some()); + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn create_standard_fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // create_standard_fee_tiers!(client, ContractRef, dex); + // let fee_tier = get_fee_tier!( + // client, + // ContractRef, + // dex, + // Percentage::from_scale(5, 2), + // 100u16 + // ); + // assert!(fee_tier.is_some()); + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn create_pool_test(mut client: ink_e2e::Client) -> E2EResult<()> { + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); + + // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); + // let init_tick = 0; + + // let alice = ink_e2e::alice(); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let result = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + // assert!(result.is_ok()); + + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let admin = ink_e2e::alice(); + // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); + // let result = create_fee_tier!(client, ContractRef, dex, fee_tier, admin); + // assert!(result.is_ok()); + // Ok(()) + // } + // #[ink_e2e::test] + // #[should_panic] + // async fn invalid_spacing_fee_tier_test(mut client: ink_e2e::Client) -> () { + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let admin = ink_e2e::alice(); + // // 0 tick spacing | should fail + // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 0); + // let result = create_fee_tier!(client, ContractRef, dex, fee_tier, admin); + // } + + // #[ink_e2e::test] + // #[should_panic] + // async fn non_admin_fee_tier_caller_test(mut client: ink_e2e::Client) -> () { + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let user = ink_e2e::bob(); + // // not-admin + // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 10); + // let result = create_fee_tier!(client, ContractRef, dex, fee_tier, user); + // } + + // #[ink_e2e::test] + // async fn position_above_current_tick_test( + // mut client: ink_e2e::Client, + // ) -> E2EResult<()> { + // let alice = ink_e2e::alice(); + // let init_tick = -23028; + + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let initial_balance = 10_000_000_000; + + // let (token_x, token_y) = + // create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); + + // let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let pool = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // approve!(client, TokenRef, token_x, dex, initial_balance, alice); + // approve!(client, TokenRef, token_y, dex, initial_balance, alice); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // let lower_tick_index = -22980; + // let upper_tick_index = 0; + // let liquidity_delta = Liquidity::new(initial_balance); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // SqrtPrice::max_instance(), + // alice + // ); + + // // Load states + // let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let lower_tick = + // get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + // let upper_tick = + // get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + // let lower_tick_bit = + // tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + // let upper_tick_bit = + // tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + // let alice_x = balance_of!(TokenRef, client, token_x, Alice); + // let alice_y = balance_of!(TokenRef, client, token_y, Alice); + // let dex_x = dex_balance!(TokenRef, client, token_x, dex); + // let dex_y = dex_balance!(TokenRef, client, token_y, dex); + + // let zero_fee = FeeGrowth::new(0); + // let expected_x_increase = 21549; + // let expected_y_increase = 0; + + // // Check ticks + // assert!(lower_tick.index == lower_tick_index); + // assert!(upper_tick.index == upper_tick_index); + // assert_eq!(lower_tick.liquidity_gross, liquidity_delta); + // assert_eq!(upper_tick.liquidity_gross, liquidity_delta); + // assert_eq!(lower_tick.liquidity_change, liquidity_delta); + // assert_eq!(upper_tick.liquidity_change, liquidity_delta); + // assert!(lower_tick.sign); + // assert!(!upper_tick.sign); + + // // Check pool + // assert!(pool_state.liquidity == Liquidity::new(0)); + // assert!(pool_state.current_tick_index == init_tick); + + // // Check position + // assert!(position_state.pool_key == pool_key); + // assert!(position_state.liquidity == liquidity_delta); + // assert!(position_state.lower_tick_index == lower_tick_index); + // assert!(position_state.upper_tick_index == upper_tick_index); + // assert!(position_state.fee_growth_inside_x == zero_fee); + // assert!(position_state.fee_growth_inside_y == zero_fee); + + // // Check balances + // assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); + // assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); + + // assert_eq!(dex_x, expected_x_increase); + // assert_eq!(dex_y, expected_y_increase); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn multiple_positions_on_same_tick( + // mut client: ink_e2e::Client, + // ) -> E2EResult<()> { + // let alice = ink_e2e::alice(); + // let init_tick = 0; + + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let initial_balance = 100_000_000; + + // let (token_x, token_y) = + // create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); + + // let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 10); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let pool = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // approve!(client, TokenRef, token_x, dex, initial_balance, alice); + // approve!(client, TokenRef, token_y, dex, initial_balance, alice); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // // Three position on same lower and upper tick + // { + // let lower_tick_index = -10; + // let upper_tick_index = 10; + + // let liquidity_delta = Liquidity::new(100); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // SqrtPrice::max_instance(), + // alice + // ); + + // let first_position = get_position!(client, ContractRef, dex, 0, alice).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // SqrtPrice::max_instance(), + // alice + // ); + + // let second_position = get_position!(client, ContractRef, dex, 1, alice).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // SqrtPrice::max_instance(), + // alice + // ); + + // let third_position = get_position!(client, ContractRef, dex, 2, alice).unwrap(); + + // assert!(first_position.lower_tick_index == second_position.lower_tick_index); + // assert!(first_position.upper_tick_index == second_position.upper_tick_index); + // assert!(first_position.lower_tick_index == third_position.lower_tick_index); + // assert!(first_position.upper_tick_index == third_position.upper_tick_index); + + // // Load states + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let lower_tick = + // get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + // let upper_tick = + // get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + // let lower_tick_bit = + // tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + // let upper_tick_bit = + // tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + // let expected_liquidity = Liquidity::new(liquidity_delta.get() * 3); + // let zero_fee = FeeGrowth::new(0); + + // // Check ticks + // assert!(lower_tick.index == lower_tick_index); + // assert!(upper_tick.index == upper_tick_index); + // assert_eq!(lower_tick.liquidity_gross, expected_liquidity); + // assert_eq!(upper_tick.liquidity_gross, expected_liquidity); + // assert_eq!(lower_tick.liquidity_change, expected_liquidity); + // assert_eq!(upper_tick.liquidity_change, expected_liquidity); + // assert!(lower_tick.sign); + // assert!(!upper_tick.sign); + + // // Check pool + // assert_eq!(pool_state.liquidity, expected_liquidity); + // assert!(pool_state.current_tick_index == init_tick); + + // // Check first position + // assert!(first_position.pool_key == pool_key); + // assert!(first_position.liquidity == liquidity_delta); + // assert!(first_position.lower_tick_index == lower_tick_index); + // assert!(first_position.upper_tick_index == upper_tick_index); + // assert!(first_position.fee_growth_inside_x == zero_fee); + // assert!(first_position.fee_growth_inside_y == zero_fee); + + // // Check second position + // assert!(second_position.pool_key == pool_key); + // assert!(second_position.liquidity == liquidity_delta); + // assert!(second_position.lower_tick_index == lower_tick_index); + // assert!(second_position.upper_tick_index == upper_tick_index); + // assert!(second_position.fee_growth_inside_x == zero_fee); + // assert!(second_position.fee_growth_inside_y == zero_fee); + + // // Check third position + // assert!(third_position.pool_key == pool_key); + // assert!(third_position.liquidity == liquidity_delta); + // assert!(third_position.lower_tick_index == lower_tick_index); + // assert!(third_position.upper_tick_index == upper_tick_index); + // assert!(third_position.fee_growth_inside_x == zero_fee); + // assert!(third_position.fee_growth_inside_y == zero_fee); + // } + // { + // let lower_tick_index = -10; + // let upper_tick_index = 10; + // let zero_fee = FeeGrowth::new(0); + + // let liquidity_delta = Liquidity::new(100); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // SqrtPrice::max_instance(), + // alice + // ); + + // let first_position = get_position!(client, ContractRef, dex, 3, alice).unwrap(); + + // // Check first position + // assert!(first_position.pool_key == pool_key); + // assert!(first_position.liquidity == liquidity_delta); + // assert!(first_position.lower_tick_index == lower_tick_index); + // assert!(first_position.upper_tick_index == upper_tick_index); + // assert!(first_position.fee_growth_inside_x == zero_fee); + // assert!(first_position.fee_growth_inside_y == zero_fee); + + // let lower_tick_index = -20; + // let upper_tick_index = -10; + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // SqrtPrice::max_instance(), + // alice + // ); + + // let second_position = get_position!(client, ContractRef, dex, 4, alice).unwrap(); + + // // Check second position + // assert!(second_position.pool_key == pool_key); + // assert!(second_position.liquidity == liquidity_delta); + // assert!(second_position.lower_tick_index == lower_tick_index); + // assert!(second_position.upper_tick_index == upper_tick_index); + // assert!(second_position.fee_growth_inside_x == zero_fee); + // assert!(second_position.fee_growth_inside_y == zero_fee); + + // let lower_tick_index = 10; + // let upper_tick_index = 20; + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // SqrtPrice::max_instance(), + // alice + // ); + + // let third_position = get_position!(client, ContractRef, dex, 5, alice).unwrap(); + + // // Check third position + // assert!(third_position.pool_key == pool_key); + // assert!(third_position.liquidity == liquidity_delta); + // assert!(third_position.lower_tick_index == lower_tick_index); + // assert!(third_position.upper_tick_index == upper_tick_index); + // assert!(third_position.fee_growth_inside_x == zero_fee); + // assert!(third_position.fee_growth_inside_y == zero_fee); + + // // Load states + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let tick_n20 = get_tick!(client, ContractRef, dex, -20, pool_key, alice).unwrap(); + // let tick_n10 = get_tick!(client, ContractRef, dex, -10, pool_key, alice).unwrap(); + // let tick_10 = get_tick!(client, ContractRef, dex, 10, pool_key, alice).unwrap(); + // let tick_20 = get_tick!(client, ContractRef, dex, 20, pool_key, alice).unwrap(); + // let tick_n20_bit = tickmap_bit!(client, ContractRef, dex, -20, pool_key, alice); + // let tick_n10_bit = tickmap_bit!(client, ContractRef, dex, -10, pool_key, alice); + // let tick_10_bit = tickmap_bit!(client, ContractRef, dex, 10, pool_key, alice); + // let tick_20_bit = tickmap_bit!(client, ContractRef, dex, 20, pool_key, alice); + + // let expected_active_liquidity = Liquidity::new(400); + + // // Check tick -20 + // assert_eq!(tick_n20.index, -20); + // assert_eq!(tick_n20.liquidity_gross, Liquidity::new(100)); + // assert_eq!(tick_n20.liquidity_change, Liquidity::new(100)); + // assert!(tick_n20.sign); + // assert!(tick_n20_bit); + + // // Check tick -10 + // assert_eq!(tick_n10.index, -10); + // assert_eq!(tick_n10.liquidity_gross, Liquidity::new(500)); + // assert_eq!(tick_n10.liquidity_change, Liquidity::new(300)); + // assert!(tick_n10.sign); + // assert!(tick_n10_bit); + + // // Check tick 10 + // assert_eq!(tick_10.index, 10); + // assert_eq!(tick_10.liquidity_gross, Liquidity::new(500)); + // assert_eq!(tick_10.liquidity_change, Liquidity::new(300)); + // assert!(!tick_10.sign); + // assert!(tick_20_bit); + + // // Check tick 20 + // assert_eq!(tick_20.index, 20); + // assert_eq!(tick_20.liquidity_gross, Liquidity::new(100)); + // assert_eq!(tick_20.liquidity_change, Liquidity::new(100)); + // assert!(!tick_20.sign); + // assert!(tick_20_bit); + + // // Check pool + // assert_eq!(pool_state.liquidity, expected_active_liquidity); + // assert!(pool_state.current_tick_index == init_tick); + // } + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn position_within_current_tick_test( + // mut client: ink_e2e::Client, + // ) -> E2EResult<()> { + // let MAX_TICK_TEST = 177_450; // for tickSpacing 4 + // let MIN_TICK_TEST = -MAX_TICK_TEST; + // let alice = ink_e2e::alice(); + // let init_tick = -23028; + + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let initial_balance = 100_000_000; + + // let (token_x, token_y) = + // create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); + + // let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let pool = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // approve!(client, TokenRef, token_x, dex, initial_balance, alice); + // approve!(client, TokenRef, token_y, dex, initial_balance, alice); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // let lower_tick_index = MIN_TICK_TEST + 10; + // let upper_tick_index = MAX_TICK_TEST - 10; + + // let liquidity_delta = Liquidity::new(initial_balance); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // SqrtPrice::max_instance(), + // alice + // ); + + // // Load states + // let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let lower_tick = + // get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + // let upper_tick = + // get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + // let lower_tick_bit = + // tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + // let upper_tick_bit = + // tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + // let alice_x = balance_of!(TokenRef, client, token_x, Alice); + // let alice_y = balance_of!(TokenRef, client, token_y, Alice); + // let dex_x = dex_balance!(TokenRef, client, token_x, dex); + // let dex_y = dex_balance!(TokenRef, client, token_y, dex); + + // let zero_fee = FeeGrowth::new(0); + // let expected_x_increase = 317; + // let expected_y_increase = 32; + + // // Check ticks + // assert!(lower_tick.index == lower_tick_index); + // assert!(upper_tick.index == upper_tick_index); + // assert_eq!(lower_tick.liquidity_gross, liquidity_delta); + // assert_eq!(upper_tick.liquidity_gross, liquidity_delta); + // assert_eq!(lower_tick.liquidity_change, liquidity_delta); + // assert_eq!(upper_tick.liquidity_change, liquidity_delta); + // assert!(lower_tick.sign); + // assert!(!upper_tick.sign); + + // // Check pool + // assert!(pool_state.liquidity == liquidity_delta); + // assert!(pool_state.current_tick_index == init_tick); + + // // Check position + // assert!(position_state.pool_key == pool_key); + // assert!(position_state.liquidity == liquidity_delta); + // assert!(position_state.lower_tick_index == lower_tick_index); + // assert!(position_state.upper_tick_index == upper_tick_index); + // assert!(position_state.fee_growth_inside_x == zero_fee); + // assert!(position_state.fee_growth_inside_y == zero_fee); + + // // Check balances + // assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); + // assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); + // assert_eq!(dex_x, expected_x_increase); + // assert_eq!(dex_y, expected_y_increase); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn position_below_current_tick_test( + // mut client: ink_e2e::Client, + // ) -> E2EResult<()> { + // let alice = ink_e2e::alice(); + // let init_tick = -23028; + + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let initial_balance = 100_000_000_00; + + // let (token_x, token_y) = + // create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); + + // let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let pool = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // approve!(client, TokenRef, token_x, dex, initial_balance, alice); + // approve!(client, TokenRef, token_y, dex, initial_balance, alice); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // let lower_tick_index = -46080; + // let upper_tick_index = -23040; + + // let liquidity_delta = Liquidity::new(initial_balance); + + // let pool_state_before = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state_before.sqrt_price, + // SqrtPrice::max_instance(), + // alice + // ); + + // // Load states + // let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let lower_tick = + // get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + // let upper_tick = + // get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + // let lower_tick_bit = + // tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + // let upper_tick_bit = + // tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + // let alice_x = balance_of!(TokenRef, client, token_x, Alice); + // let alice_y = balance_of!(TokenRef, client, token_y, Alice); + // let dex_x = dex_balance!(TokenRef, client, token_x, dex); + // let dex_y = dex_balance!(TokenRef, client, token_y, dex); + + // let zero_fee = FeeGrowth::new(0); + // let expected_x_increase = 0; + // let expected_y_increase = 2162; + + // // Check ticks + // assert!(lower_tick.index == lower_tick_index); + // assert!(upper_tick.index == upper_tick_index); + // assert_eq!(lower_tick.liquidity_gross, liquidity_delta); + // assert_eq!(upper_tick.liquidity_gross, liquidity_delta); + // assert_eq!(lower_tick.liquidity_change, liquidity_delta); + // assert_eq!(upper_tick.liquidity_change, liquidity_delta); + // assert!(lower_tick.sign); + // assert!(!upper_tick.sign); + + // // Check pool + // assert!(pool_state.liquidity == pool_state_before.liquidity); + // assert!(pool_state.current_tick_index == init_tick); + + // // Check position + // assert!(position_state.pool_key == pool_key); + // assert!(position_state.liquidity == liquidity_delta); + // assert!(position_state.lower_tick_index == lower_tick_index); + // assert!(position_state.upper_tick_index == upper_tick_index); + // assert!(position_state.fee_growth_inside_x == zero_fee); + // assert!(position_state.fee_growth_inside_y == zero_fee); + + // // Check balances + // assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); + // assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); + + // assert_eq!(dex_x, expected_x_increase); + // assert_eq!(dex_y, expected_y_increase); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn change_fee_reciever_test(mut client: ink_e2e::Client) -> E2EResult<()> { + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); + + // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 1); + // let init_tick = 0; + + // let alice = ink_e2e::alice(); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let result = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + // assert!(result.is_ok()); + + // let admin = ink_e2e::alice(); + // let alice = address_of!(Alice); + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // change_fee_receiver!(client, ContractRef, dex, pool_key, alice, admin); + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // assert_eq!(pool.fee_receiver, alice); + + // Ok(()) + // } + + // #[ink_e2e::test] + // #[should_panic] + // async fn not_admin_change_fee_reciever_test(mut client: ink_e2e::Client) -> () { + // let dex = create_dex!(client, ContractRef, Percentage::new(0)); + // let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); + + // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); + // let init_tick = 0; + + // let admin = ink_e2e::alice(); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, admin); + + // let result = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + // assert!(result.is_ok()); + + // let user = ink_e2e::bob(); + // let bob = address_of!(Bob); + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // change_fee_receiver!(client, ContractRef, dex, pool_key, bob, user); + // } + + // #[ink_e2e::test] + // async fn remove_position_test(mut client: ink_e2e::Client) -> E2EResult<()> { + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + // let alice = ink_e2e::alice(); + // let bob = ink_e2e::bob(); + // let init_tick = 0; + // let remove_position_index = 0; + + // let initial_mint = 10u128.pow(10); + + // let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); + // let (token_x, token_y) = + // create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let pool = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // let lower_tick_index = -20; + // let upper_tick_index = 10; + // let liquidity_delta = Liquidity::from_integer(1_000_000); + + // approve!(client, TokenRef, token_x, dex, initial_mint, alice); + // approve!(client, TokenRef, token_y, dex, initial_mint, alice); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // pool_state.sqrt_price, + // alice + // ); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // assert_eq!(pool_state.liquidity, liquidity_delta); + + // let liquidity_delta = Liquidity::new(liquidity_delta.get() * 1_000_000); + // { + // let incorrect_lower_tick_index = lower_tick_index - 50; + // let incorrect_upper_tick_index = upper_tick_index + 50; + + // approve!(client, TokenRef, token_x, dex, liquidity_delta.get(), alice); + // approve!(client, TokenRef, token_y, dex, liquidity_delta.get(), alice); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // incorrect_lower_tick_index, + // incorrect_upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // pool_state.sqrt_price, + // alice + // ); + + // let position_state = get_position!(client, ContractRef, dex, 1, alice).unwrap(); + // // Check position + // assert!(position_state.lower_tick_index == incorrect_lower_tick_index); + // assert!(position_state.upper_tick_index == incorrect_upper_tick_index); + // } + + // let amount = 1000; + // mint!(TokenRef, client, token_x, Bob, amount); + // let amount_x = balance_of!(TokenRef, client, token_x, Bob); + // assert_eq!(amount_x, amount); + + // approve!(client, TokenRef, token_x, dex, amount, bob); + + // let pool_state_before = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // let swap_amount = TokenAmount::new(amount); + // let slippage = SqrtPrice::new(MIN_SQRT_PRICE); + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // slippage, + // bob + // ); + + // let pool_state_after = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // assert_eq!( + // pool_state_after.fee_growth_global_x, + // FeeGrowth::new(49999950000049999) + // ); + // assert_eq!(pool_state_after.fee_protocol_token_x, TokenAmount(1)); + // assert_eq!(pool_state_after.fee_protocol_token_y, TokenAmount(0)); + + // assert!(pool_state_after + // .sqrt_price + // .lt(&pool_state_before.sqrt_price)); + + // assert_eq!(pool_state_after.liquidity, pool_state_before.liquidity); + // assert_eq!(pool_state_after.current_tick_index, -10); + // assert_ne!(pool_state_after.sqrt_price, pool_state_before.sqrt_price); + + // let amount_x = balance_of!(TokenRef, client, token_x, Bob); + // let amount_y = balance_of!(TokenRef, client, token_y, Bob); + // assert_eq!(amount_x, 0); + // assert_eq!(amount_y, 993); + + // // pre load dex balances + // let dex_x_before_remove = dex_balance!(TokenRef, client, token_x, dex); + // let dex_y_before_remove = dex_balance!(TokenRef, client, token_y, dex); + + // // Remove position + // let remove_result = + // remove_position!(client, ContractRef, dex, remove_position_index, alice); + + // // Load states + // let position_state = + // get_position!(client, ContractRef, dex, remove_position_index, alice); + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let lower_tick = get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + // let upper_tick = get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + // let lower_tick_bit = + // tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + // let upper_tick_bit = + // tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + // let alice_x = balance_of!(TokenRef, client, token_x, Alice); + // let alice_y = balance_of!(TokenRef, client, token_y, Alice); + // let dex_x = dex_balance!(TokenRef, client, token_x, dex); + // let dex_y = dex_balance!(TokenRef, client, token_y, dex); + // let expected_withdrawn_x = 499; + // let expected_withdrawn_y = 999; + // let expected_fee_x = 0; + + // assert_eq!( + // dex_x_before_remove - dex_x, + // expected_withdrawn_x + expected_fee_x + // ); + // assert_eq!(dex_y_before_remove - dex_y, expected_withdrawn_y); + + // // Check ticks + // assert_eq!(lower_tick, Err(InvariantError::TickNotFound)); + // assert_eq!(upper_tick, Err(InvariantError::TickNotFound)); + + // // Check tickmap + // assert!(!lower_tick_bit); + // assert!(!upper_tick_bit); + + // // Check pool + // assert!(pool_state.liquidity == liquidity_delta); + // assert!(pool_state.current_tick_index == -10); + + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn position_slippage_zero_slippage_and_inside_range( + // mut client: ink_e2e::Client, + // ) -> E2EResult<()> { + // let alice = ink_e2e::alice(); + // let (dex, token_x, token_y) = + // init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); + // let pool_key = create_slippage_pool_with_liquidity!( + // client, + // ContractRef, + // TokenRef, + // dex, + // token_x, + // token_y + // ); + + // let pool = get_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // pool_key.fee_tier + // ) + // .unwrap(); + + // // zero slippage + // { + // let liquidity_delta = Liquidity::from_integer(1_000_000); + // let known_price = pool.sqrt_price; + // let tick = pool_key.fee_tier.tick_spacing as i32; + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // -tick, + // tick, + // liquidity_delta, + // known_price, + // known_price, + // alice + // ); + // } + // // inside range + // { + // let liquidity_delta = Liquidity::from_integer(1_000_000); + // let known_price = SqrtPrice::new(1010000000000000000000000); + // let limit_lower = SqrtPrice::new(994734637981406576896367); + // let limit_upper = SqrtPrice::new(1025038048074314166333500); + + // let tick = pool_key.fee_tier.tick_spacing as i32; + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // -tick, + // tick, + // liquidity_delta, + // limit_lower, + // limit_upper, + // alice + // ); + // } + + // Ok(()) + // } + // #[ink_e2e::test] + // #[should_panic] + // async fn position_slippage_below_range(mut client: ink_e2e::Client) -> () { + // let alice = ink_e2e::alice(); + // let (dex, token_x, token_y) = + // init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); + // let pool_key = create_slippage_pool_with_liquidity!( + // client, + // ContractRef, + // TokenRef, + // dex, + // token_x, + // token_y + // ); + + // let pool = get_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // pool_key.fee_tier + // ) + // .unwrap(); + + // let liquidity_delta = Liquidity::from_integer(1_000_000); + // let known_price = SqrtPrice::new(1030000000000000000000000); + // let limit_lower = SqrtPrice::new(1014432353584998786339859); + // let limit_upper = SqrtPrice::new(1045335831204498605270797); + // let tick = pool_key.fee_tier.tick_spacing as i32; + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // -tick, + // tick, + // liquidity_delta, + // limit_lower, + // limit_upper, + // alice + // ); + // } + // #[ink_e2e::test] + // #[should_panic] + // async fn position_slippage_above_range(mut client: ink_e2e::Client) -> () { + // let alice = ink_e2e::alice(); + // let (dex, token_x, token_y) = + // init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); + // let pool_key = create_slippage_pool_with_liquidity!( + // client, + // ContractRef, + // TokenRef, + // dex, + // token_x, + // token_y + // ); + + // let pool = get_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // pool_key.fee_tier + // ) + // .unwrap(); + + // let liquidity_delta = Liquidity::from_integer(1_000_000); + // let known_price = pool.sqrt_price; + // let limit_lower = SqrtPrice::new(955339206774222158009382); + // let limit_upper = SqrtPrice::new(984442481813945288458906); + // let tick = pool_key.fee_tier.tick_spacing as i32; + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // -tick, + // tick, + // liquidity_delta, + // limit_lower, + // limit_upper, + // alice + // ); + // } + + // #[ink_e2e::test] + // #[should_panic] + // async fn no_liquidity_swap(mut client: ink_e2e::Client) -> () { + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + // let alice = ink_e2e::alice(); + // let bob = ink_e2e::bob(); + // let init_tick = 0; + + // let initial_mint = 10u128.pow(10); + + // let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); + // let (token_x, token_y) = + // create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let pool = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // let lower_tick_index = -10; + // let upper_tick_index = 10; + + // let mint_amount = 10u128.pow(10); + // mint!(TokenRef, client, token_x, Alice, mint_amount); + // mint!(TokenRef, client, token_y, Alice, mint_amount); + + // approve!(client, TokenRef, token_x, dex, mint_amount, alice); + // approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + // let liquidity_delta = Liquidity::from_integer(20_006_000); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // pool_state.sqrt_price, + // alice + // ); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // assert_eq!(pool_state.liquidity, liquidity_delta); + + // let mint_amount = 10067; + // mint!(TokenRef, client, token_x, Bob, mint_amount); + + // approve!(client, TokenRef, token_x, dex, mint_amount, bob); + + // let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); + // let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); + + // let swap_amount = TokenAmount::new(10067); + // let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + // let quoted_target_sqrt_price = quote!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // target_sqrt_price, + // alice + // ) + // .unwrap() + // .2; + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // quoted_target_sqrt_price, + // bob + // ); + + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let expected_price = calculate_sqrt_price(-10).unwrap(); + // let expected_y_amount_out = 9999; + + // assert_eq!(pool.liquidity, liquidity_delta); + // assert_eq!(pool.current_tick_index, lower_tick_index); + // assert_eq!(pool.sqrt_price, expected_price); + + // let bob_x = balance_of!(TokenRef, client, token_x, Bob); + // let bob_y = balance_of!(TokenRef, client, token_y, Bob); + // let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); + // let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); + + // let delta_dex_x = dex_x_after - dex_x_before; + // let delta_dex_y = dex_y_before - dex_y_after; + + // assert_eq!(bob_x, 0); + // assert_eq!(bob_y, expected_y_amount_out); + // assert_eq!(delta_dex_x, swap_amount.get()); + // assert_eq!(delta_dex_y, expected_y_amount_out); + // assert_eq!( + // pool.fee_growth_global_x, + // FeeGrowth::new(29991002699190242927121) + // ); + // assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); + // assert_eq!(pool.fee_protocol_token_x, TokenAmount::new(1)); + // assert_eq!(pool.fee_protocol_token_y, TokenAmount::new(0)); + + // let swap_amount = TokenAmount(1); + // let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + // let quoted_target_sqrt_price = quote!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // target_sqrt_price, + // alice + // ) + // .unwrap() + // .2; + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // quoted_target_sqrt_price, + // bob + // ); + // } + + // #[ink_e2e::test] + // async fn liquidity_gap_test(mut client: ink_e2e::Client) -> E2EResult<()> { + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + // let alice = ink_e2e::alice(); + // let bob = ink_e2e::bob(); + // let init_tick = 0; + + // let initial_mint = 10u128.pow(10); + + // let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); + // let (token_x, token_y) = + // create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let pool = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // let lower_tick_index = -10; + // let upper_tick_index = 10; + + // let mint_amount = 10u128.pow(10); + // mint!(TokenRef, client, token_x, Alice, mint_amount); + // mint!(TokenRef, client, token_y, Alice, mint_amount); + + // approve!(client, TokenRef, token_x, dex, mint_amount, alice); + // approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + // let liquidity_delta = Liquidity::from_integer(20_006_000); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // pool_state.sqrt_price, + // alice + // ); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // assert_eq!(pool_state.liquidity, liquidity_delta); + + // let mint_amount = 10067; + // mint!(TokenRef, client, token_x, Bob, mint_amount); + + // approve!(client, TokenRef, token_x, dex, mint_amount, bob); + + // let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); + // let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); + + // let swap_amount = TokenAmount::new(10067); + // let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + // let quoted_target_sqrt_price = quote!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // target_sqrt_price, + // alice + // ) + // .unwrap() + // .2; + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // quoted_target_sqrt_price, + // bob + // ); + + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let expected_price = calculate_sqrt_price(-10).unwrap(); + // let expected_y_amount_out = 9999; + + // assert_eq!(pool.liquidity, liquidity_delta); + // assert_eq!(pool.current_tick_index, lower_tick_index); + // assert_eq!(pool.sqrt_price, expected_price); + + // let bob_x = balance_of!(TokenRef, client, token_x, Bob); + // let bob_y = balance_of!(TokenRef, client, token_y, Bob); + // let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); + // let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); + + // let delta_dex_x = dex_x_after - dex_x_before; + // let delta_dex_y = dex_y_before - dex_y_after; + + // assert_eq!(bob_x, 0); + // assert_eq!(bob_y, expected_y_amount_out); + // assert_eq!(delta_dex_x, swap_amount.get()); + // assert_eq!(delta_dex_y, expected_y_amount_out); + // assert_eq!( + // pool.fee_growth_global_x, + // FeeGrowth::new(29991002699190242927121) + // ); + // assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); + // assert_eq!(pool.fee_protocol_token_x, TokenAmount::new(1)); + // assert_eq!(pool.fee_protocol_token_y, TokenAmount::new(0)); + + // // Should skip gap and then swap + // let lower_tick_after_swap = -90; + // let upper_tick_after_swap = -50; + // let liquidity_delta = Liquidity::from_integer(20008000); + + // approve!(client, TokenRef, token_x, dex, liquidity_delta.get(), alice); + // approve!(client, TokenRef, token_y, dex, liquidity_delta.get(), alice); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_after_swap, + // upper_tick_after_swap, + // liquidity_delta, + // pool_state.sqrt_price, + // pool_state.sqrt_price, + // alice + // ); + + // let swap_amount = TokenAmount::new(5000); + // mint!(TokenRef, client, token_x, Bob, swap_amount.get()); + + // approve!(client, TokenRef, token_x, dex, swap_amount.get(), bob); + + // let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); + // let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); + + // let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + // let quoted_target_sqrt_price = quote!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // target_sqrt_price, + // alice + // ) + // .unwrap() + // .2; + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // swap_amount, + // true, + // quoted_target_sqrt_price, + // bob + // ); + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // let bob_x = balance_of!(TokenRef, client, token_x, Bob); + // let bob_y = balance_of!(TokenRef, client, token_y, Bob); + // let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); + // let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); + + // let delta_dex_x = dex_x_after - dex_x_before; + // let delta_dex_y = dex_y_before - dex_y_after; + // Ok(()) + // } + + // #[ink_e2e::test] + // async fn cross_both_side_test(mut client: ink_e2e::Client) -> E2EResult<()> { + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + // let alice = ink_e2e::alice(); + // let bob = ink_e2e::bob(); + // let init_tick = 0; + + // let initial_mint = 10u128.pow(10); + + // let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); + // let (token_x, token_y) = + // create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let pool = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // let lower_tick_index = -10; + // let upper_tick_index = 10; + + // let mint_amount = 10u128.pow(5); + // mint!(TokenRef, client, token_x, Alice, mint_amount); + // mint!(TokenRef, client, token_y, Alice, mint_amount); + + // approve!(client, TokenRef, token_x, dex, mint_amount, alice); + // approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + // let liquidity_delta = Liquidity::new(20006000000000); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // pool_state.sqrt_price, + // alice + // ); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // -20, + // lower_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // pool_state.sqrt_price, + // alice + // ); + + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // assert_eq!(pool.liquidity, liquidity_delta); + + // let limit_without_cross_tick_amount = TokenAmount(10_068); + // let not_cross_amount = TokenAmount(1); + // let min_amount_to_cross_from_tick_price = TokenAmount(3); + // let crossing_amount_by_amount_out = TokenAmount(20136101434); + + // let mint_amount = limit_without_cross_tick_amount.get() + // + not_cross_amount.get() + // + min_amount_to_cross_from_tick_price.get() + // + crossing_amount_by_amount_out.get(); + + // mint!(TokenRef, client, token_x, Alice, mint_amount); + // mint!(TokenRef, client, token_y, Alice, mint_amount); + + // approve!(client, TokenRef, token_x, dex, mint_amount, alice); + // approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + // let pool_before = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // let limit_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // limit_without_cross_tick_amount, + // true, + // limit_sqrt_price, + // alice + // ); + + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let expected_tick = -10; + // let expected_price = calculate_sqrt_price(expected_tick).unwrap(); + + // assert_eq!(pool.current_tick_index, expected_tick); + // assert_eq!(pool.liquidity, pool_before.liquidity); + // assert_eq!(pool.sqrt_price, expected_price); + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // min_amount_to_cross_from_tick_price, + // true, + // limit_sqrt_price, + // alice + // ); + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // false, + // min_amount_to_cross_from_tick_price, + // true, + // SqrtPrice::new(MAX_SQRT_PRICE), + // alice + // ); + + // let massive_x = 10u128.pow(19); + // let massive_y = 10u128.pow(19); + + // mint!(TokenRef, client, token_x, Alice, massive_x); + // mint!(TokenRef, client, token_y, Alice, massive_y); + // approve!(client, TokenRef, token_x, dex, massive_x, alice); + // approve!(client, TokenRef, token_y, dex, massive_y, alice); + + // let massive_liquidity_delta = Liquidity::new(19996000399699881985603000000); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // -20, + // 0, + // massive_liquidity_delta, + // SqrtPrice::new(MIN_SQRT_PRICE), + // SqrtPrice::new(MAX_SQRT_PRICE), + // alice + // ); + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // TokenAmount(1), + // false, + // limit_sqrt_price, + // alice + // ); + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // false, + // TokenAmount(2), + // true, + // SqrtPrice::new(MAX_SQRT_PRICE), + // alice + // ); + + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // assert_eq!(pool.current_tick_index, -20); + // assert_eq!( + // pool.fee_growth_global_x, + // FeeGrowth::new(29991002699190242927121) + // ); + // assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); + // assert_eq!(pool.fee_protocol_token_x, TokenAmount(4)); + // assert_eq!(pool.fee_protocol_token_y, TokenAmount(2)); + // assert_eq!( + // pool.liquidity, + // Liquidity::new(19996000399699901991603000000) + // ); + // assert_eq!(pool.sqrt_price, SqrtPrice::new(999500149964999999999999)); + + // let final_last_tick = + // get_tick!(client, ContractRef, dex, -20, pool_key, alice).unwrap(); + // assert_eq!(final_last_tick.fee_growth_outside_x, FeeGrowth::new(0)); + // assert_eq!(final_last_tick.fee_growth_outside_y, FeeGrowth::new(0)); + // assert_eq!( + // final_last_tick.liquidity_change, + // Liquidity::new(19996000399699901991603000000) + // ); + + // let final_lower_tick = + // get_tick!(client, ContractRef, dex, -10, pool_key, alice).unwrap(); + // assert_eq!( + // final_lower_tick.fee_growth_outside_x, + // FeeGrowth::new(29991002699190242927121) + // ); + // assert_eq!(final_lower_tick.fee_growth_outside_y, FeeGrowth::new(0)); + // assert_eq!(final_lower_tick.liquidity_change, Liquidity::new(0)); + + // let final_upper_tick = + // get_tick!(client, ContractRef, dex, 10, pool_key, alice).unwrap(); + // assert_eq!(final_upper_tick.fee_growth_outside_x, FeeGrowth::new(0)); + // assert_eq!(final_upper_tick.fee_growth_outside_y, FeeGrowth::new(0)); + // assert_eq!( + // final_upper_tick.liquidity_change, + // Liquidity::new(20006000000000) + // ); + + // Ok(()) + // } + + // #[ink_e2e::test] + // #[should_panic] + // async fn cross_both_side_not_cross_case_test(mut client: ink_e2e::Client) -> () { + // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + // let alice = ink_e2e::alice(); + // let bob = ink_e2e::bob(); + // let init_tick = 0; + + // let initial_mint = 10u128.pow(10); + + // let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); + // let (token_x, token_y) = + // create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); + + // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + // let pool = create_pool!( + // client, + // ContractRef, + // dex, + // token_x, + // token_y, + // fee_tier, + // init_tick + // ); + + // let lower_tick_index = -10; + // let upper_tick_index = 10; + + // let mint_amount = 10u128.pow(5); + // mint!(TokenRef, client, token_x, Alice, mint_amount); + // mint!(TokenRef, client, token_y, Alice, mint_amount); + + // approve!(client, TokenRef, token_x, dex, mint_amount, alice); + // approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + // let liquidity_delta = Liquidity::new(20006000000000); + + // let pool_state = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // lower_tick_index, + // upper_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // pool_state.sqrt_price, + // alice + // ); + + // create_position!( + // client, + // ContractRef, + // dex, + // pool_key, + // -20, + // lower_tick_index, + // liquidity_delta, + // pool_state.sqrt_price, + // pool_state.sqrt_price, + // alice + // ); + + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // assert_eq!(pool.liquidity, liquidity_delta); + + // let limit_without_cross_tick_amount = TokenAmount(10_068); + // let not_cross_amount = TokenAmount(1); + // let min_amount_to_cross_from_tick_price = TokenAmount(3); + // let crossing_amount_by_amount_out = TokenAmount(20136101434); + + // let mint_amount = limit_without_cross_tick_amount.get() + // + not_cross_amount.get() + // + min_amount_to_cross_from_tick_price.get() + // + crossing_amount_by_amount_out.get(); + + // mint!(TokenRef, client, token_x, Alice, mint_amount); + // mint!(TokenRef, client, token_y, Alice, mint_amount); + + // approve!(client, TokenRef, token_x, dex, mint_amount, alice); + // approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + // let pool_before = + // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + // let limit_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // limit_without_cross_tick_amount, + // true, + // limit_sqrt_price, + // alice + // ); + + // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + // let expected_tick = -10; + // let expected_price = calculate_sqrt_price(expected_tick).unwrap(); + + // assert_eq!(pool.current_tick_index, expected_tick); + // assert_eq!(pool.liquidity, pool_before.liquidity); + // assert_eq!(pool.sqrt_price, expected_price); + + // let slippage = SqrtPrice::new(MIN_SQRT_PRICE); + // let target_sqrt_price = quote!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // not_cross_amount, + // true, + // slippage, + // alice + // ) + // .unwrap() + // .2; + + // swap!( + // client, + // ContractRef, + // dex, + // pool_key, + // true, + // not_cross_amount, + // true, + // target_sqrt_price, + // alice + // ); + // } } } From 5db1a2283ccff802806bacc870b330d4df33aa10 Mon Sep 17 00:00:00 2001 From: Sniezka Date: Tue, 28 Nov 2023 21:43:52 +0100 Subject: [PATCH 5/7] Cleanup --- src/lib.rs | 5456 ++++++++++++++++++++++++++-------------------------- 1 file changed, 2728 insertions(+), 2728 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1b1a944d..872c2df7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1360,2733 +1360,2733 @@ pub mod contract { Ok(()) } - // #[ink_e2e::test] - // async fn swap_route(mut client: ink_e2e::Client) -> E2EResult<()> { - // let (dex, token_x, token_y, token_z) = - // init_dex_and_3_tokens!(client, ContractRef, TokenRef); - - // let alice = ink_e2e::alice(); - // approve!(client, TokenRef, token_x, dex, u64::MAX as u128, alice); - // approve!(client, TokenRef, token_y, dex, u64::MAX as u128, alice); - // approve!(client, TokenRef, token_z, dex, u64::MAX as u128, alice); - - // let amount = 1000; - // let bob = ink_e2e::bob(); - // mint_with_aprove_for_bob!(client, TokenRef, token_x, dex, amount); - // approve!(client, TokenRef, token_y, dex, u64::MAX as u128, bob); - - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let init_tick = 0; - // create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // let init_tick = 0; - // create_pool!( - // client, - // ContractRef, - // dex, - // token_y, - // token_z, - // fee_tier, - // init_tick - // ); - - // let pool_key_1 = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // let pool_key_2 = PoolKey::new(token_y, token_z, fee_tier).unwrap(); - - // let liquidity_delta = Liquidity::new(2u128.pow(63) - 1); - - // let pool_1 = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let slippage_limit_lower = pool_1.sqrt_price; - // let slippage_limit_upper = pool_1.sqrt_price; - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key_1, - // -1, - // 1, - // liquidity_delta, - // slippage_limit_lower, - // slippage_limit_upper, - // alice - // ); - - // let pool_2 = get_pool!(client, ContractRef, dex, token_y, token_z, fee_tier).unwrap(); - // let slippage_limit_lower = pool_2.sqrt_price; - // let slippage_limit_upper = pool_2.sqrt_price; - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key_2, - // -1, - // 1, - // liquidity_delta, - // slippage_limit_lower, - // slippage_limit_upper, - // alice - // ); - - // let amount_in = TokenAmount(1000); - // let expected_amount_out = TokenAmount(1000); - // let slippage = Percentage::new(0); - // let swaps = vec![ - // Hop { - // pool_key: pool_key_1, - // x_to_y: true, - // }, - // Hop { - // pool_key: pool_key_2, - // x_to_y: true, - // }, - // ]; - - // let expected_token_amount = - // quote_route!(client, ContractRef, dex, amount_in, swaps.clone(), bob).unwrap(); - - // swap_route!( - // client, - // ContractRef, - // dex, - // amount_in, - // expected_token_amount, - // slippage, - // swaps.clone(), - // bob - // ); - - // let bob_amount_x = balance_of!(TokenRef, client, token_x, Bob); - // let bob_amount_y = balance_of!(TokenRef, client, token_y, Bob); - // let bob_amount_z = balance_of!(TokenRef, client, token_z, Bob); - - // assert_eq!(bob_amount_x, 0); - // assert_eq!(bob_amount_y, 0); - // assert_eq!(bob_amount_z, 986); - - // let pool_1_after = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // assert_eq!(pool_1_after.fee_protocol_token_x, TokenAmount(1)); - // assert_eq!(pool_1_after.fee_protocol_token_y, TokenAmount(0)); - - // let pool_2_after = - // get_pool!(client, ContractRef, dex, token_y, token_z, fee_tier).unwrap(); - // assert_eq!(pool_2_after.fee_protocol_token_x, TokenAmount(1)); - // assert_eq!(pool_2_after.fee_protocol_token_y, TokenAmount(0)); - - // let alice_amount_x_before = balance_of!(TokenRef, client, token_x, Alice); - // let alice_amount_y_before = balance_of!(TokenRef, client, token_y, Alice); - // let alice_amount_z_before = balance_of!(TokenRef, client, token_z, Alice); - - // claim_fee!(client, ContractRef, dex, 0, alice); - // claim_fee!(client, ContractRef, dex, 1, alice); - - // let alice_amount_x_after = balance_of!(TokenRef, client, token_x, Alice); - // let alice_amount_y_after = balance_of!(TokenRef, client, token_y, Alice); - // let alice_amount_z_after = balance_of!(TokenRef, client, token_z, Alice); - - // assert_eq!(alice_amount_x_after - alice_amount_x_before, 4); - // assert_eq!(alice_amount_y_after - alice_amount_y_before, 4); - // assert_eq!(alice_amount_z_after - alice_amount_z_before, 0); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn limits_full_range_with_max_liquidity(mut client: ink_e2e::Client) -> () { - // let (dex, token_x, token_y) = - // init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); - - // let mint_amount = u128::MAX; - // let alice = ink_e2e::alice(); - // approve!(client, TokenRef, token_x, dex, u128::MAX, alice); - // approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let init_tick = get_max_tick(1); - // create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let current_sqrt_price = pool.sqrt_price; - // assert_eq!(pool.current_tick_index, init_tick); - // assert_eq!(pool.sqrt_price, calculate_sqrt_price(init_tick).unwrap()); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // let liquidity_delta = Liquidity::new(2u128.pow(109) - 1); - // let slippage_limit_lower = pool.sqrt_price; - // let slippage_limit_upper = pool.sqrt_price; - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // -MAX_TICK, - // MAX_TICK, - // liquidity_delta, - // slippage_limit_lower, - // slippage_limit_upper, - // alice - // ); - - // let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); - // let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); - - // let expected_x = 0; - // let expected_y = 42534896005851865508212194815854; - // assert_eq!(contract_amount_x, expected_x); - // assert_eq!(contract_amount_y, expected_y); - // } - - // #[ink_e2e::test] - // async fn deposit_limits_at_upper_limit(mut client: ink_e2e::Client) -> E2EResult<()> { - // let (dex, token_x, token_y) = - // init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); - - // let mint_amount = 2u128.pow(105) - 1; - // let alice = ink_e2e::alice(); - // approve!(client, TokenRef, token_x, dex, u128::MAX, alice); - // approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let init_tick = get_max_tick(1); - // create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let current_sqrt_price = pool.sqrt_price; - // assert_eq!(pool.current_tick_index, init_tick); - // assert_eq!(pool.sqrt_price, calculate_sqrt_price(init_tick).unwrap()); - - // let position_amount = mint_amount - 1; - - // let liquidity_delta = get_liquidity_by_y( - // TokenAmount(position_amount), - // 0, - // MAX_TICK, - // pool.sqrt_price, - // false, - // ) - // .unwrap() - // .l; - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // let slippage_limit_lower = pool.sqrt_price; - // let slippage_limit_upper = pool.sqrt_price; - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // 0, - // MAX_TICK, - // liquidity_delta, - // slippage_limit_lower, - // slippage_limit_upper, - // alice - // ); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn limits_big_deposit_and_swaps(mut client: ink_e2e::Client) -> E2EResult<()> { - // let (dex, token_x, token_y) = - // init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); - - // let mint_amount = 2u128.pow(76) - 1; - // let alice = ink_e2e::alice(); - // approve!(client, TokenRef, token_x, dex, u128::MAX, alice); - // approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let init_tick = 0; - // create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // let pos_amount = mint_amount / 2; - // let lower_tick = -(fee_tier.tick_spacing as i32); - // let upper_tick = fee_tier.tick_spacing as i32; - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // let liquidity_delta = get_liquidity_by_x( - // TokenAmount(pos_amount), - // lower_tick, - // upper_tick, - // pool.sqrt_price, - // false, - // ) - // .unwrap() - // .l; - - // let y = get_delta_y( - // calculate_sqrt_price(lower_tick).unwrap(), - // pool.sqrt_price, - // liquidity_delta, - // true, - // ) - // .unwrap(); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // let slippage_limit_lower = pool.sqrt_price; - // let slippage_limit_upper = pool.sqrt_price; - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick, - // upper_tick, - // liquidity_delta, - // slippage_limit_lower, - // slippage_limit_upper, - // alice - // ); - - // let user_amount_x = balance_of!(TokenRef, client, token_x, Alice); - // let user_amount_y = balance_of!(TokenRef, client, token_y, Alice); - // assert_eq!(user_amount_x, u128::MAX - pos_amount); - // assert_eq!(user_amount_y, u128::MAX - y.get()); - - // let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); - // let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); - // assert_eq!(contract_amount_x, pos_amount); - // assert_eq!(contract_amount_y, y.get()); - - // let swap_amount = TokenAmount(mint_amount / 8); - - // for i in 1..=4 { - // let (x_to_y, sqrt_price_limit) = if i % 2 == 0 { - // (true, SqrtPrice::new(MIN_SQRT_PRICE)) - // } else { - // (false, SqrtPrice::new(MAX_SQRT_PRICE)) - // }; - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // i % 2 == 0, - // swap_amount, - // true, - // sqrt_price_limit, - // alice - // ); - // } - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn multiple_swap_x_to_y(mut client: ink_e2e::Client) -> E2EResult<()> { - // multiple_swap!(client, ContractRef, TokenRef, true); - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn limits_big_deposit_x_and_swap_y( - // mut client: ink_e2e::Client, - // ) -> E2EResult<()> { - // big_deposit_and_swap!(client, ContractRef, TokenRef, true); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn multiple_swap_y_to_x(mut client: ink_e2e::Client) -> E2EResult<()> { - // multiple_swap!(client, ContractRef, TokenRef, false); - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn limits_big_deposit_y_and_swap_x( - // mut client: ink_e2e::Client, - // ) -> E2EResult<()> { - // big_deposit_and_swap!(client, ContractRef, TokenRef, false); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn limits_big_deposit_both_tokens( - // mut client: ink_e2e::Client, - // ) -> E2EResult<()> { - // let (dex, token_x, token_y) = - // init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); - - // let mint_amount = 2u128.pow(75) - 1; - // let alice = ink_e2e::alice(); - // approve!(client, TokenRef, token_x, dex, u128::MAX, alice); - // approve!(client, TokenRef, token_y, dex, u128::MAX, alice); - - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let init_tick = 0; - // create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // let lower_tick = -(fee_tier.tick_spacing as i32); - // let upper_tick = fee_tier.tick_spacing as i32; - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let liquidity_delta = get_liquidity_by_x( - // TokenAmount(mint_amount), - // lower_tick, - // upper_tick, - // pool.sqrt_price, - // false, - // ) - // .unwrap() - // .l; - // let y = get_delta_y( - // calculate_sqrt_price(lower_tick).unwrap(), - // pool.sqrt_price, - // liquidity_delta, - // true, - // ) - // .unwrap(); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // let slippage_limit_lower = pool.sqrt_price; - // let slippage_limit_upper = pool.sqrt_price; - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick, - // upper_tick, - // liquidity_delta, - // slippage_limit_lower, - // slippage_limit_upper, - // alice - // ); - - // let user_amount_x = balance_of!(TokenRef, client, token_x, Alice); - // let user_amount_y = balance_of!(TokenRef, client, token_y, Alice); - // assert_eq!(user_amount_x, u128::MAX - mint_amount); - // assert_eq!(user_amount_y, u128::MAX - y.get()); - - // let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); - // let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); - // assert_eq!(contract_amount_x, mint_amount); - // assert_eq!(contract_amount_y, y.get()); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn max_tick_cross(mut client: ink_e2e::Client) -> E2EResult<()> { - // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - - // let mint_amount = u128::MAX; - // let alice = ink_e2e::alice(); - // approve!(client, TokenRef, token_x, dex, mint_amount, alice); - // approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - // let liquidity = Liquidity::from_integer(10000000); - - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - // for i in (-2560..20).step_by(10) { - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // let slippage_limit_lower = pool.sqrt_price; - // let slippage_limit_upper = pool.sqrt_price; - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // i, - // i + 10, - // liquidity, - // slippage_limit_lower, - // slippage_limit_upper, - // alice - // ); - // } - - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // assert_eq!(pool.liquidity, liquidity); - - // let amount = 760_000; - // let bob = ink_e2e::bob(); - // mint!(TokenRef, client, token_x, Bob, amount); - // let amount_x = balance_of!(TokenRef, client, token_x, Bob); - // assert_eq!(amount_x, amount); - // approve!(client, TokenRef, token_x, dex, amount, bob); - - // let pool_before = get_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // pool_key.fee_tier - // ) - // .unwrap(); - - // let swap_amount = TokenAmount::new(amount); - // let slippage = SqrtPrice::new(MIN_SQRT_PRICE); - // let quote_result = quote!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // slippage, - // bob - // ) - // .unwrap(); - - // let pool_after_quote = get_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // pool_key.fee_tier - // ) - // .unwrap(); - - // let crosses_after_quote = - // ((pool_after_quote.current_tick_index - pool_before.current_tick_index) / 10).abs(); - // assert_eq!(crosses_after_quote, 0); - // assert_eq!(quote_result.3.len() - 1, 146); - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // slippage, - // bob - // ); - - // let pool_after = get_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // pool_key.fee_tier - // ) - // .unwrap(); - - // let crosses = - // ((pool_after.current_tick_index - pool_before.current_tick_index) / 10).abs(); - // assert_eq!(crosses, 146); - // assert_eq!( - // pool_after.current_tick_index, - // get_tick_at_sqrt_price(quote_result.2, 10).unwrap() - // ); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn swap_exact_limit(mut client: ink_e2e::Client) -> E2EResult<()> { - // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - // let amount = 1000; - // let bob = ink_e2e::bob(); - // mint!(TokenRef, client, token_x, Bob, amount); - // let amount_x = balance_of!(TokenRef, client, token_x, Bob); - // assert_eq!(amount_x, amount); - // approve!(client, TokenRef, token_x, dex, amount, bob); - - // let swap_amount = TokenAmount::new(amount); - // swap_exact_limit!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // bob - // ); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn claim(mut client: ink_e2e::Client) -> E2EResult<()> { - // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - // init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // let alice = ink_e2e::alice(); - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let user_amount_before_claim = balance_of!(TokenRef, client, token_x, Alice); - // let dex_amount_before_claim = dex_balance!(TokenRef, client, token_x, dex); - - // claim_fee!(client, ContractRef, dex, 0, alice); - - // let user_amount_after_claim = balance_of!(TokenRef, client, token_x, Alice); - // let dex_amount_after_claim = dex_balance!(TokenRef, client, token_x, dex); - // let position = get_position!(client, ContractRef, dex, 0, alice).unwrap(); - // let expected_tokens_claimed = 5; - - // assert_eq!( - // user_amount_after_claim - expected_tokens_claimed, - // user_amount_before_claim - // ); - // assert_eq!( - // dex_amount_after_claim + expected_tokens_claimed, - // dex_amount_before_claim - // ); - // assert_eq!(position.fee_growth_inside_x, pool.fee_growth_global_x); - // assert_eq!(position.tokens_owed_x, TokenAmount(0)); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn basic_slippage_test(mut client: ink_e2e::Client) -> E2EResult<()> { - // let alice = ink_e2e::alice(); - // let (dex, token_x, token_y) = - // init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); - // let pool_key = create_slippage_pool_with_liquidity!( - // client, - // ContractRef, - // TokenRef, - // dex, - // token_x, - // token_y - // ); - // let amount = 10u128.pow(8); - // let swap_amount = TokenAmount::new(amount); - // approve!(client, TokenRef, token_x, dex, amount, alice); - - // let target_sqrt_price = SqrtPrice::new(1009940000000000000000001); - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // false, - // swap_amount, - // true, - // target_sqrt_price, - // alice - // ); - // let expected_sqrt_price = SqrtPrice::new(1009940000000000000000000); - // let pool = get_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // pool_key.fee_tier - // ) - // .unwrap(); - - // assert_eq!(expected_sqrt_price, pool.sqrt_price); - // Ok(()) - // } - - // #[ink_e2e::test] - // #[should_panic] - // async fn swap_close_to_limit_test(mut client: ink_e2e::Client) -> () { - // let alice = ink_e2e::alice(); - // let (dex, token_x, token_y) = - // init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); - // let pool_key = create_slippage_pool_with_liquidity!( - // client, - // ContractRef, - // TokenRef, - // dex, - // token_x, - // token_y - // ); - // let amount = 10u128.pow(8); - // let swap_amount = TokenAmount::new(amount); - // approve!(client, TokenRef, token_x, dex, amount, alice); - - // let target_sqrt_price = calculate_sqrt_price(-98).unwrap(); - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // false, - // swap_amount, - // true, - // target_sqrt_price, - // alice - // ); - // } - - // #[ink_e2e::test] - // async fn cross(mut client: ink_e2e::Client) -> E2EResult<()> { - // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - // init_cross_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - // init_cross_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // let alice = ink_e2e::alice(); - - // let upper_tick_index = 10; - // let middle_tick_index = -10; - // let lower_tick_index = -20; - - // let upper_tick = - // get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); - // let middle_tick = - // get_tick!(client, ContractRef, dex, middle_tick_index, pool_key, alice).unwrap(); - // let lower_tick = - // get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); - - // assert_eq!( - // upper_tick.liquidity_change, - // Liquidity::from_integer(1000000) - // ); - // assert_eq!( - // middle_tick.liquidity_change, - // Liquidity::from_integer(1000000) - // ); - // assert_eq!( - // lower_tick.liquidity_change, - // Liquidity::from_integer(1000000) - // ); - - // assert_eq!(upper_tick.fee_growth_outside_x, FeeGrowth::new(0)); - // assert_eq!( - // middle_tick.fee_growth_outside_x, - // FeeGrowth::new(30000000000000000000000) - // ); - // assert_eq!(lower_tick.fee_growth_outside_x, FeeGrowth::new(0)); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn swap(mut client: ink_e2e::Client) -> E2EResult<()> { - // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - // init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn protocol_fee(mut client: ink_e2e::Client) -> E2EResult<()> { - // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - // init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); - // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - // init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // let alice = ink_e2e::alice(); - // withdraw_protocol_fee!(client, ContractRef, dex, pool_key, alice); - - // let amount_x = balance_of!(TokenRef, client, token_x, Alice); - // let amount_y = balance_of!(TokenRef, client, token_y, Alice); - // assert_eq!(amount_x, 9999999501); - // assert_eq!(amount_y, 9999999000); - - // let amount_x = dex_balance!(TokenRef, client, token_x, dex); - // let amount_y = dex_balance!(TokenRef, client, token_y, dex); - // assert_eq!(amount_x, 1499); - // assert_eq!(amount_y, 7); - - // let pool_after_withdraw = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // assert_eq!( - // pool_after_withdraw.fee_protocol_token_x, - // TokenAmount::new(0) - // ); - // assert_eq!( - // pool_after_withdraw.fee_protocol_token_y, - // TokenAmount::new(0) - // ); - - // Ok(()) - // } - - // #[ink_e2e::test] - // #[should_panic] - // async fn protocol_fee_should_panic(mut client: ink_e2e::Client) -> () { - // let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); - // init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); - // init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); - - // let pool_key = PoolKey::new( - // token_x, - // token_y, - // FeeTier { - // fee: Percentage::from_scale(6, 3), - // tick_spacing: 10, - // }, - // ) - // .unwrap(); - // let bob = ink_e2e::bob(); - // withdraw_protocol_fee!(client, ContractRef, dex, pool_key, bob); - // } - - // #[ink_e2e::test] - // async fn constructor_test(mut client: ink_e2e::Client) -> E2EResult<()> { - // let constructor = TokenRef::new(500, None, None, 0); - // let _token: AccountId = client - // .instantiate("token", &ink_e2e::alice(), constructor, 0, None) - // .await - // .expect("Instantiate failed") - // .account_id; - - // let constructor = ContractRef::new(Percentage::new(0)); - - // let _contract: AccountId = client - // .instantiate("contract", &ink_e2e::alice(), constructor, 0, None) - // .await - // .expect("Instantiate failed") - // .account_id; - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn change_protocol_fee(mut client: ink_e2e::Client) -> E2EResult<()> { - // let contract = create_dex!(client, ContractRef, Percentage::new(0)); - - // let protocol_fee = { - // let _msg = build_message::(contract.clone()) - // .call(|contract| contract.get_protocol_fee()); - // client - // .call(&ink_e2e::alice(), _msg, 0, None) - // .await - // .expect("getting protocol fee failed") - // } - // .return_value(); - - // assert_eq!(protocol_fee, Percentage::new(0)); - - // let _result = { - // let _msg = build_message::(contract.clone()) - // .call(|contract| contract.change_protocol_fee(Percentage::new(1))); - // client - // .call(&ink_e2e::alice(), _msg, 0, None) - // .await - // .expect("changing protocol fee failed") - // }; - - // let protocol_fee = { - // let _msg = build_message::(contract.clone()) - // .call(|contract| contract.get_protocol_fee()); - // client - // .call(&ink_e2e::alice(), _msg, 0, None) - // .await - // .expect("getting protocol fee failed") - // } - // .return_value(); - - // assert_eq!(protocol_fee, Percentage::new(1)); - - // Ok(()) - // } - - // #[ink_e2e::test] - // #[should_panic] - // async fn change_protocol_fee_should_panic(mut client: ink_e2e::Client) -> () { - // let contract = create_dex!(client, ContractRef, Percentage::new(0)); - - // let result = { - // let _msg = build_message::(contract.clone()) - // .call(|contract| contract.change_protocol_fee(Percentage::new(1))); - // client - // .call(&ink_e2e::bob(), _msg, 0, None) - // .await - // .expect("changing protocol fee failed") - // }; - // } - - // #[ink_e2e::test] - // async fn create_position(mut client: ink_e2e::Client) -> E2EResult<()> { - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); - - // let alice = ink_e2e::alice(); - - // let fee_tier = FeeTier::new(Percentage::new(0), 1); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let pool = create_pool!(client, ContractRef, dex, token_x, token_y, fee_tier, 10); - - // approve!(client, TokenRef, token_x, dex, 500, alice); - // approve!(client, TokenRef, token_y, dex, 500, alice); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - // let position = create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // -10, - // 10, - // Liquidity::new(10), - // SqrtPrice::new(0), - // SqrtPrice::max_instance(), - // alice - // ); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn create_fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let fee_tier = FeeTier::new(Percentage::new(0), 10u16); - // let alice = ink_e2e::alice(); - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - // let fee_tier = get_fee_tier!(client, ContractRef, dex, Percentage::new(0), 10u16); - // assert!(fee_tier.is_some()); - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn create_standard_fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // create_standard_fee_tiers!(client, ContractRef, dex); - // let fee_tier = get_fee_tier!( - // client, - // ContractRef, - // dex, - // Percentage::from_scale(5, 2), - // 100u16 - // ); - // assert!(fee_tier.is_some()); - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn create_pool_test(mut client: ink_e2e::Client) -> E2EResult<()> { - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); - - // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); - // let init_tick = 0; - - // let alice = ink_e2e::alice(); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let result = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - // assert!(result.is_ok()); - - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let admin = ink_e2e::alice(); - // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); - // let result = create_fee_tier!(client, ContractRef, dex, fee_tier, admin); - // assert!(result.is_ok()); - // Ok(()) - // } - // #[ink_e2e::test] - // #[should_panic] - // async fn invalid_spacing_fee_tier_test(mut client: ink_e2e::Client) -> () { - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let admin = ink_e2e::alice(); - // // 0 tick spacing | should fail - // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 0); - // let result = create_fee_tier!(client, ContractRef, dex, fee_tier, admin); - // } - - // #[ink_e2e::test] - // #[should_panic] - // async fn non_admin_fee_tier_caller_test(mut client: ink_e2e::Client) -> () { - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let user = ink_e2e::bob(); - // // not-admin - // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 10); - // let result = create_fee_tier!(client, ContractRef, dex, fee_tier, user); - // } - - // #[ink_e2e::test] - // async fn position_above_current_tick_test( - // mut client: ink_e2e::Client, - // ) -> E2EResult<()> { - // let alice = ink_e2e::alice(); - // let init_tick = -23028; - - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let initial_balance = 10_000_000_000; - - // let (token_x, token_y) = - // create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - - // let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let pool = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // approve!(client, TokenRef, token_x, dex, initial_balance, alice); - // approve!(client, TokenRef, token_y, dex, initial_balance, alice); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // let lower_tick_index = -22980; - // let upper_tick_index = 0; - // let liquidity_delta = Liquidity::new(initial_balance); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // SqrtPrice::max_instance(), - // alice - // ); - - // // Load states - // let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let lower_tick = - // get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); - // let upper_tick = - // get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); - // let lower_tick_bit = - // tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - // let upper_tick_bit = - // tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - // let alice_x = balance_of!(TokenRef, client, token_x, Alice); - // let alice_y = balance_of!(TokenRef, client, token_y, Alice); - // let dex_x = dex_balance!(TokenRef, client, token_x, dex); - // let dex_y = dex_balance!(TokenRef, client, token_y, dex); - - // let zero_fee = FeeGrowth::new(0); - // let expected_x_increase = 21549; - // let expected_y_increase = 0; - - // // Check ticks - // assert!(lower_tick.index == lower_tick_index); - // assert!(upper_tick.index == upper_tick_index); - // assert_eq!(lower_tick.liquidity_gross, liquidity_delta); - // assert_eq!(upper_tick.liquidity_gross, liquidity_delta); - // assert_eq!(lower_tick.liquidity_change, liquidity_delta); - // assert_eq!(upper_tick.liquidity_change, liquidity_delta); - // assert!(lower_tick.sign); - // assert!(!upper_tick.sign); - - // // Check pool - // assert!(pool_state.liquidity == Liquidity::new(0)); - // assert!(pool_state.current_tick_index == init_tick); - - // // Check position - // assert!(position_state.pool_key == pool_key); - // assert!(position_state.liquidity == liquidity_delta); - // assert!(position_state.lower_tick_index == lower_tick_index); - // assert!(position_state.upper_tick_index == upper_tick_index); - // assert!(position_state.fee_growth_inside_x == zero_fee); - // assert!(position_state.fee_growth_inside_y == zero_fee); - - // // Check balances - // assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); - // assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); - - // assert_eq!(dex_x, expected_x_increase); - // assert_eq!(dex_y, expected_y_increase); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn multiple_positions_on_same_tick( - // mut client: ink_e2e::Client, - // ) -> E2EResult<()> { - // let alice = ink_e2e::alice(); - // let init_tick = 0; - - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let initial_balance = 100_000_000; - - // let (token_x, token_y) = - // create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - - // let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 10); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let pool = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // approve!(client, TokenRef, token_x, dex, initial_balance, alice); - // approve!(client, TokenRef, token_y, dex, initial_balance, alice); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // // Three position on same lower and upper tick - // { - // let lower_tick_index = -10; - // let upper_tick_index = 10; - - // let liquidity_delta = Liquidity::new(100); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // SqrtPrice::max_instance(), - // alice - // ); - - // let first_position = get_position!(client, ContractRef, dex, 0, alice).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // SqrtPrice::max_instance(), - // alice - // ); - - // let second_position = get_position!(client, ContractRef, dex, 1, alice).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // SqrtPrice::max_instance(), - // alice - // ); - - // let third_position = get_position!(client, ContractRef, dex, 2, alice).unwrap(); - - // assert!(first_position.lower_tick_index == second_position.lower_tick_index); - // assert!(first_position.upper_tick_index == second_position.upper_tick_index); - // assert!(first_position.lower_tick_index == third_position.lower_tick_index); - // assert!(first_position.upper_tick_index == third_position.upper_tick_index); - - // // Load states - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let lower_tick = - // get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); - // let upper_tick = - // get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); - // let lower_tick_bit = - // tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - // let upper_tick_bit = - // tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - // let expected_liquidity = Liquidity::new(liquidity_delta.get() * 3); - // let zero_fee = FeeGrowth::new(0); - - // // Check ticks - // assert!(lower_tick.index == lower_tick_index); - // assert!(upper_tick.index == upper_tick_index); - // assert_eq!(lower_tick.liquidity_gross, expected_liquidity); - // assert_eq!(upper_tick.liquidity_gross, expected_liquidity); - // assert_eq!(lower_tick.liquidity_change, expected_liquidity); - // assert_eq!(upper_tick.liquidity_change, expected_liquidity); - // assert!(lower_tick.sign); - // assert!(!upper_tick.sign); - - // // Check pool - // assert_eq!(pool_state.liquidity, expected_liquidity); - // assert!(pool_state.current_tick_index == init_tick); - - // // Check first position - // assert!(first_position.pool_key == pool_key); - // assert!(first_position.liquidity == liquidity_delta); - // assert!(first_position.lower_tick_index == lower_tick_index); - // assert!(first_position.upper_tick_index == upper_tick_index); - // assert!(first_position.fee_growth_inside_x == zero_fee); - // assert!(first_position.fee_growth_inside_y == zero_fee); - - // // Check second position - // assert!(second_position.pool_key == pool_key); - // assert!(second_position.liquidity == liquidity_delta); - // assert!(second_position.lower_tick_index == lower_tick_index); - // assert!(second_position.upper_tick_index == upper_tick_index); - // assert!(second_position.fee_growth_inside_x == zero_fee); - // assert!(second_position.fee_growth_inside_y == zero_fee); - - // // Check third position - // assert!(third_position.pool_key == pool_key); - // assert!(third_position.liquidity == liquidity_delta); - // assert!(third_position.lower_tick_index == lower_tick_index); - // assert!(third_position.upper_tick_index == upper_tick_index); - // assert!(third_position.fee_growth_inside_x == zero_fee); - // assert!(third_position.fee_growth_inside_y == zero_fee); - // } - // { - // let lower_tick_index = -10; - // let upper_tick_index = 10; - // let zero_fee = FeeGrowth::new(0); - - // let liquidity_delta = Liquidity::new(100); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // SqrtPrice::max_instance(), - // alice - // ); - - // let first_position = get_position!(client, ContractRef, dex, 3, alice).unwrap(); - - // // Check first position - // assert!(first_position.pool_key == pool_key); - // assert!(first_position.liquidity == liquidity_delta); - // assert!(first_position.lower_tick_index == lower_tick_index); - // assert!(first_position.upper_tick_index == upper_tick_index); - // assert!(first_position.fee_growth_inside_x == zero_fee); - // assert!(first_position.fee_growth_inside_y == zero_fee); - - // let lower_tick_index = -20; - // let upper_tick_index = -10; - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // SqrtPrice::max_instance(), - // alice - // ); - - // let second_position = get_position!(client, ContractRef, dex, 4, alice).unwrap(); - - // // Check second position - // assert!(second_position.pool_key == pool_key); - // assert!(second_position.liquidity == liquidity_delta); - // assert!(second_position.lower_tick_index == lower_tick_index); - // assert!(second_position.upper_tick_index == upper_tick_index); - // assert!(second_position.fee_growth_inside_x == zero_fee); - // assert!(second_position.fee_growth_inside_y == zero_fee); - - // let lower_tick_index = 10; - // let upper_tick_index = 20; - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // SqrtPrice::max_instance(), - // alice - // ); - - // let third_position = get_position!(client, ContractRef, dex, 5, alice).unwrap(); - - // // Check third position - // assert!(third_position.pool_key == pool_key); - // assert!(third_position.liquidity == liquidity_delta); - // assert!(third_position.lower_tick_index == lower_tick_index); - // assert!(third_position.upper_tick_index == upper_tick_index); - // assert!(third_position.fee_growth_inside_x == zero_fee); - // assert!(third_position.fee_growth_inside_y == zero_fee); - - // // Load states - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let tick_n20 = get_tick!(client, ContractRef, dex, -20, pool_key, alice).unwrap(); - // let tick_n10 = get_tick!(client, ContractRef, dex, -10, pool_key, alice).unwrap(); - // let tick_10 = get_tick!(client, ContractRef, dex, 10, pool_key, alice).unwrap(); - // let tick_20 = get_tick!(client, ContractRef, dex, 20, pool_key, alice).unwrap(); - // let tick_n20_bit = tickmap_bit!(client, ContractRef, dex, -20, pool_key, alice); - // let tick_n10_bit = tickmap_bit!(client, ContractRef, dex, -10, pool_key, alice); - // let tick_10_bit = tickmap_bit!(client, ContractRef, dex, 10, pool_key, alice); - // let tick_20_bit = tickmap_bit!(client, ContractRef, dex, 20, pool_key, alice); - - // let expected_active_liquidity = Liquidity::new(400); - - // // Check tick -20 - // assert_eq!(tick_n20.index, -20); - // assert_eq!(tick_n20.liquidity_gross, Liquidity::new(100)); - // assert_eq!(tick_n20.liquidity_change, Liquidity::new(100)); - // assert!(tick_n20.sign); - // assert!(tick_n20_bit); - - // // Check tick -10 - // assert_eq!(tick_n10.index, -10); - // assert_eq!(tick_n10.liquidity_gross, Liquidity::new(500)); - // assert_eq!(tick_n10.liquidity_change, Liquidity::new(300)); - // assert!(tick_n10.sign); - // assert!(tick_n10_bit); - - // // Check tick 10 - // assert_eq!(tick_10.index, 10); - // assert_eq!(tick_10.liquidity_gross, Liquidity::new(500)); - // assert_eq!(tick_10.liquidity_change, Liquidity::new(300)); - // assert!(!tick_10.sign); - // assert!(tick_20_bit); - - // // Check tick 20 - // assert_eq!(tick_20.index, 20); - // assert_eq!(tick_20.liquidity_gross, Liquidity::new(100)); - // assert_eq!(tick_20.liquidity_change, Liquidity::new(100)); - // assert!(!tick_20.sign); - // assert!(tick_20_bit); - - // // Check pool - // assert_eq!(pool_state.liquidity, expected_active_liquidity); - // assert!(pool_state.current_tick_index == init_tick); - // } - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn position_within_current_tick_test( - // mut client: ink_e2e::Client, - // ) -> E2EResult<()> { - // let MAX_TICK_TEST = 177_450; // for tickSpacing 4 - // let MIN_TICK_TEST = -MAX_TICK_TEST; - // let alice = ink_e2e::alice(); - // let init_tick = -23028; - - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let initial_balance = 100_000_000; - - // let (token_x, token_y) = - // create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - - // let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let pool = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // approve!(client, TokenRef, token_x, dex, initial_balance, alice); - // approve!(client, TokenRef, token_y, dex, initial_balance, alice); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // let lower_tick_index = MIN_TICK_TEST + 10; - // let upper_tick_index = MAX_TICK_TEST - 10; - - // let liquidity_delta = Liquidity::new(initial_balance); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // SqrtPrice::max_instance(), - // alice - // ); - - // // Load states - // let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let lower_tick = - // get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); - // let upper_tick = - // get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); - // let lower_tick_bit = - // tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - // let upper_tick_bit = - // tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - // let alice_x = balance_of!(TokenRef, client, token_x, Alice); - // let alice_y = balance_of!(TokenRef, client, token_y, Alice); - // let dex_x = dex_balance!(TokenRef, client, token_x, dex); - // let dex_y = dex_balance!(TokenRef, client, token_y, dex); - - // let zero_fee = FeeGrowth::new(0); - // let expected_x_increase = 317; - // let expected_y_increase = 32; - - // // Check ticks - // assert!(lower_tick.index == lower_tick_index); - // assert!(upper_tick.index == upper_tick_index); - // assert_eq!(lower_tick.liquidity_gross, liquidity_delta); - // assert_eq!(upper_tick.liquidity_gross, liquidity_delta); - // assert_eq!(lower_tick.liquidity_change, liquidity_delta); - // assert_eq!(upper_tick.liquidity_change, liquidity_delta); - // assert!(lower_tick.sign); - // assert!(!upper_tick.sign); - - // // Check pool - // assert!(pool_state.liquidity == liquidity_delta); - // assert!(pool_state.current_tick_index == init_tick); - - // // Check position - // assert!(position_state.pool_key == pool_key); - // assert!(position_state.liquidity == liquidity_delta); - // assert!(position_state.lower_tick_index == lower_tick_index); - // assert!(position_state.upper_tick_index == upper_tick_index); - // assert!(position_state.fee_growth_inside_x == zero_fee); - // assert!(position_state.fee_growth_inside_y == zero_fee); - - // // Check balances - // assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); - // assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); - // assert_eq!(dex_x, expected_x_increase); - // assert_eq!(dex_y, expected_y_increase); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn position_below_current_tick_test( - // mut client: ink_e2e::Client, - // ) -> E2EResult<()> { - // let alice = ink_e2e::alice(); - // let init_tick = -23028; - - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let initial_balance = 100_000_000_00; - - // let (token_x, token_y) = - // create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); - - // let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let pool = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // approve!(client, TokenRef, token_x, dex, initial_balance, alice); - // approve!(client, TokenRef, token_y, dex, initial_balance, alice); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // let lower_tick_index = -46080; - // let upper_tick_index = -23040; - - // let liquidity_delta = Liquidity::new(initial_balance); - - // let pool_state_before = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state_before.sqrt_price, - // SqrtPrice::max_instance(), - // alice - // ); - - // // Load states - // let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let lower_tick = - // get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); - // let upper_tick = - // get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); - // let lower_tick_bit = - // tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - // let upper_tick_bit = - // tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - // let alice_x = balance_of!(TokenRef, client, token_x, Alice); - // let alice_y = balance_of!(TokenRef, client, token_y, Alice); - // let dex_x = dex_balance!(TokenRef, client, token_x, dex); - // let dex_y = dex_balance!(TokenRef, client, token_y, dex); - - // let zero_fee = FeeGrowth::new(0); - // let expected_x_increase = 0; - // let expected_y_increase = 2162; - - // // Check ticks - // assert!(lower_tick.index == lower_tick_index); - // assert!(upper_tick.index == upper_tick_index); - // assert_eq!(lower_tick.liquidity_gross, liquidity_delta); - // assert_eq!(upper_tick.liquidity_gross, liquidity_delta); - // assert_eq!(lower_tick.liquidity_change, liquidity_delta); - // assert_eq!(upper_tick.liquidity_change, liquidity_delta); - // assert!(lower_tick.sign); - // assert!(!upper_tick.sign); - - // // Check pool - // assert!(pool_state.liquidity == pool_state_before.liquidity); - // assert!(pool_state.current_tick_index == init_tick); - - // // Check position - // assert!(position_state.pool_key == pool_key); - // assert!(position_state.liquidity == liquidity_delta); - // assert!(position_state.lower_tick_index == lower_tick_index); - // assert!(position_state.upper_tick_index == upper_tick_index); - // assert!(position_state.fee_growth_inside_x == zero_fee); - // assert!(position_state.fee_growth_inside_y == zero_fee); - - // // Check balances - // assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); - // assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); - - // assert_eq!(dex_x, expected_x_increase); - // assert_eq!(dex_y, expected_y_increase); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn change_fee_reciever_test(mut client: ink_e2e::Client) -> E2EResult<()> { - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); - - // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 1); - // let init_tick = 0; - - // let alice = ink_e2e::alice(); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let result = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - // assert!(result.is_ok()); - - // let admin = ink_e2e::alice(); - // let alice = address_of!(Alice); - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // change_fee_receiver!(client, ContractRef, dex, pool_key, alice, admin); - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // assert_eq!(pool.fee_receiver, alice); - - // Ok(()) - // } - - // #[ink_e2e::test] - // #[should_panic] - // async fn not_admin_change_fee_reciever_test(mut client: ink_e2e::Client) -> () { - // let dex = create_dex!(client, ContractRef, Percentage::new(0)); - // let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); - - // let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); - // let init_tick = 0; - - // let admin = ink_e2e::alice(); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, admin); - - // let result = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - // assert!(result.is_ok()); - - // let user = ink_e2e::bob(); - // let bob = address_of!(Bob); - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - // change_fee_receiver!(client, ContractRef, dex, pool_key, bob, user); - // } - - // #[ink_e2e::test] - // async fn remove_position_test(mut client: ink_e2e::Client) -> E2EResult<()> { - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - // let alice = ink_e2e::alice(); - // let bob = ink_e2e::bob(); - // let init_tick = 0; - // let remove_position_index = 0; - - // let initial_mint = 10u128.pow(10); - - // let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); - // let (token_x, token_y) = - // create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let pool = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // let lower_tick_index = -20; - // let upper_tick_index = 10; - // let liquidity_delta = Liquidity::from_integer(1_000_000); - - // approve!(client, TokenRef, token_x, dex, initial_mint, alice); - // approve!(client, TokenRef, token_y, dex, initial_mint, alice); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // pool_state.sqrt_price, - // alice - // ); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // assert_eq!(pool_state.liquidity, liquidity_delta); - - // let liquidity_delta = Liquidity::new(liquidity_delta.get() * 1_000_000); - // { - // let incorrect_lower_tick_index = lower_tick_index - 50; - // let incorrect_upper_tick_index = upper_tick_index + 50; - - // approve!(client, TokenRef, token_x, dex, liquidity_delta.get(), alice); - // approve!(client, TokenRef, token_y, dex, liquidity_delta.get(), alice); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // incorrect_lower_tick_index, - // incorrect_upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // pool_state.sqrt_price, - // alice - // ); - - // let position_state = get_position!(client, ContractRef, dex, 1, alice).unwrap(); - // // Check position - // assert!(position_state.lower_tick_index == incorrect_lower_tick_index); - // assert!(position_state.upper_tick_index == incorrect_upper_tick_index); - // } - - // let amount = 1000; - // mint!(TokenRef, client, token_x, Bob, amount); - // let amount_x = balance_of!(TokenRef, client, token_x, Bob); - // assert_eq!(amount_x, amount); - - // approve!(client, TokenRef, token_x, dex, amount, bob); - - // let pool_state_before = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // let swap_amount = TokenAmount::new(amount); - // let slippage = SqrtPrice::new(MIN_SQRT_PRICE); - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // slippage, - // bob - // ); - - // let pool_state_after = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // assert_eq!( - // pool_state_after.fee_growth_global_x, - // FeeGrowth::new(49999950000049999) - // ); - // assert_eq!(pool_state_after.fee_protocol_token_x, TokenAmount(1)); - // assert_eq!(pool_state_after.fee_protocol_token_y, TokenAmount(0)); - - // assert!(pool_state_after - // .sqrt_price - // .lt(&pool_state_before.sqrt_price)); - - // assert_eq!(pool_state_after.liquidity, pool_state_before.liquidity); - // assert_eq!(pool_state_after.current_tick_index, -10); - // assert_ne!(pool_state_after.sqrt_price, pool_state_before.sqrt_price); - - // let amount_x = balance_of!(TokenRef, client, token_x, Bob); - // let amount_y = balance_of!(TokenRef, client, token_y, Bob); - // assert_eq!(amount_x, 0); - // assert_eq!(amount_y, 993); - - // // pre load dex balances - // let dex_x_before_remove = dex_balance!(TokenRef, client, token_x, dex); - // let dex_y_before_remove = dex_balance!(TokenRef, client, token_y, dex); - - // // Remove position - // let remove_result = - // remove_position!(client, ContractRef, dex, remove_position_index, alice); - - // // Load states - // let position_state = - // get_position!(client, ContractRef, dex, remove_position_index, alice); - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let lower_tick = get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - // let upper_tick = get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - // let lower_tick_bit = - // tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); - // let upper_tick_bit = - // tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); - // let alice_x = balance_of!(TokenRef, client, token_x, Alice); - // let alice_y = balance_of!(TokenRef, client, token_y, Alice); - // let dex_x = dex_balance!(TokenRef, client, token_x, dex); - // let dex_y = dex_balance!(TokenRef, client, token_y, dex); - // let expected_withdrawn_x = 499; - // let expected_withdrawn_y = 999; - // let expected_fee_x = 0; - - // assert_eq!( - // dex_x_before_remove - dex_x, - // expected_withdrawn_x + expected_fee_x - // ); - // assert_eq!(dex_y_before_remove - dex_y, expected_withdrawn_y); - - // // Check ticks - // assert_eq!(lower_tick, Err(InvariantError::TickNotFound)); - // assert_eq!(upper_tick, Err(InvariantError::TickNotFound)); - - // // Check tickmap - // assert!(!lower_tick_bit); - // assert!(!upper_tick_bit); - - // // Check pool - // assert!(pool_state.liquidity == liquidity_delta); - // assert!(pool_state.current_tick_index == -10); - - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn position_slippage_zero_slippage_and_inside_range( - // mut client: ink_e2e::Client, - // ) -> E2EResult<()> { - // let alice = ink_e2e::alice(); - // let (dex, token_x, token_y) = - // init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); - // let pool_key = create_slippage_pool_with_liquidity!( - // client, - // ContractRef, - // TokenRef, - // dex, - // token_x, - // token_y - // ); - - // let pool = get_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // pool_key.fee_tier - // ) - // .unwrap(); - - // // zero slippage - // { - // let liquidity_delta = Liquidity::from_integer(1_000_000); - // let known_price = pool.sqrt_price; - // let tick = pool_key.fee_tier.tick_spacing as i32; - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // -tick, - // tick, - // liquidity_delta, - // known_price, - // known_price, - // alice - // ); - // } - // // inside range - // { - // let liquidity_delta = Liquidity::from_integer(1_000_000); - // let known_price = SqrtPrice::new(1010000000000000000000000); - // let limit_lower = SqrtPrice::new(994734637981406576896367); - // let limit_upper = SqrtPrice::new(1025038048074314166333500); - - // let tick = pool_key.fee_tier.tick_spacing as i32; - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // -tick, - // tick, - // liquidity_delta, - // limit_lower, - // limit_upper, - // alice - // ); - // } - - // Ok(()) - // } - // #[ink_e2e::test] - // #[should_panic] - // async fn position_slippage_below_range(mut client: ink_e2e::Client) -> () { - // let alice = ink_e2e::alice(); - // let (dex, token_x, token_y) = - // init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); - // let pool_key = create_slippage_pool_with_liquidity!( - // client, - // ContractRef, - // TokenRef, - // dex, - // token_x, - // token_y - // ); - - // let pool = get_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // pool_key.fee_tier - // ) - // .unwrap(); - - // let liquidity_delta = Liquidity::from_integer(1_000_000); - // let known_price = SqrtPrice::new(1030000000000000000000000); - // let limit_lower = SqrtPrice::new(1014432353584998786339859); - // let limit_upper = SqrtPrice::new(1045335831204498605270797); - // let tick = pool_key.fee_tier.tick_spacing as i32; - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // -tick, - // tick, - // liquidity_delta, - // limit_lower, - // limit_upper, - // alice - // ); - // } - // #[ink_e2e::test] - // #[should_panic] - // async fn position_slippage_above_range(mut client: ink_e2e::Client) -> () { - // let alice = ink_e2e::alice(); - // let (dex, token_x, token_y) = - // init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); - // let pool_key = create_slippage_pool_with_liquidity!( - // client, - // ContractRef, - // TokenRef, - // dex, - // token_x, - // token_y - // ); - - // let pool = get_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // pool_key.fee_tier - // ) - // .unwrap(); - - // let liquidity_delta = Liquidity::from_integer(1_000_000); - // let known_price = pool.sqrt_price; - // let limit_lower = SqrtPrice::new(955339206774222158009382); - // let limit_upper = SqrtPrice::new(984442481813945288458906); - // let tick = pool_key.fee_tier.tick_spacing as i32; - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // -tick, - // tick, - // liquidity_delta, - // limit_lower, - // limit_upper, - // alice - // ); - // } - - // #[ink_e2e::test] - // #[should_panic] - // async fn no_liquidity_swap(mut client: ink_e2e::Client) -> () { - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - // let alice = ink_e2e::alice(); - // let bob = ink_e2e::bob(); - // let init_tick = 0; - - // let initial_mint = 10u128.pow(10); - - // let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); - // let (token_x, token_y) = - // create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let pool = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // let lower_tick_index = -10; - // let upper_tick_index = 10; - - // let mint_amount = 10u128.pow(10); - // mint!(TokenRef, client, token_x, Alice, mint_amount); - // mint!(TokenRef, client, token_y, Alice, mint_amount); - - // approve!(client, TokenRef, token_x, dex, mint_amount, alice); - // approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - // let liquidity_delta = Liquidity::from_integer(20_006_000); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // pool_state.sqrt_price, - // alice - // ); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // assert_eq!(pool_state.liquidity, liquidity_delta); - - // let mint_amount = 10067; - // mint!(TokenRef, client, token_x, Bob, mint_amount); - - // approve!(client, TokenRef, token_x, dex, mint_amount, bob); - - // let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); - // let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); - - // let swap_amount = TokenAmount::new(10067); - // let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - // let quoted_target_sqrt_price = quote!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // target_sqrt_price, - // alice - // ) - // .unwrap() - // .2; - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // quoted_target_sqrt_price, - // bob - // ); - - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let expected_price = calculate_sqrt_price(-10).unwrap(); - // let expected_y_amount_out = 9999; - - // assert_eq!(pool.liquidity, liquidity_delta); - // assert_eq!(pool.current_tick_index, lower_tick_index); - // assert_eq!(pool.sqrt_price, expected_price); - - // let bob_x = balance_of!(TokenRef, client, token_x, Bob); - // let bob_y = balance_of!(TokenRef, client, token_y, Bob); - // let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); - // let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); - - // let delta_dex_x = dex_x_after - dex_x_before; - // let delta_dex_y = dex_y_before - dex_y_after; - - // assert_eq!(bob_x, 0); - // assert_eq!(bob_y, expected_y_amount_out); - // assert_eq!(delta_dex_x, swap_amount.get()); - // assert_eq!(delta_dex_y, expected_y_amount_out); - // assert_eq!( - // pool.fee_growth_global_x, - // FeeGrowth::new(29991002699190242927121) - // ); - // assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); - // assert_eq!(pool.fee_protocol_token_x, TokenAmount::new(1)); - // assert_eq!(pool.fee_protocol_token_y, TokenAmount::new(0)); - - // let swap_amount = TokenAmount(1); - // let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - // let quoted_target_sqrt_price = quote!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // target_sqrt_price, - // alice - // ) - // .unwrap() - // .2; - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // quoted_target_sqrt_price, - // bob - // ); - // } - - // #[ink_e2e::test] - // async fn liquidity_gap_test(mut client: ink_e2e::Client) -> E2EResult<()> { - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - // let alice = ink_e2e::alice(); - // let bob = ink_e2e::bob(); - // let init_tick = 0; - - // let initial_mint = 10u128.pow(10); - - // let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); - // let (token_x, token_y) = - // create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let pool = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // let lower_tick_index = -10; - // let upper_tick_index = 10; - - // let mint_amount = 10u128.pow(10); - // mint!(TokenRef, client, token_x, Alice, mint_amount); - // mint!(TokenRef, client, token_y, Alice, mint_amount); - - // approve!(client, TokenRef, token_x, dex, mint_amount, alice); - // approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - // let liquidity_delta = Liquidity::from_integer(20_006_000); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // pool_state.sqrt_price, - // alice - // ); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // assert_eq!(pool_state.liquidity, liquidity_delta); - - // let mint_amount = 10067; - // mint!(TokenRef, client, token_x, Bob, mint_amount); - - // approve!(client, TokenRef, token_x, dex, mint_amount, bob); - - // let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); - // let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); - - // let swap_amount = TokenAmount::new(10067); - // let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - // let quoted_target_sqrt_price = quote!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // target_sqrt_price, - // alice - // ) - // .unwrap() - // .2; - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // quoted_target_sqrt_price, - // bob - // ); - - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let expected_price = calculate_sqrt_price(-10).unwrap(); - // let expected_y_amount_out = 9999; - - // assert_eq!(pool.liquidity, liquidity_delta); - // assert_eq!(pool.current_tick_index, lower_tick_index); - // assert_eq!(pool.sqrt_price, expected_price); - - // let bob_x = balance_of!(TokenRef, client, token_x, Bob); - // let bob_y = balance_of!(TokenRef, client, token_y, Bob); - // let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); - // let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); - - // let delta_dex_x = dex_x_after - dex_x_before; - // let delta_dex_y = dex_y_before - dex_y_after; - - // assert_eq!(bob_x, 0); - // assert_eq!(bob_y, expected_y_amount_out); - // assert_eq!(delta_dex_x, swap_amount.get()); - // assert_eq!(delta_dex_y, expected_y_amount_out); - // assert_eq!( - // pool.fee_growth_global_x, - // FeeGrowth::new(29991002699190242927121) - // ); - // assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); - // assert_eq!(pool.fee_protocol_token_x, TokenAmount::new(1)); - // assert_eq!(pool.fee_protocol_token_y, TokenAmount::new(0)); - - // // Should skip gap and then swap - // let lower_tick_after_swap = -90; - // let upper_tick_after_swap = -50; - // let liquidity_delta = Liquidity::from_integer(20008000); - - // approve!(client, TokenRef, token_x, dex, liquidity_delta.get(), alice); - // approve!(client, TokenRef, token_y, dex, liquidity_delta.get(), alice); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_after_swap, - // upper_tick_after_swap, - // liquidity_delta, - // pool_state.sqrt_price, - // pool_state.sqrt_price, - // alice - // ); - - // let swap_amount = TokenAmount::new(5000); - // mint!(TokenRef, client, token_x, Bob, swap_amount.get()); - - // approve!(client, TokenRef, token_x, dex, swap_amount.get(), bob); - - // let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); - // let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); - - // let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - // let quoted_target_sqrt_price = quote!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // target_sqrt_price, - // alice - // ) - // .unwrap() - // .2; - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // swap_amount, - // true, - // quoted_target_sqrt_price, - // bob - // ); - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // let bob_x = balance_of!(TokenRef, client, token_x, Bob); - // let bob_y = balance_of!(TokenRef, client, token_y, Bob); - // let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); - // let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); - - // let delta_dex_x = dex_x_after - dex_x_before; - // let delta_dex_y = dex_y_before - dex_y_after; - // Ok(()) - // } - - // #[ink_e2e::test] - // async fn cross_both_side_test(mut client: ink_e2e::Client) -> E2EResult<()> { - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - // let alice = ink_e2e::alice(); - // let bob = ink_e2e::bob(); - // let init_tick = 0; - - // let initial_mint = 10u128.pow(10); - - // let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); - // let (token_x, token_y) = - // create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let pool = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // let lower_tick_index = -10; - // let upper_tick_index = 10; - - // let mint_amount = 10u128.pow(5); - // mint!(TokenRef, client, token_x, Alice, mint_amount); - // mint!(TokenRef, client, token_y, Alice, mint_amount); - - // approve!(client, TokenRef, token_x, dex, mint_amount, alice); - // approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - // let liquidity_delta = Liquidity::new(20006000000000); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // pool_state.sqrt_price, - // alice - // ); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // -20, - // lower_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // pool_state.sqrt_price, - // alice - // ); - - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // assert_eq!(pool.liquidity, liquidity_delta); - - // let limit_without_cross_tick_amount = TokenAmount(10_068); - // let not_cross_amount = TokenAmount(1); - // let min_amount_to_cross_from_tick_price = TokenAmount(3); - // let crossing_amount_by_amount_out = TokenAmount(20136101434); - - // let mint_amount = limit_without_cross_tick_amount.get() - // + not_cross_amount.get() - // + min_amount_to_cross_from_tick_price.get() - // + crossing_amount_by_amount_out.get(); - - // mint!(TokenRef, client, token_x, Alice, mint_amount); - // mint!(TokenRef, client, token_y, Alice, mint_amount); - - // approve!(client, TokenRef, token_x, dex, mint_amount, alice); - // approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - // let pool_before = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // let limit_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // limit_without_cross_tick_amount, - // true, - // limit_sqrt_price, - // alice - // ); - - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let expected_tick = -10; - // let expected_price = calculate_sqrt_price(expected_tick).unwrap(); - - // assert_eq!(pool.current_tick_index, expected_tick); - // assert_eq!(pool.liquidity, pool_before.liquidity); - // assert_eq!(pool.sqrt_price, expected_price); - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // min_amount_to_cross_from_tick_price, - // true, - // limit_sqrt_price, - // alice - // ); - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // false, - // min_amount_to_cross_from_tick_price, - // true, - // SqrtPrice::new(MAX_SQRT_PRICE), - // alice - // ); - - // let massive_x = 10u128.pow(19); - // let massive_y = 10u128.pow(19); - - // mint!(TokenRef, client, token_x, Alice, massive_x); - // mint!(TokenRef, client, token_y, Alice, massive_y); - // approve!(client, TokenRef, token_x, dex, massive_x, alice); - // approve!(client, TokenRef, token_y, dex, massive_y, alice); - - // let massive_liquidity_delta = Liquidity::new(19996000399699881985603000000); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // -20, - // 0, - // massive_liquidity_delta, - // SqrtPrice::new(MIN_SQRT_PRICE), - // SqrtPrice::new(MAX_SQRT_PRICE), - // alice - // ); - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // TokenAmount(1), - // false, - // limit_sqrt_price, - // alice - // ); - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // false, - // TokenAmount(2), - // true, - // SqrtPrice::new(MAX_SQRT_PRICE), - // alice - // ); - - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // assert_eq!(pool.current_tick_index, -20); - // assert_eq!( - // pool.fee_growth_global_x, - // FeeGrowth::new(29991002699190242927121) - // ); - // assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); - // assert_eq!(pool.fee_protocol_token_x, TokenAmount(4)); - // assert_eq!(pool.fee_protocol_token_y, TokenAmount(2)); - // assert_eq!( - // pool.liquidity, - // Liquidity::new(19996000399699901991603000000) - // ); - // assert_eq!(pool.sqrt_price, SqrtPrice::new(999500149964999999999999)); - - // let final_last_tick = - // get_tick!(client, ContractRef, dex, -20, pool_key, alice).unwrap(); - // assert_eq!(final_last_tick.fee_growth_outside_x, FeeGrowth::new(0)); - // assert_eq!(final_last_tick.fee_growth_outside_y, FeeGrowth::new(0)); - // assert_eq!( - // final_last_tick.liquidity_change, - // Liquidity::new(19996000399699901991603000000) - // ); - - // let final_lower_tick = - // get_tick!(client, ContractRef, dex, -10, pool_key, alice).unwrap(); - // assert_eq!( - // final_lower_tick.fee_growth_outside_x, - // FeeGrowth::new(29991002699190242927121) - // ); - // assert_eq!(final_lower_tick.fee_growth_outside_y, FeeGrowth::new(0)); - // assert_eq!(final_lower_tick.liquidity_change, Liquidity::new(0)); - - // let final_upper_tick = - // get_tick!(client, ContractRef, dex, 10, pool_key, alice).unwrap(); - // assert_eq!(final_upper_tick.fee_growth_outside_x, FeeGrowth::new(0)); - // assert_eq!(final_upper_tick.fee_growth_outside_y, FeeGrowth::new(0)); - // assert_eq!( - // final_upper_tick.liquidity_change, - // Liquidity::new(20006000000000) - // ); - - // Ok(()) - // } - - // #[ink_e2e::test] - // #[should_panic] - // async fn cross_both_side_not_cross_case_test(mut client: ink_e2e::Client) -> () { - // let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); - // let alice = ink_e2e::alice(); - // let bob = ink_e2e::bob(); - // let init_tick = 0; - - // let initial_mint = 10u128.pow(10); - - // let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); - // let (token_x, token_y) = - // create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); - - // let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); - - // create_fee_tier!(client, ContractRef, dex, fee_tier, alice); - - // let pool = create_pool!( - // client, - // ContractRef, - // dex, - // token_x, - // token_y, - // fee_tier, - // init_tick - // ); - - // let lower_tick_index = -10; - // let upper_tick_index = 10; - - // let mint_amount = 10u128.pow(5); - // mint!(TokenRef, client, token_x, Alice, mint_amount); - // mint!(TokenRef, client, token_y, Alice, mint_amount); - - // approve!(client, TokenRef, token_x, dex, mint_amount, alice); - // approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - // let liquidity_delta = Liquidity::new(20006000000000); - - // let pool_state = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // lower_tick_index, - // upper_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // pool_state.sqrt_price, - // alice - // ); - - // create_position!( - // client, - // ContractRef, - // dex, - // pool_key, - // -20, - // lower_tick_index, - // liquidity_delta, - // pool_state.sqrt_price, - // pool_state.sqrt_price, - // alice - // ); - - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // assert_eq!(pool.liquidity, liquidity_delta); - - // let limit_without_cross_tick_amount = TokenAmount(10_068); - // let not_cross_amount = TokenAmount(1); - // let min_amount_to_cross_from_tick_price = TokenAmount(3); - // let crossing_amount_by_amount_out = TokenAmount(20136101434); - - // let mint_amount = limit_without_cross_tick_amount.get() - // + not_cross_amount.get() - // + min_amount_to_cross_from_tick_price.get() - // + crossing_amount_by_amount_out.get(); - - // mint!(TokenRef, client, token_x, Alice, mint_amount); - // mint!(TokenRef, client, token_y, Alice, mint_amount); - - // approve!(client, TokenRef, token_x, dex, mint_amount, alice); - // approve!(client, TokenRef, token_y, dex, mint_amount, alice); - - // let pool_before = - // get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - - // let limit_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // limit_without_cross_tick_amount, - // true, - // limit_sqrt_price, - // alice - // ); - - // let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); - // let expected_tick = -10; - // let expected_price = calculate_sqrt_price(expected_tick).unwrap(); - - // assert_eq!(pool.current_tick_index, expected_tick); - // assert_eq!(pool.liquidity, pool_before.liquidity); - // assert_eq!(pool.sqrt_price, expected_price); - - // let slippage = SqrtPrice::new(MIN_SQRT_PRICE); - // let target_sqrt_price = quote!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // not_cross_amount, - // true, - // slippage, - // alice - // ) - // .unwrap() - // .2; - - // swap!( - // client, - // ContractRef, - // dex, - // pool_key, - // true, - // not_cross_amount, - // true, - // target_sqrt_price, - // alice - // ); - // } + #[ink_e2e::test] + async fn swap_route(mut client: ink_e2e::Client) -> E2EResult<()> { + let (dex, token_x, token_y, token_z) = + init_dex_and_3_tokens!(client, ContractRef, TokenRef); + + let alice = ink_e2e::alice(); + approve!(client, TokenRef, token_x, dex, u64::MAX as u128, alice); + approve!(client, TokenRef, token_y, dex, u64::MAX as u128, alice); + approve!(client, TokenRef, token_z, dex, u64::MAX as u128, alice); + + let amount = 1000; + let bob = ink_e2e::bob(); + mint_with_aprove_for_bob!(client, TokenRef, token_x, dex, amount); + approve!(client, TokenRef, token_y, dex, u64::MAX as u128, bob); + + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let init_tick = 0; + create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + let init_tick = 0; + create_pool!( + client, + ContractRef, + dex, + token_y, + token_z, + fee_tier, + init_tick + ); + + let pool_key_1 = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let pool_key_2 = PoolKey::new(token_y, token_z, fee_tier).unwrap(); + + let liquidity_delta = Liquidity::new(2u128.pow(63) - 1); + + let pool_1 = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let slippage_limit_lower = pool_1.sqrt_price; + let slippage_limit_upper = pool_1.sqrt_price; + create_position!( + client, + ContractRef, + dex, + pool_key_1, + -1, + 1, + liquidity_delta, + slippage_limit_lower, + slippage_limit_upper, + alice + ); + + let pool_2 = get_pool!(client, ContractRef, dex, token_y, token_z, fee_tier).unwrap(); + let slippage_limit_lower = pool_2.sqrt_price; + let slippage_limit_upper = pool_2.sqrt_price; + create_position!( + client, + ContractRef, + dex, + pool_key_2, + -1, + 1, + liquidity_delta, + slippage_limit_lower, + slippage_limit_upper, + alice + ); + + let amount_in = TokenAmount(1000); + let expected_amount_out = TokenAmount(1000); + let slippage = Percentage::new(0); + let swaps = vec![ + Hop { + pool_key: pool_key_1, + x_to_y: true, + }, + Hop { + pool_key: pool_key_2, + x_to_y: true, + }, + ]; + + let expected_token_amount = + quote_route!(client, ContractRef, dex, amount_in, swaps.clone(), bob).unwrap(); + + swap_route!( + client, + ContractRef, + dex, + amount_in, + expected_token_amount, + slippage, + swaps.clone(), + bob + ); + + let bob_amount_x = balance_of!(TokenRef, client, token_x, Bob); + let bob_amount_y = balance_of!(TokenRef, client, token_y, Bob); + let bob_amount_z = balance_of!(TokenRef, client, token_z, Bob); + + assert_eq!(bob_amount_x, 0); + assert_eq!(bob_amount_y, 0); + assert_eq!(bob_amount_z, 986); + + let pool_1_after = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!(pool_1_after.fee_protocol_token_x, TokenAmount(1)); + assert_eq!(pool_1_after.fee_protocol_token_y, TokenAmount(0)); + + let pool_2_after = + get_pool!(client, ContractRef, dex, token_y, token_z, fee_tier).unwrap(); + assert_eq!(pool_2_after.fee_protocol_token_x, TokenAmount(1)); + assert_eq!(pool_2_after.fee_protocol_token_y, TokenAmount(0)); + + let alice_amount_x_before = balance_of!(TokenRef, client, token_x, Alice); + let alice_amount_y_before = balance_of!(TokenRef, client, token_y, Alice); + let alice_amount_z_before = balance_of!(TokenRef, client, token_z, Alice); + + claim_fee!(client, ContractRef, dex, 0, alice); + claim_fee!(client, ContractRef, dex, 1, alice); + + let alice_amount_x_after = balance_of!(TokenRef, client, token_x, Alice); + let alice_amount_y_after = balance_of!(TokenRef, client, token_y, Alice); + let alice_amount_z_after = balance_of!(TokenRef, client, token_z, Alice); + + assert_eq!(alice_amount_x_after - alice_amount_x_before, 4); + assert_eq!(alice_amount_y_after - alice_amount_y_before, 4); + assert_eq!(alice_amount_z_after - alice_amount_z_before, 0); + + Ok(()) + } + + #[ink_e2e::test] + async fn limits_full_range_with_max_liquidity(mut client: ink_e2e::Client) -> () { + let (dex, token_x, token_y) = + init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); + + let mint_amount = u128::MAX; + let alice = ink_e2e::alice(); + approve!(client, TokenRef, token_x, dex, u128::MAX, alice); + approve!(client, TokenRef, token_y, dex, u128::MAX, alice); + + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let init_tick = get_max_tick(1); + create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let current_sqrt_price = pool.sqrt_price; + assert_eq!(pool.current_tick_index, init_tick); + assert_eq!(pool.sqrt_price, calculate_sqrt_price(init_tick).unwrap()); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let liquidity_delta = Liquidity::new(2u128.pow(109) - 1); + let slippage_limit_lower = pool.sqrt_price; + let slippage_limit_upper = pool.sqrt_price; + create_position!( + client, + ContractRef, + dex, + pool_key, + -MAX_TICK, + MAX_TICK, + liquidity_delta, + slippage_limit_lower, + slippage_limit_upper, + alice + ); + + let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); + let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); + + let expected_x = 0; + let expected_y = 42534896005851865508212194815854; + assert_eq!(contract_amount_x, expected_x); + assert_eq!(contract_amount_y, expected_y); + } + + #[ink_e2e::test] + async fn deposit_limits_at_upper_limit(mut client: ink_e2e::Client) -> E2EResult<()> { + let (dex, token_x, token_y) = + init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); + + let mint_amount = 2u128.pow(105) - 1; + let alice = ink_e2e::alice(); + approve!(client, TokenRef, token_x, dex, u128::MAX, alice); + approve!(client, TokenRef, token_y, dex, u128::MAX, alice); + + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let init_tick = get_max_tick(1); + create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let current_sqrt_price = pool.sqrt_price; + assert_eq!(pool.current_tick_index, init_tick); + assert_eq!(pool.sqrt_price, calculate_sqrt_price(init_tick).unwrap()); + + let position_amount = mint_amount - 1; + + let liquidity_delta = get_liquidity_by_y( + TokenAmount(position_amount), + 0, + MAX_TICK, + pool.sqrt_price, + false, + ) + .unwrap() + .l; + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let slippage_limit_lower = pool.sqrt_price; + let slippage_limit_upper = pool.sqrt_price; + create_position!( + client, + ContractRef, + dex, + pool_key, + 0, + MAX_TICK, + liquidity_delta, + slippage_limit_lower, + slippage_limit_upper, + alice + ); + + Ok(()) + } + + #[ink_e2e::test] + async fn limits_big_deposit_and_swaps(mut client: ink_e2e::Client) -> E2EResult<()> { + let (dex, token_x, token_y) = + init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); + + let mint_amount = 2u128.pow(76) - 1; + let alice = ink_e2e::alice(); + approve!(client, TokenRef, token_x, dex, u128::MAX, alice); + approve!(client, TokenRef, token_y, dex, u128::MAX, alice); + + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let init_tick = 0; + create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + let pos_amount = mint_amount / 2; + let lower_tick = -(fee_tier.tick_spacing as i32); + let upper_tick = fee_tier.tick_spacing as i32; + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + let liquidity_delta = get_liquidity_by_x( + TokenAmount(pos_amount), + lower_tick, + upper_tick, + pool.sqrt_price, + false, + ) + .unwrap() + .l; + + let y = get_delta_y( + calculate_sqrt_price(lower_tick).unwrap(), + pool.sqrt_price, + liquidity_delta, + true, + ) + .unwrap(); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let slippage_limit_lower = pool.sqrt_price; + let slippage_limit_upper = pool.sqrt_price; + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick, + upper_tick, + liquidity_delta, + slippage_limit_lower, + slippage_limit_upper, + alice + ); + + let user_amount_x = balance_of!(TokenRef, client, token_x, Alice); + let user_amount_y = balance_of!(TokenRef, client, token_y, Alice); + assert_eq!(user_amount_x, u128::MAX - pos_amount); + assert_eq!(user_amount_y, u128::MAX - y.get()); + + let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); + let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); + assert_eq!(contract_amount_x, pos_amount); + assert_eq!(contract_amount_y, y.get()); + + let swap_amount = TokenAmount(mint_amount / 8); + + for i in 1..=4 { + let (x_to_y, sqrt_price_limit) = if i % 2 == 0 { + (true, SqrtPrice::new(MIN_SQRT_PRICE)) + } else { + (false, SqrtPrice::new(MAX_SQRT_PRICE)) + }; + + swap!( + client, + ContractRef, + dex, + pool_key, + i % 2 == 0, + swap_amount, + true, + sqrt_price_limit, + alice + ); + } + + Ok(()) + } + + #[ink_e2e::test] + async fn multiple_swap_x_to_y(mut client: ink_e2e::Client) -> E2EResult<()> { + multiple_swap!(client, ContractRef, TokenRef, true); + Ok(()) + } + + #[ink_e2e::test] + async fn limits_big_deposit_x_and_swap_y( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + big_deposit_and_swap!(client, ContractRef, TokenRef, true); + + Ok(()) + } + + #[ink_e2e::test] + async fn multiple_swap_y_to_x(mut client: ink_e2e::Client) -> E2EResult<()> { + multiple_swap!(client, ContractRef, TokenRef, false); + Ok(()) + } + + #[ink_e2e::test] + async fn limits_big_deposit_y_and_swap_x( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + big_deposit_and_swap!(client, ContractRef, TokenRef, false); + + Ok(()) + } + + #[ink_e2e::test] + async fn limits_big_deposit_both_tokens( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let (dex, token_x, token_y) = + init_dex_and_tokens_max_mint_amount!(client, ContractRef, TokenRef); + + let mint_amount = 2u128.pow(75) - 1; + let alice = ink_e2e::alice(); + approve!(client, TokenRef, token_x, dex, u128::MAX, alice); + approve!(client, TokenRef, token_y, dex, u128::MAX, alice); + + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 1); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let init_tick = 0; + create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + let lower_tick = -(fee_tier.tick_spacing as i32); + let upper_tick = fee_tier.tick_spacing as i32; + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let liquidity_delta = get_liquidity_by_x( + TokenAmount(mint_amount), + lower_tick, + upper_tick, + pool.sqrt_price, + false, + ) + .unwrap() + .l; + let y = get_delta_y( + calculate_sqrt_price(lower_tick).unwrap(), + pool.sqrt_price, + liquidity_delta, + true, + ) + .unwrap(); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let slippage_limit_lower = pool.sqrt_price; + let slippage_limit_upper = pool.sqrt_price; + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick, + upper_tick, + liquidity_delta, + slippage_limit_lower, + slippage_limit_upper, + alice + ); + + let user_amount_x = balance_of!(TokenRef, client, token_x, Alice); + let user_amount_y = balance_of!(TokenRef, client, token_y, Alice); + assert_eq!(user_amount_x, u128::MAX - mint_amount); + assert_eq!(user_amount_y, u128::MAX - y.get()); + + let contract_amount_x = dex_balance!(TokenRef, client, token_x, dex); + let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); + assert_eq!(contract_amount_x, mint_amount); + assert_eq!(contract_amount_y, y.get()); + + Ok(()) + } + + #[ink_e2e::test] + async fn max_tick_cross(mut client: ink_e2e::Client) -> E2EResult<()> { + let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + + let mint_amount = u128::MAX; + let alice = ink_e2e::alice(); + approve!(client, TokenRef, token_x, dex, mint_amount, alice); + approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + let liquidity = Liquidity::from_integer(10000000); + + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + for i in (-2560..20).step_by(10) { + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + let slippage_limit_lower = pool.sqrt_price; + let slippage_limit_upper = pool.sqrt_price; + + create_position!( + client, + ContractRef, + dex, + pool_key, + i, + i + 10, + liquidity, + slippage_limit_lower, + slippage_limit_upper, + alice + ); + } + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!(pool.liquidity, liquidity); + + let amount = 760_000; + let bob = ink_e2e::bob(); + mint!(TokenRef, client, token_x, Bob, amount); + let amount_x = balance_of!(TokenRef, client, token_x, Bob); + assert_eq!(amount_x, amount); + approve!(client, TokenRef, token_x, dex, amount, bob); + + let pool_before = get_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + pool_key.fee_tier + ) + .unwrap(); + + let swap_amount = TokenAmount::new(amount); + let slippage = SqrtPrice::new(MIN_SQRT_PRICE); + let quote_result = quote!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + slippage, + bob + ) + .unwrap(); + + let pool_after_quote = get_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + pool_key.fee_tier + ) + .unwrap(); + + let crosses_after_quote = + ((pool_after_quote.current_tick_index - pool_before.current_tick_index) / 10).abs(); + assert_eq!(crosses_after_quote, 0); + assert_eq!(quote_result.3.len() - 1, 146); + + swap!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + slippage, + bob + ); + + let pool_after = get_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + pool_key.fee_tier + ) + .unwrap(); + + let crosses = + ((pool_after.current_tick_index - pool_before.current_tick_index) / 10).abs(); + assert_eq!(crosses, 146); + assert_eq!( + pool_after.current_tick_index, + get_tick_at_sqrt_price(quote_result.2, 10).unwrap() + ); + + Ok(()) + } + + #[ink_e2e::test] + async fn swap_exact_limit(mut client: ink_e2e::Client) -> E2EResult<()> { + let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + let amount = 1000; + let bob = ink_e2e::bob(); + mint!(TokenRef, client, token_x, Bob, amount); + let amount_x = balance_of!(TokenRef, client, token_x, Bob); + assert_eq!(amount_x, amount); + approve!(client, TokenRef, token_x, dex, amount, bob); + + let swap_amount = TokenAmount::new(amount); + swap_exact_limit!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + bob + ); + + Ok(()) + } + + #[ink_e2e::test] + async fn claim(mut client: ink_e2e::Client) -> E2EResult<()> { + let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); + + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let alice = ink_e2e::alice(); + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let user_amount_before_claim = balance_of!(TokenRef, client, token_x, Alice); + let dex_amount_before_claim = dex_balance!(TokenRef, client, token_x, dex); + + claim_fee!(client, ContractRef, dex, 0, alice); + + let user_amount_after_claim = balance_of!(TokenRef, client, token_x, Alice); + let dex_amount_after_claim = dex_balance!(TokenRef, client, token_x, dex); + let position = get_position!(client, ContractRef, dex, 0, alice).unwrap(); + let expected_tokens_claimed = 5; + + assert_eq!( + user_amount_after_claim - expected_tokens_claimed, + user_amount_before_claim + ); + assert_eq!( + dex_amount_after_claim + expected_tokens_claimed, + dex_amount_before_claim + ); + assert_eq!(position.fee_growth_inside_x, pool.fee_growth_global_x); + assert_eq!(position.tokens_owed_x, TokenAmount(0)); + + Ok(()) + } + + #[ink_e2e::test] + async fn basic_slippage_test(mut client: ink_e2e::Client) -> E2EResult<()> { + let alice = ink_e2e::alice(); + let (dex, token_x, token_y) = + init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); + let pool_key = create_slippage_pool_with_liquidity!( + client, + ContractRef, + TokenRef, + dex, + token_x, + token_y + ); + let amount = 10u128.pow(8); + let swap_amount = TokenAmount::new(amount); + approve!(client, TokenRef, token_x, dex, amount, alice); + + let target_sqrt_price = SqrtPrice::new(1009940000000000000000001); + swap!( + client, + ContractRef, + dex, + pool_key, + false, + swap_amount, + true, + target_sqrt_price, + alice + ); + let expected_sqrt_price = SqrtPrice::new(1009940000000000000000000); + let pool = get_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + pool_key.fee_tier + ) + .unwrap(); + + assert_eq!(expected_sqrt_price, pool.sqrt_price); + Ok(()) + } + + #[ink_e2e::test] + #[should_panic] + async fn swap_close_to_limit_test(mut client: ink_e2e::Client) -> () { + let alice = ink_e2e::alice(); + let (dex, token_x, token_y) = + init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); + let pool_key = create_slippage_pool_with_liquidity!( + client, + ContractRef, + TokenRef, + dex, + token_x, + token_y + ); + let amount = 10u128.pow(8); + let swap_amount = TokenAmount::new(amount); + approve!(client, TokenRef, token_x, dex, amount, alice); + + let target_sqrt_price = calculate_sqrt_price(-98).unwrap(); + swap!( + client, + ContractRef, + dex, + pool_key, + false, + swap_amount, + true, + target_sqrt_price, + alice + ); + } + + #[ink_e2e::test] + async fn cross(mut client: ink_e2e::Client) -> E2EResult<()> { + let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + init_cross_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + init_cross_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); + + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let alice = ink_e2e::alice(); + + let upper_tick_index = 10; + let middle_tick_index = -10; + let lower_tick_index = -20; + + let upper_tick = + get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + let middle_tick = + get_tick!(client, ContractRef, dex, middle_tick_index, pool_key, alice).unwrap(); + let lower_tick = + get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + + assert_eq!( + upper_tick.liquidity_change, + Liquidity::from_integer(1000000) + ); + assert_eq!( + middle_tick.liquidity_change, + Liquidity::from_integer(1000000) + ); + assert_eq!( + lower_tick.liquidity_change, + Liquidity::from_integer(1000000) + ); + + assert_eq!(upper_tick.fee_growth_outside_x, FeeGrowth::new(0)); + assert_eq!( + middle_tick.fee_growth_outside_x, + FeeGrowth::new(30000000000000000000000) + ); + assert_eq!(lower_tick.fee_growth_outside_x, FeeGrowth::new(0)); + + Ok(()) + } + + #[ink_e2e::test] + async fn swap(mut client: ink_e2e::Client) -> E2EResult<()> { + let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); + Ok(()) + } + + #[ink_e2e::test] + async fn protocol_fee(mut client: ink_e2e::Client) -> E2EResult<()> { + let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + init_basic_pool!(client, ContractRef, TokenRef, dex, token_x, token_y); + init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); + + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let alice = ink_e2e::alice(); + withdraw_protocol_fee!(client, ContractRef, dex, pool_key, alice); + + let amount_x = balance_of!(TokenRef, client, token_x, Alice); + let amount_y = balance_of!(TokenRef, client, token_y, Alice); + assert_eq!(amount_x, 9999999501); + assert_eq!(amount_y, 9999999000); + + let amount_x = dex_balance!(TokenRef, client, token_x, dex); + let amount_y = dex_balance!(TokenRef, client, token_y, dex); + assert_eq!(amount_x, 1499); + assert_eq!(amount_y, 7); + + let pool_after_withdraw = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!( + pool_after_withdraw.fee_protocol_token_x, + TokenAmount::new(0) + ); + assert_eq!( + pool_after_withdraw.fee_protocol_token_y, + TokenAmount::new(0) + ); + + Ok(()) + } + + #[ink_e2e::test] + #[should_panic] + async fn protocol_fee_should_panic(mut client: ink_e2e::Client) -> () { + let (dex, token_x, token_y) = init_dex_and_tokens!(client, ContractRef, TokenRef); + init_basic_position!(client, ContractRef, TokenRef, dex, token_x, token_y); + init_basic_swap!(client, ContractRef, TokenRef, dex, token_x, token_y); + + let pool_key = PoolKey::new( + token_x, + token_y, + FeeTier { + fee: Percentage::from_scale(6, 3), + tick_spacing: 10, + }, + ) + .unwrap(); + let bob = ink_e2e::bob(); + withdraw_protocol_fee!(client, ContractRef, dex, pool_key, bob); + } + + #[ink_e2e::test] + async fn constructor_test(mut client: ink_e2e::Client) -> E2EResult<()> { + let constructor = TokenRef::new(500, None, None, 0); + let _token: AccountId = client + .instantiate("token", &ink_e2e::alice(), constructor, 0, None) + .await + .expect("Instantiate failed") + .account_id; + + let constructor = ContractRef::new(Percentage::new(0)); + + let _contract: AccountId = client + .instantiate("contract", &ink_e2e::alice(), constructor, 0, None) + .await + .expect("Instantiate failed") + .account_id; + Ok(()) + } + + #[ink_e2e::test] + async fn change_protocol_fee(mut client: ink_e2e::Client) -> E2EResult<()> { + let contract = create_dex!(client, ContractRef, Percentage::new(0)); + + let protocol_fee = { + let _msg = build_message::(contract.clone()) + .call(|contract| contract.get_protocol_fee()); + client + .call(&ink_e2e::alice(), _msg, 0, None) + .await + .expect("getting protocol fee failed") + } + .return_value(); + + assert_eq!(protocol_fee, Percentage::new(0)); + + let _result = { + let _msg = build_message::(contract.clone()) + .call(|contract| contract.change_protocol_fee(Percentage::new(1))); + client + .call(&ink_e2e::alice(), _msg, 0, None) + .await + .expect("changing protocol fee failed") + }; + + let protocol_fee = { + let _msg = build_message::(contract.clone()) + .call(|contract| contract.get_protocol_fee()); + client + .call(&ink_e2e::alice(), _msg, 0, None) + .await + .expect("getting protocol fee failed") + } + .return_value(); + + assert_eq!(protocol_fee, Percentage::new(1)); + + Ok(()) + } + + #[ink_e2e::test] + #[should_panic] + async fn change_protocol_fee_should_panic(mut client: ink_e2e::Client) -> () { + let contract = create_dex!(client, ContractRef, Percentage::new(0)); + + let result = { + let _msg = build_message::(contract.clone()) + .call(|contract| contract.change_protocol_fee(Percentage::new(1))); + client + .call(&ink_e2e::bob(), _msg, 0, None) + .await + .expect("changing protocol fee failed") + }; + } + + #[ink_e2e::test] + async fn create_position(mut client: ink_e2e::Client) -> E2EResult<()> { + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); + + let alice = ink_e2e::alice(); + + let fee_tier = FeeTier::new(Percentage::new(0), 1); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let pool = create_pool!(client, ContractRef, dex, token_x, token_y, fee_tier, 10); + + approve!(client, TokenRef, token_x, dex, 500, alice); + approve!(client, TokenRef, token_y, dex, 500, alice); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + let position = create_position!( + client, + ContractRef, + dex, + pool_key, + -10, + 10, + Liquidity::new(10), + SqrtPrice::new(0), + SqrtPrice::max_instance(), + alice + ); + + Ok(()) + } + + #[ink_e2e::test] + async fn create_fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let fee_tier = FeeTier::new(Percentage::new(0), 10u16); + let alice = ink_e2e::alice(); + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + let fee_tier = get_fee_tier!(client, ContractRef, dex, Percentage::new(0), 10u16); + assert!(fee_tier.is_some()); + Ok(()) + } + + #[ink_e2e::test] + async fn create_standard_fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + create_standard_fee_tiers!(client, ContractRef, dex); + let fee_tier = get_fee_tier!( + client, + ContractRef, + dex, + Percentage::from_scale(5, 2), + 100u16 + ); + assert!(fee_tier.is_some()); + Ok(()) + } + + #[ink_e2e::test] + async fn create_pool_test(mut client: ink_e2e::Client) -> E2EResult<()> { + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); + + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); + let init_tick = 0; + + let alice = ink_e2e::alice(); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let result = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + assert!(result.is_ok()); + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + Ok(()) + } + + #[ink_e2e::test] + async fn fee_tier_test(mut client: ink_e2e::Client) -> E2EResult<()> { + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let admin = ink_e2e::alice(); + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); + let result = create_fee_tier!(client, ContractRef, dex, fee_tier, admin); + assert!(result.is_ok()); + Ok(()) + } + #[ink_e2e::test] + #[should_panic] + async fn invalid_spacing_fee_tier_test(mut client: ink_e2e::Client) -> () { + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let admin = ink_e2e::alice(); + // 0 tick spacing | should fail + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 0); + let result = create_fee_tier!(client, ContractRef, dex, fee_tier, admin); + } + + #[ink_e2e::test] + #[should_panic] + async fn non_admin_fee_tier_caller_test(mut client: ink_e2e::Client) -> () { + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let user = ink_e2e::bob(); + // not-admin + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 10); + let result = create_fee_tier!(client, ContractRef, dex, fee_tier, user); + } + + #[ink_e2e::test] + async fn position_above_current_tick_test( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let alice = ink_e2e::alice(); + let init_tick = -23028; + + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let initial_balance = 10_000_000_000; + + let (token_x, token_y) = + create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); + + let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let pool = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + approve!(client, TokenRef, token_x, dex, initial_balance, alice); + approve!(client, TokenRef, token_y, dex, initial_balance, alice); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let lower_tick_index = -22980; + let upper_tick_index = 0; + let liquidity_delta = Liquidity::new(initial_balance); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + SqrtPrice::max_instance(), + alice + ); + + // Load states + let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let lower_tick = + get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + let upper_tick = + get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + let lower_tick_bit = + tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + let upper_tick_bit = + tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + let alice_x = balance_of!(TokenRef, client, token_x, Alice); + let alice_y = balance_of!(TokenRef, client, token_y, Alice); + let dex_x = dex_balance!(TokenRef, client, token_x, dex); + let dex_y = dex_balance!(TokenRef, client, token_y, dex); + + let zero_fee = FeeGrowth::new(0); + let expected_x_increase = 21549; + let expected_y_increase = 0; + + // Check ticks + assert!(lower_tick.index == lower_tick_index); + assert!(upper_tick.index == upper_tick_index); + assert_eq!(lower_tick.liquidity_gross, liquidity_delta); + assert_eq!(upper_tick.liquidity_gross, liquidity_delta); + assert_eq!(lower_tick.liquidity_change, liquidity_delta); + assert_eq!(upper_tick.liquidity_change, liquidity_delta); + assert!(lower_tick.sign); + assert!(!upper_tick.sign); + + // Check pool + assert!(pool_state.liquidity == Liquidity::new(0)); + assert!(pool_state.current_tick_index == init_tick); + + // Check position + assert!(position_state.pool_key == pool_key); + assert!(position_state.liquidity == liquidity_delta); + assert!(position_state.lower_tick_index == lower_tick_index); + assert!(position_state.upper_tick_index == upper_tick_index); + assert!(position_state.fee_growth_inside_x == zero_fee); + assert!(position_state.fee_growth_inside_y == zero_fee); + + // Check balances + assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); + assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); + + assert_eq!(dex_x, expected_x_increase); + assert_eq!(dex_y, expected_y_increase); + + Ok(()) + } + + #[ink_e2e::test] + async fn multiple_positions_on_same_tick( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let alice = ink_e2e::alice(); + let init_tick = 0; + + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let initial_balance = 100_000_000; + + let (token_x, token_y) = + create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); + + let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 10); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let pool = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + approve!(client, TokenRef, token_x, dex, initial_balance, alice); + approve!(client, TokenRef, token_y, dex, initial_balance, alice); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + // Three position on same lower and upper tick + { + let lower_tick_index = -10; + let upper_tick_index = 10; + + let liquidity_delta = Liquidity::new(100); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + SqrtPrice::max_instance(), + alice + ); + + let first_position = get_position!(client, ContractRef, dex, 0, alice).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + SqrtPrice::max_instance(), + alice + ); + + let second_position = get_position!(client, ContractRef, dex, 1, alice).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + SqrtPrice::max_instance(), + alice + ); + + let third_position = get_position!(client, ContractRef, dex, 2, alice).unwrap(); + + assert!(first_position.lower_tick_index == second_position.lower_tick_index); + assert!(first_position.upper_tick_index == second_position.upper_tick_index); + assert!(first_position.lower_tick_index == third_position.lower_tick_index); + assert!(first_position.upper_tick_index == third_position.upper_tick_index); + + // Load states + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let lower_tick = + get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + let upper_tick = + get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + let lower_tick_bit = + tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + let upper_tick_bit = + tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + let expected_liquidity = Liquidity::new(liquidity_delta.get() * 3); + let zero_fee = FeeGrowth::new(0); + + // Check ticks + assert!(lower_tick.index == lower_tick_index); + assert!(upper_tick.index == upper_tick_index); + assert_eq!(lower_tick.liquidity_gross, expected_liquidity); + assert_eq!(upper_tick.liquidity_gross, expected_liquidity); + assert_eq!(lower_tick.liquidity_change, expected_liquidity); + assert_eq!(upper_tick.liquidity_change, expected_liquidity); + assert!(lower_tick.sign); + assert!(!upper_tick.sign); + + // Check pool + assert_eq!(pool_state.liquidity, expected_liquidity); + assert!(pool_state.current_tick_index == init_tick); + + // Check first position + assert!(first_position.pool_key == pool_key); + assert!(first_position.liquidity == liquidity_delta); + assert!(first_position.lower_tick_index == lower_tick_index); + assert!(first_position.upper_tick_index == upper_tick_index); + assert!(first_position.fee_growth_inside_x == zero_fee); + assert!(first_position.fee_growth_inside_y == zero_fee); + + // Check second position + assert!(second_position.pool_key == pool_key); + assert!(second_position.liquidity == liquidity_delta); + assert!(second_position.lower_tick_index == lower_tick_index); + assert!(second_position.upper_tick_index == upper_tick_index); + assert!(second_position.fee_growth_inside_x == zero_fee); + assert!(second_position.fee_growth_inside_y == zero_fee); + + // Check third position + assert!(third_position.pool_key == pool_key); + assert!(third_position.liquidity == liquidity_delta); + assert!(third_position.lower_tick_index == lower_tick_index); + assert!(third_position.upper_tick_index == upper_tick_index); + assert!(third_position.fee_growth_inside_x == zero_fee); + assert!(third_position.fee_growth_inside_y == zero_fee); + } + { + let lower_tick_index = -10; + let upper_tick_index = 10; + let zero_fee = FeeGrowth::new(0); + + let liquidity_delta = Liquidity::new(100); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + SqrtPrice::max_instance(), + alice + ); + + let first_position = get_position!(client, ContractRef, dex, 3, alice).unwrap(); + + // Check first position + assert!(first_position.pool_key == pool_key); + assert!(first_position.liquidity == liquidity_delta); + assert!(first_position.lower_tick_index == lower_tick_index); + assert!(first_position.upper_tick_index == upper_tick_index); + assert!(first_position.fee_growth_inside_x == zero_fee); + assert!(first_position.fee_growth_inside_y == zero_fee); + + let lower_tick_index = -20; + let upper_tick_index = -10; + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + SqrtPrice::max_instance(), + alice + ); + + let second_position = get_position!(client, ContractRef, dex, 4, alice).unwrap(); + + // Check second position + assert!(second_position.pool_key == pool_key); + assert!(second_position.liquidity == liquidity_delta); + assert!(second_position.lower_tick_index == lower_tick_index); + assert!(second_position.upper_tick_index == upper_tick_index); + assert!(second_position.fee_growth_inside_x == zero_fee); + assert!(second_position.fee_growth_inside_y == zero_fee); + + let lower_tick_index = 10; + let upper_tick_index = 20; + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + SqrtPrice::max_instance(), + alice + ); + + let third_position = get_position!(client, ContractRef, dex, 5, alice).unwrap(); + + // Check third position + assert!(third_position.pool_key == pool_key); + assert!(third_position.liquidity == liquidity_delta); + assert!(third_position.lower_tick_index == lower_tick_index); + assert!(third_position.upper_tick_index == upper_tick_index); + assert!(third_position.fee_growth_inside_x == zero_fee); + assert!(third_position.fee_growth_inside_y == zero_fee); + + // Load states + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let tick_n20 = get_tick!(client, ContractRef, dex, -20, pool_key, alice).unwrap(); + let tick_n10 = get_tick!(client, ContractRef, dex, -10, pool_key, alice).unwrap(); + let tick_10 = get_tick!(client, ContractRef, dex, 10, pool_key, alice).unwrap(); + let tick_20 = get_tick!(client, ContractRef, dex, 20, pool_key, alice).unwrap(); + let tick_n20_bit = tickmap_bit!(client, ContractRef, dex, -20, pool_key, alice); + let tick_n10_bit = tickmap_bit!(client, ContractRef, dex, -10, pool_key, alice); + let tick_10_bit = tickmap_bit!(client, ContractRef, dex, 10, pool_key, alice); + let tick_20_bit = tickmap_bit!(client, ContractRef, dex, 20, pool_key, alice); + + let expected_active_liquidity = Liquidity::new(400); + + // Check tick -20 + assert_eq!(tick_n20.index, -20); + assert_eq!(tick_n20.liquidity_gross, Liquidity::new(100)); + assert_eq!(tick_n20.liquidity_change, Liquidity::new(100)); + assert!(tick_n20.sign); + assert!(tick_n20_bit); + + // Check tick -10 + assert_eq!(tick_n10.index, -10); + assert_eq!(tick_n10.liquidity_gross, Liquidity::new(500)); + assert_eq!(tick_n10.liquidity_change, Liquidity::new(300)); + assert!(tick_n10.sign); + assert!(tick_n10_bit); + + // Check tick 10 + assert_eq!(tick_10.index, 10); + assert_eq!(tick_10.liquidity_gross, Liquidity::new(500)); + assert_eq!(tick_10.liquidity_change, Liquidity::new(300)); + assert!(!tick_10.sign); + assert!(tick_20_bit); + + // Check tick 20 + assert_eq!(tick_20.index, 20); + assert_eq!(tick_20.liquidity_gross, Liquidity::new(100)); + assert_eq!(tick_20.liquidity_change, Liquidity::new(100)); + assert!(!tick_20.sign); + assert!(tick_20_bit); + + // Check pool + assert_eq!(pool_state.liquidity, expected_active_liquidity); + assert!(pool_state.current_tick_index == init_tick); + } + Ok(()) + } + + #[ink_e2e::test] + async fn position_within_current_tick_test( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let MAX_TICK_TEST = 177_450; // for tickSpacing 4 + let MIN_TICK_TEST = -MAX_TICK_TEST; + let alice = ink_e2e::alice(); + let init_tick = -23028; + + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let initial_balance = 100_000_000; + + let (token_x, token_y) = + create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); + + let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let pool = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + approve!(client, TokenRef, token_x, dex, initial_balance, alice); + approve!(client, TokenRef, token_y, dex, initial_balance, alice); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let lower_tick_index = MIN_TICK_TEST + 10; + let upper_tick_index = MAX_TICK_TEST - 10; + + let liquidity_delta = Liquidity::new(initial_balance); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + SqrtPrice::max_instance(), + alice + ); + + // Load states + let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let lower_tick = + get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + let upper_tick = + get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + let lower_tick_bit = + tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + let upper_tick_bit = + tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + let alice_x = balance_of!(TokenRef, client, token_x, Alice); + let alice_y = balance_of!(TokenRef, client, token_y, Alice); + let dex_x = dex_balance!(TokenRef, client, token_x, dex); + let dex_y = dex_balance!(TokenRef, client, token_y, dex); + + let zero_fee = FeeGrowth::new(0); + let expected_x_increase = 317; + let expected_y_increase = 32; + + // Check ticks + assert!(lower_tick.index == lower_tick_index); + assert!(upper_tick.index == upper_tick_index); + assert_eq!(lower_tick.liquidity_gross, liquidity_delta); + assert_eq!(upper_tick.liquidity_gross, liquidity_delta); + assert_eq!(lower_tick.liquidity_change, liquidity_delta); + assert_eq!(upper_tick.liquidity_change, liquidity_delta); + assert!(lower_tick.sign); + assert!(!upper_tick.sign); + + // Check pool + assert!(pool_state.liquidity == liquidity_delta); + assert!(pool_state.current_tick_index == init_tick); + + // Check position + assert!(position_state.pool_key == pool_key); + assert!(position_state.liquidity == liquidity_delta); + assert!(position_state.lower_tick_index == lower_tick_index); + assert!(position_state.upper_tick_index == upper_tick_index); + assert!(position_state.fee_growth_inside_x == zero_fee); + assert!(position_state.fee_growth_inside_y == zero_fee); + + // Check balances + assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); + assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); + assert_eq!(dex_x, expected_x_increase); + assert_eq!(dex_y, expected_y_increase); + + Ok(()) + } + + #[ink_e2e::test] + async fn position_below_current_tick_test( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let alice = ink_e2e::alice(); + let init_tick = -23028; + + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let initial_balance = 100_000_000_00; + + let (token_x, token_y) = + create_tokens!(client, TokenRef, TokenRef, initial_balance, initial_balance); + + let fee_tier = FeeTier::new(Percentage::from_scale(2, 4), 4); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let pool = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + approve!(client, TokenRef, token_x, dex, initial_balance, alice); + approve!(client, TokenRef, token_y, dex, initial_balance, alice); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + let lower_tick_index = -46080; + let upper_tick_index = -23040; + + let liquidity_delta = Liquidity::new(initial_balance); + + let pool_state_before = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state_before.sqrt_price, + SqrtPrice::max_instance(), + alice + ); + + // Load states + let position_state = get_position!(client, ContractRef, dex, 0, alice).unwrap(); + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let lower_tick = + get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + let upper_tick = + get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + let lower_tick_bit = + tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + let upper_tick_bit = + tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + let alice_x = balance_of!(TokenRef, client, token_x, Alice); + let alice_y = balance_of!(TokenRef, client, token_y, Alice); + let dex_x = dex_balance!(TokenRef, client, token_x, dex); + let dex_y = dex_balance!(TokenRef, client, token_y, dex); + + let zero_fee = FeeGrowth::new(0); + let expected_x_increase = 0; + let expected_y_increase = 2162; + + // Check ticks + assert!(lower_tick.index == lower_tick_index); + assert!(upper_tick.index == upper_tick_index); + assert_eq!(lower_tick.liquidity_gross, liquidity_delta); + assert_eq!(upper_tick.liquidity_gross, liquidity_delta); + assert_eq!(lower_tick.liquidity_change, liquidity_delta); + assert_eq!(upper_tick.liquidity_change, liquidity_delta); + assert!(lower_tick.sign); + assert!(!upper_tick.sign); + + // Check pool + assert!(pool_state.liquidity == pool_state_before.liquidity); + assert!(pool_state.current_tick_index == init_tick); + + // Check position + assert!(position_state.pool_key == pool_key); + assert!(position_state.liquidity == liquidity_delta); + assert!(position_state.lower_tick_index == lower_tick_index); + assert!(position_state.upper_tick_index == upper_tick_index); + assert!(position_state.fee_growth_inside_x == zero_fee); + assert!(position_state.fee_growth_inside_y == zero_fee); + + // Check balances + assert_eq!(alice_x, initial_balance.checked_sub(dex_x).unwrap()); + assert_eq!(alice_y, initial_balance.checked_sub(dex_y).unwrap()); + + assert_eq!(dex_x, expected_x_increase); + assert_eq!(dex_y, expected_y_increase); + + Ok(()) + } + + #[ink_e2e::test] + async fn change_fee_reciever_test(mut client: ink_e2e::Client) -> E2EResult<()> { + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); + + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 1); + let init_tick = 0; + + let alice = ink_e2e::alice(); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let result = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + assert!(result.is_ok()); + + let admin = ink_e2e::alice(); + let alice = address_of!(Alice); + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + change_fee_receiver!(client, ContractRef, dex, pool_key, alice, admin); + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!(pool.fee_receiver, alice); + + Ok(()) + } + + #[ink_e2e::test] + #[should_panic] + async fn not_admin_change_fee_reciever_test(mut client: ink_e2e::Client) -> () { + let dex = create_dex!(client, ContractRef, Percentage::new(0)); + let (token_x, token_y) = create_tokens!(client, TokenRef, TokenRef, 500, 500); + + let fee_tier = FeeTier::new(Percentage::from_scale(5, 1), 100); + let init_tick = 0; + + let admin = ink_e2e::alice(); + + create_fee_tier!(client, ContractRef, dex, fee_tier, admin); + + let result = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + assert!(result.is_ok()); + + let user = ink_e2e::bob(); + let bob = address_of!(Bob); + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + change_fee_receiver!(client, ContractRef, dex, pool_key, bob, user); + } + + #[ink_e2e::test] + async fn remove_position_test(mut client: ink_e2e::Client) -> E2EResult<()> { + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + let alice = ink_e2e::alice(); + let bob = ink_e2e::bob(); + let init_tick = 0; + let remove_position_index = 0; + + let initial_mint = 10u128.pow(10); + + let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); + let (token_x, token_y) = + create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let pool = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + let lower_tick_index = -20; + let upper_tick_index = 10; + let liquidity_delta = Liquidity::from_integer(1_000_000); + + approve!(client, TokenRef, token_x, dex, initial_mint, alice); + approve!(client, TokenRef, token_y, dex, initial_mint, alice); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + pool_state.sqrt_price, + alice + ); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + assert_eq!(pool_state.liquidity, liquidity_delta); + + let liquidity_delta = Liquidity::new(liquidity_delta.get() * 1_000_000); + { + let incorrect_lower_tick_index = lower_tick_index - 50; + let incorrect_upper_tick_index = upper_tick_index + 50; + + approve!(client, TokenRef, token_x, dex, liquidity_delta.get(), alice); + approve!(client, TokenRef, token_y, dex, liquidity_delta.get(), alice); + + create_position!( + client, + ContractRef, + dex, + pool_key, + incorrect_lower_tick_index, + incorrect_upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + pool_state.sqrt_price, + alice + ); + + let position_state = get_position!(client, ContractRef, dex, 1, alice).unwrap(); + // Check position + assert!(position_state.lower_tick_index == incorrect_lower_tick_index); + assert!(position_state.upper_tick_index == incorrect_upper_tick_index); + } + + let amount = 1000; + mint!(TokenRef, client, token_x, Bob, amount); + let amount_x = balance_of!(TokenRef, client, token_x, Bob); + assert_eq!(amount_x, amount); + + approve!(client, TokenRef, token_x, dex, amount, bob); + + let pool_state_before = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + let swap_amount = TokenAmount::new(amount); + let slippage = SqrtPrice::new(MIN_SQRT_PRICE); + swap!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + slippage, + bob + ); + + let pool_state_after = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!( + pool_state_after.fee_growth_global_x, + FeeGrowth::new(49999950000049999) + ); + assert_eq!(pool_state_after.fee_protocol_token_x, TokenAmount(1)); + assert_eq!(pool_state_after.fee_protocol_token_y, TokenAmount(0)); + + assert!(pool_state_after + .sqrt_price + .lt(&pool_state_before.sqrt_price)); + + assert_eq!(pool_state_after.liquidity, pool_state_before.liquidity); + assert_eq!(pool_state_after.current_tick_index, -10); + assert_ne!(pool_state_after.sqrt_price, pool_state_before.sqrt_price); + + let amount_x = balance_of!(TokenRef, client, token_x, Bob); + let amount_y = balance_of!(TokenRef, client, token_y, Bob); + assert_eq!(amount_x, 0); + assert_eq!(amount_y, 993); + + // pre load dex balances + let dex_x_before_remove = dex_balance!(TokenRef, client, token_x, dex); + let dex_y_before_remove = dex_balance!(TokenRef, client, token_y, dex); + + // Remove position + let remove_result = + remove_position!(client, ContractRef, dex, remove_position_index, alice); + + // Load states + let position_state = + get_position!(client, ContractRef, dex, remove_position_index, alice); + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let lower_tick = get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + let upper_tick = get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + let lower_tick_bit = + tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + let upper_tick_bit = + tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + let alice_x = balance_of!(TokenRef, client, token_x, Alice); + let alice_y = balance_of!(TokenRef, client, token_y, Alice); + let dex_x = dex_balance!(TokenRef, client, token_x, dex); + let dex_y = dex_balance!(TokenRef, client, token_y, dex); + let expected_withdrawn_x = 499; + let expected_withdrawn_y = 999; + let expected_fee_x = 0; + + assert_eq!( + dex_x_before_remove - dex_x, + expected_withdrawn_x + expected_fee_x + ); + assert_eq!(dex_y_before_remove - dex_y, expected_withdrawn_y); + + // Check ticks + assert_eq!(lower_tick, Err(InvariantError::TickNotFound)); + assert_eq!(upper_tick, Err(InvariantError::TickNotFound)); + + // Check tickmap + assert!(!lower_tick_bit); + assert!(!upper_tick_bit); + + // Check pool + assert!(pool_state.liquidity == liquidity_delta); + assert!(pool_state.current_tick_index == -10); + + Ok(()) + } + + #[ink_e2e::test] + async fn position_slippage_zero_slippage_and_inside_range( + mut client: ink_e2e::Client, + ) -> E2EResult<()> { + let alice = ink_e2e::alice(); + let (dex, token_x, token_y) = + init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); + let pool_key = create_slippage_pool_with_liquidity!( + client, + ContractRef, + TokenRef, + dex, + token_x, + token_y + ); + + let pool = get_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + pool_key.fee_tier + ) + .unwrap(); + + // zero slippage + { + let liquidity_delta = Liquidity::from_integer(1_000_000); + let known_price = pool.sqrt_price; + let tick = pool_key.fee_tier.tick_spacing as i32; + create_position!( + client, + ContractRef, + dex, + pool_key, + -tick, + tick, + liquidity_delta, + known_price, + known_price, + alice + ); + } + // inside range + { + let liquidity_delta = Liquidity::from_integer(1_000_000); + let known_price = SqrtPrice::new(1010000000000000000000000); + let limit_lower = SqrtPrice::new(994734637981406576896367); + let limit_upper = SqrtPrice::new(1025038048074314166333500); + + let tick = pool_key.fee_tier.tick_spacing as i32; + + create_position!( + client, + ContractRef, + dex, + pool_key, + -tick, + tick, + liquidity_delta, + limit_lower, + limit_upper, + alice + ); + } + + Ok(()) + } + #[ink_e2e::test] + #[should_panic] + async fn position_slippage_below_range(mut client: ink_e2e::Client) -> () { + let alice = ink_e2e::alice(); + let (dex, token_x, token_y) = + init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); + let pool_key = create_slippage_pool_with_liquidity!( + client, + ContractRef, + TokenRef, + dex, + token_x, + token_y + ); + + let pool = get_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + pool_key.fee_tier + ) + .unwrap(); + + let liquidity_delta = Liquidity::from_integer(1_000_000); + let known_price = SqrtPrice::new(1030000000000000000000000); + let limit_lower = SqrtPrice::new(1014432353584998786339859); + let limit_upper = SqrtPrice::new(1045335831204498605270797); + let tick = pool_key.fee_tier.tick_spacing as i32; + create_position!( + client, + ContractRef, + dex, + pool_key, + -tick, + tick, + liquidity_delta, + limit_lower, + limit_upper, + alice + ); + } + #[ink_e2e::test] + #[should_panic] + async fn position_slippage_above_range(mut client: ink_e2e::Client) -> () { + let alice = ink_e2e::alice(); + let (dex, token_x, token_y) = + init_slippage_dex_and_tokens!(client, ContractRef, TokenRef); + let pool_key = create_slippage_pool_with_liquidity!( + client, + ContractRef, + TokenRef, + dex, + token_x, + token_y + ); + + let pool = get_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + pool_key.fee_tier + ) + .unwrap(); + + let liquidity_delta = Liquidity::from_integer(1_000_000); + let known_price = pool.sqrt_price; + let limit_lower = SqrtPrice::new(955339206774222158009382); + let limit_upper = SqrtPrice::new(984442481813945288458906); + let tick = pool_key.fee_tier.tick_spacing as i32; + create_position!( + client, + ContractRef, + dex, + pool_key, + -tick, + tick, + liquidity_delta, + limit_lower, + limit_upper, + alice + ); + } + + #[ink_e2e::test] + #[should_panic] + async fn no_liquidity_swap(mut client: ink_e2e::Client) -> () { + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + let alice = ink_e2e::alice(); + let bob = ink_e2e::bob(); + let init_tick = 0; + + let initial_mint = 10u128.pow(10); + + let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); + let (token_x, token_y) = + create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let pool = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + let lower_tick_index = -10; + let upper_tick_index = 10; + + let mint_amount = 10u128.pow(10); + mint!(TokenRef, client, token_x, Alice, mint_amount); + mint!(TokenRef, client, token_y, Alice, mint_amount); + + approve!(client, TokenRef, token_x, dex, mint_amount, alice); + approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + let liquidity_delta = Liquidity::from_integer(20_006_000); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + pool_state.sqrt_price, + alice + ); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + assert_eq!(pool_state.liquidity, liquidity_delta); + + let mint_amount = 10067; + mint!(TokenRef, client, token_x, Bob, mint_amount); + + approve!(client, TokenRef, token_x, dex, mint_amount, bob); + + let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); + let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); + + let swap_amount = TokenAmount::new(10067); + let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + let quoted_target_sqrt_price = quote!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + target_sqrt_price, + alice + ) + .unwrap() + .2; + + swap!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + quoted_target_sqrt_price, + bob + ); + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let expected_price = calculate_sqrt_price(-10).unwrap(); + let expected_y_amount_out = 9999; + + assert_eq!(pool.liquidity, liquidity_delta); + assert_eq!(pool.current_tick_index, lower_tick_index); + assert_eq!(pool.sqrt_price, expected_price); + + let bob_x = balance_of!(TokenRef, client, token_x, Bob); + let bob_y = balance_of!(TokenRef, client, token_y, Bob); + let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); + let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); + + let delta_dex_x = dex_x_after - dex_x_before; + let delta_dex_y = dex_y_before - dex_y_after; + + assert_eq!(bob_x, 0); + assert_eq!(bob_y, expected_y_amount_out); + assert_eq!(delta_dex_x, swap_amount.get()); + assert_eq!(delta_dex_y, expected_y_amount_out); + assert_eq!( + pool.fee_growth_global_x, + FeeGrowth::new(29991002699190242927121) + ); + assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); + assert_eq!(pool.fee_protocol_token_x, TokenAmount::new(1)); + assert_eq!(pool.fee_protocol_token_y, TokenAmount::new(0)); + + let swap_amount = TokenAmount(1); + let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + let quoted_target_sqrt_price = quote!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + target_sqrt_price, + alice + ) + .unwrap() + .2; + swap!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + quoted_target_sqrt_price, + bob + ); + } + + #[ink_e2e::test] + async fn liquidity_gap_test(mut client: ink_e2e::Client) -> E2EResult<()> { + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + let alice = ink_e2e::alice(); + let bob = ink_e2e::bob(); + let init_tick = 0; + + let initial_mint = 10u128.pow(10); + + let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); + let (token_x, token_y) = + create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let pool = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + let lower_tick_index = -10; + let upper_tick_index = 10; + + let mint_amount = 10u128.pow(10); + mint!(TokenRef, client, token_x, Alice, mint_amount); + mint!(TokenRef, client, token_y, Alice, mint_amount); + + approve!(client, TokenRef, token_x, dex, mint_amount, alice); + approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + let liquidity_delta = Liquidity::from_integer(20_006_000); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + pool_state.sqrt_price, + alice + ); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + assert_eq!(pool_state.liquidity, liquidity_delta); + + let mint_amount = 10067; + mint!(TokenRef, client, token_x, Bob, mint_amount); + + approve!(client, TokenRef, token_x, dex, mint_amount, bob); + + let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); + let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); + + let swap_amount = TokenAmount::new(10067); + let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + let quoted_target_sqrt_price = quote!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + target_sqrt_price, + alice + ) + .unwrap() + .2; + + swap!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + quoted_target_sqrt_price, + bob + ); + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let expected_price = calculate_sqrt_price(-10).unwrap(); + let expected_y_amount_out = 9999; + + assert_eq!(pool.liquidity, liquidity_delta); + assert_eq!(pool.current_tick_index, lower_tick_index); + assert_eq!(pool.sqrt_price, expected_price); + + let bob_x = balance_of!(TokenRef, client, token_x, Bob); + let bob_y = balance_of!(TokenRef, client, token_y, Bob); + let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); + let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); + + let delta_dex_x = dex_x_after - dex_x_before; + let delta_dex_y = dex_y_before - dex_y_after; + + assert_eq!(bob_x, 0); + assert_eq!(bob_y, expected_y_amount_out); + assert_eq!(delta_dex_x, swap_amount.get()); + assert_eq!(delta_dex_y, expected_y_amount_out); + assert_eq!( + pool.fee_growth_global_x, + FeeGrowth::new(29991002699190242927121) + ); + assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); + assert_eq!(pool.fee_protocol_token_x, TokenAmount::new(1)); + assert_eq!(pool.fee_protocol_token_y, TokenAmount::new(0)); + + // Should skip gap and then swap + let lower_tick_after_swap = -90; + let upper_tick_after_swap = -50; + let liquidity_delta = Liquidity::from_integer(20008000); + + approve!(client, TokenRef, token_x, dex, liquidity_delta.get(), alice); + approve!(client, TokenRef, token_y, dex, liquidity_delta.get(), alice); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_after_swap, + upper_tick_after_swap, + liquidity_delta, + pool_state.sqrt_price, + pool_state.sqrt_price, + alice + ); + + let swap_amount = TokenAmount::new(5000); + mint!(TokenRef, client, token_x, Bob, swap_amount.get()); + + approve!(client, TokenRef, token_x, dex, swap_amount.get(), bob); + + let dex_x_before = dex_balance!(TokenRef, client, token_x, dex); + let dex_y_before = dex_balance!(TokenRef, client, token_y, dex); + + let target_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + let quoted_target_sqrt_price = quote!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + target_sqrt_price, + alice + ) + .unwrap() + .2; + + swap!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + quoted_target_sqrt_price, + bob + ); + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + let bob_x = balance_of!(TokenRef, client, token_x, Bob); + let bob_y = balance_of!(TokenRef, client, token_y, Bob); + let dex_x_after = dex_balance!(TokenRef, client, token_x, dex); + let dex_y_after = dex_balance!(TokenRef, client, token_y, dex); + + let delta_dex_x = dex_x_after - dex_x_before; + let delta_dex_y = dex_y_before - dex_y_after; + Ok(()) + } + + #[ink_e2e::test] + async fn cross_both_side_test(mut client: ink_e2e::Client) -> E2EResult<()> { + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + let alice = ink_e2e::alice(); + let bob = ink_e2e::bob(); + let init_tick = 0; + + let initial_mint = 10u128.pow(10); + + let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); + let (token_x, token_y) = + create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let pool = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + let lower_tick_index = -10; + let upper_tick_index = 10; + + let mint_amount = 10u128.pow(5); + mint!(TokenRef, client, token_x, Alice, mint_amount); + mint!(TokenRef, client, token_y, Alice, mint_amount); + + approve!(client, TokenRef, token_x, dex, mint_amount, alice); + approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + let liquidity_delta = Liquidity::new(20006000000000); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + pool_state.sqrt_price, + alice + ); + + create_position!( + client, + ContractRef, + dex, + pool_key, + -20, + lower_tick_index, + liquidity_delta, + pool_state.sqrt_price, + pool_state.sqrt_price, + alice + ); + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + assert_eq!(pool.liquidity, liquidity_delta); + + let limit_without_cross_tick_amount = TokenAmount(10_068); + let not_cross_amount = TokenAmount(1); + let min_amount_to_cross_from_tick_price = TokenAmount(3); + let crossing_amount_by_amount_out = TokenAmount(20136101434); + + let mint_amount = limit_without_cross_tick_amount.get() + + not_cross_amount.get() + + min_amount_to_cross_from_tick_price.get() + + crossing_amount_by_amount_out.get(); + + mint!(TokenRef, client, token_x, Alice, mint_amount); + mint!(TokenRef, client, token_y, Alice, mint_amount); + + approve!(client, TokenRef, token_x, dex, mint_amount, alice); + approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + let pool_before = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + let limit_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + + swap!( + client, + ContractRef, + dex, + pool_key, + true, + limit_without_cross_tick_amount, + true, + limit_sqrt_price, + alice + ); + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let expected_tick = -10; + let expected_price = calculate_sqrt_price(expected_tick).unwrap(); + + assert_eq!(pool.current_tick_index, expected_tick); + assert_eq!(pool.liquidity, pool_before.liquidity); + assert_eq!(pool.sqrt_price, expected_price); + + swap!( + client, + ContractRef, + dex, + pool_key, + true, + min_amount_to_cross_from_tick_price, + true, + limit_sqrt_price, + alice + ); + + swap!( + client, + ContractRef, + dex, + pool_key, + false, + min_amount_to_cross_from_tick_price, + true, + SqrtPrice::new(MAX_SQRT_PRICE), + alice + ); + + let massive_x = 10u128.pow(19); + let massive_y = 10u128.pow(19); + + mint!(TokenRef, client, token_x, Alice, massive_x); + mint!(TokenRef, client, token_y, Alice, massive_y); + approve!(client, TokenRef, token_x, dex, massive_x, alice); + approve!(client, TokenRef, token_y, dex, massive_y, alice); + + let massive_liquidity_delta = Liquidity::new(19996000399699881985603000000); + + create_position!( + client, + ContractRef, + dex, + pool_key, + -20, + 0, + massive_liquidity_delta, + SqrtPrice::new(MIN_SQRT_PRICE), + SqrtPrice::new(MAX_SQRT_PRICE), + alice + ); + + swap!( + client, + ContractRef, + dex, + pool_key, + true, + TokenAmount(1), + false, + limit_sqrt_price, + alice + ); + + swap!( + client, + ContractRef, + dex, + pool_key, + false, + TokenAmount(2), + true, + SqrtPrice::new(MAX_SQRT_PRICE), + alice + ); + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + assert_eq!(pool.current_tick_index, -20); + assert_eq!( + pool.fee_growth_global_x, + FeeGrowth::new(29991002699190242927121) + ); + assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); + assert_eq!(pool.fee_protocol_token_x, TokenAmount(4)); + assert_eq!(pool.fee_protocol_token_y, TokenAmount(2)); + assert_eq!( + pool.liquidity, + Liquidity::new(19996000399699901991603000000) + ); + assert_eq!(pool.sqrt_price, SqrtPrice::new(999500149964999999999999)); + + let final_last_tick = + get_tick!(client, ContractRef, dex, -20, pool_key, alice).unwrap(); + assert_eq!(final_last_tick.fee_growth_outside_x, FeeGrowth::new(0)); + assert_eq!(final_last_tick.fee_growth_outside_y, FeeGrowth::new(0)); + assert_eq!( + final_last_tick.liquidity_change, + Liquidity::new(19996000399699901991603000000) + ); + + let final_lower_tick = + get_tick!(client, ContractRef, dex, -10, pool_key, alice).unwrap(); + assert_eq!( + final_lower_tick.fee_growth_outside_x, + FeeGrowth::new(29991002699190242927121) + ); + assert_eq!(final_lower_tick.fee_growth_outside_y, FeeGrowth::new(0)); + assert_eq!(final_lower_tick.liquidity_change, Liquidity::new(0)); + + let final_upper_tick = + get_tick!(client, ContractRef, dex, 10, pool_key, alice).unwrap(); + assert_eq!(final_upper_tick.fee_growth_outside_x, FeeGrowth::new(0)); + assert_eq!(final_upper_tick.fee_growth_outside_y, FeeGrowth::new(0)); + assert_eq!( + final_upper_tick.liquidity_change, + Liquidity::new(20006000000000) + ); + + Ok(()) + } + + #[ink_e2e::test] + #[should_panic] + async fn cross_both_side_not_cross_case_test(mut client: ink_e2e::Client) -> () { + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + let alice = ink_e2e::alice(); + let bob = ink_e2e::bob(); + let init_tick = 0; + + let initial_mint = 10u128.pow(10); + + let dex = create_dex!(client, ContractRef, Percentage::from_scale(1, 2)); + let (token_x, token_y) = + create_tokens!(client, TokenRef, TokenRef, initial_mint, initial_mint); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let pool = create_pool!( + client, + ContractRef, + dex, + token_x, + token_y, + fee_tier, + init_tick + ); + + let lower_tick_index = -10; + let upper_tick_index = 10; + + let mint_amount = 10u128.pow(5); + mint!(TokenRef, client, token_x, Alice, mint_amount); + mint!(TokenRef, client, token_y, Alice, mint_amount); + + approve!(client, TokenRef, token_x, dex, mint_amount, alice); + approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + let liquidity_delta = Liquidity::new(20006000000000); + + let pool_state = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + pool_state.sqrt_price, + pool_state.sqrt_price, + alice + ); + + create_position!( + client, + ContractRef, + dex, + pool_key, + -20, + lower_tick_index, + liquidity_delta, + pool_state.sqrt_price, + pool_state.sqrt_price, + alice + ); + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + assert_eq!(pool.liquidity, liquidity_delta); + + let limit_without_cross_tick_amount = TokenAmount(10_068); + let not_cross_amount = TokenAmount(1); + let min_amount_to_cross_from_tick_price = TokenAmount(3); + let crossing_amount_by_amount_out = TokenAmount(20136101434); + + let mint_amount = limit_without_cross_tick_amount.get() + + not_cross_amount.get() + + min_amount_to_cross_from_tick_price.get() + + crossing_amount_by_amount_out.get(); + + mint!(TokenRef, client, token_x, Alice, mint_amount); + mint!(TokenRef, client, token_y, Alice, mint_amount); + + approve!(client, TokenRef, token_x, dex, mint_amount, alice); + approve!(client, TokenRef, token_y, dex, mint_amount, alice); + + let pool_before = + get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + let limit_sqrt_price = SqrtPrice::new(MIN_SQRT_PRICE); + + swap!( + client, + ContractRef, + dex, + pool_key, + true, + limit_without_cross_tick_amount, + true, + limit_sqrt_price, + alice + ); + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let expected_tick = -10; + let expected_price = calculate_sqrt_price(expected_tick).unwrap(); + + assert_eq!(pool.current_tick_index, expected_tick); + assert_eq!(pool.liquidity, pool_before.liquidity); + assert_eq!(pool.sqrt_price, expected_price); + + let slippage = SqrtPrice::new(MIN_SQRT_PRICE); + let target_sqrt_price = quote!( + client, + ContractRef, + dex, + pool_key, + true, + not_cross_amount, + true, + slippage, + alice + ) + .unwrap() + .2; + + swap!( + client, + ContractRef, + dex, + pool_key, + true, + not_cross_amount, + true, + target_sqrt_price, + alice + ); + } } } From 9205749fea94e6220e04f7fd9bede7f3bb4eb17f Mon Sep 17 00:00:00 2001 From: Sniezka Date: Wed, 29 Nov 2023 11:21:27 +0100 Subject: [PATCH 6/7] Added QuoteResult struct --- src/contracts/entrypoints.rs | 4 ++-- src/lib.rs | 45 ++++++++++++++++++++++-------------- src/test_helpers/lib.rs | 2 +- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/contracts/entrypoints.rs b/src/contracts/entrypoints.rs index 7d105d6f..9219df1e 100644 --- a/src/contracts/entrypoints.rs +++ b/src/contracts/entrypoints.rs @@ -1,5 +1,5 @@ use crate::{ - contract::{CalculateSwapResult, Hop}, + contract::{CalculateSwapResult, Hop, QuoteResult}, contracts::{FeeTier, FeeTierKey, Pool, PoolKey, Position, Tick}, math::{ liquidity::Liquidity, percentage::Percentage, sqrt_price::sqrt_price::SqrtPrice, @@ -66,7 +66,7 @@ pub trait Invariant { amount: TokenAmount, by_amount_in: bool, sqrt_price_limit: SqrtPrice, - ) -> Result<(TokenAmount, TokenAmount, SqrtPrice, Vec), InvariantError>; + ) -> Result; #[ink(message)] fn quote_route( diff --git a/src/lib.rs b/src/lib.rs index 872c2df7..e22af57b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,6 +111,17 @@ pub mod contract { pub pool: Pool, pub ticks: Vec, } + #[derive(Default, Debug, scale::Decode, scale::Encode)] + #[cfg_attr( + feature = "std", + derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout) + )] + pub struct QuoteResult { + pub amount_in: TokenAmount, + pub amount_out: TokenAmount, + pub target_sqrt_price: SqrtPrice, + pub ticks: Vec, + } #[derive(scale::Decode, Default, scale::Encode, Clone, Debug)] #[cfg_attr( @@ -627,16 +638,16 @@ pub mod contract { amount: TokenAmount, by_amount_in: bool, sqrt_price_limit: SqrtPrice, - ) -> Result<(TokenAmount, TokenAmount, SqrtPrice, Vec), InvariantError> { + ) -> Result { let calculate_swap_result = self.calculate_swap(pool_key, x_to_y, amount, by_amount_in, sqrt_price_limit)?; - Ok(( - calculate_swap_result.amount_in, - calculate_swap_result.amount_out, - calculate_swap_result.pool.sqrt_price, - calculate_swap_result.ticks, - )) + Ok(QuoteResult { + amount_in: calculate_swap_result.amount_in, + amount_out: calculate_swap_result.amount_out, + target_sqrt_price: calculate_swap_result.pool.sqrt_price, + ticks: calculate_swap_result.ticks, + }) } #[ink(message)] @@ -1214,7 +1225,7 @@ pub mod contract { type E2EResult = Result>; #[ink_e2e::test] - async fn reversed(mut client: ink_e2e::Client) -> E2EResult<()> { + async fn test_swap_y_to_x(mut client: ink_e2e::Client) -> E2EResult<()> { let dex = create_dex!(client, ContractRef, Percentage::from_scale(6, 3)); let initial_amount = 10u128.pow(10); let (token_x, token_y) = @@ -1288,7 +1299,7 @@ pub mod contract { bob ) .unwrap() - .2; + .target_sqrt_price; let before_dex_x = dex_balance!(TokenRef, client, token_x, dex); let before_dex_y = dex_balance!(TokenRef, client, token_y, dex); @@ -1552,7 +1563,7 @@ pub mod contract { let contract_amount_y = dex_balance!(TokenRef, client, token_y, dex); let expected_x = 0; - let expected_y = 42534896005851865508212194815854; + let expected_y = 42534896005851865508212194815854; // < 2^106 assert_eq!(contract_amount_x, expected_x); assert_eq!(contract_amount_y, expected_y); } @@ -1905,7 +1916,7 @@ pub mod contract { let crosses_after_quote = ((pool_after_quote.current_tick_index - pool_before.current_tick_index) / 10).abs(); assert_eq!(crosses_after_quote, 0); - assert_eq!(quote_result.3.len() - 1, 146); + assert_eq!(quote_result.ticks.len() - 1, 146); swap!( client, @@ -1934,7 +1945,7 @@ pub mod contract { assert_eq!(crosses, 146); assert_eq!( pool_after.current_tick_index, - get_tick_at_sqrt_price(quote_result.2, 10).unwrap() + get_tick_at_sqrt_price(quote_result.target_sqrt_price, 10).unwrap() ); Ok(()) @@ -3454,7 +3465,7 @@ pub mod contract { alice ) .unwrap() - .2; + .target_sqrt_price; swap!( client, @@ -3510,7 +3521,7 @@ pub mod contract { alice ) .unwrap() - .2; + .target_sqrt_price; swap!( client, ContractRef, @@ -3606,7 +3617,7 @@ pub mod contract { alice ) .unwrap() - .2; + .target_sqrt_price; swap!( client, @@ -3693,7 +3704,7 @@ pub mod contract { alice ) .unwrap() - .2; + .target_sqrt_price; swap!( client, @@ -4074,7 +4085,7 @@ pub mod contract { alice ) .unwrap() - .2; + .target_sqrt_price; swap!( client, diff --git a/src/test_helpers/lib.rs b/src/test_helpers/lib.rs index fcfac3ce..f75a4dd7 100644 --- a/src/test_helpers/lib.rs +++ b/src/test_helpers/lib.rs @@ -1253,7 +1253,7 @@ macro_rules! swap_exact_limit { $x_to_y, $amount, $by_amount_in, - quote_result.2, + quote_result.target_sqrt_price, $caller ); }}; From 2d5e0beff3f3151f511488f6edec1558301151d3 Mon Sep 17 00:00:00 2001 From: Sniezka Date: Wed, 29 Nov 2023 11:41:30 +0100 Subject: [PATCH 7/7] Added x_to_y test --- src/lib.rs | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index e22af57b..9596102c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1224,6 +1224,152 @@ pub mod contract { type E2EResult = Result>; + #[ink_e2e::test] + async fn test_swap_x_to_y(mut client: ink_e2e::Client) -> E2EResult<()> { + let dex = create_dex!(client, ContractRef, Percentage::from_scale(6, 3)); + let initial_amount = 10u128.pow(10); + let (token_x, token_y) = + create_tokens!(client, TokenRef, TokenRef, initial_amount, initial_amount); + + let alice = ink_e2e::alice(); + + let fee_tier = FeeTier::new(Percentage::from_scale(6, 3), 10); + + create_fee_tier!(client, ContractRef, dex, fee_tier, alice); + + let pool = create_pool!(client, ContractRef, dex, token_x, token_y, fee_tier, 0); + + approve!(client, TokenRef, token_x, dex, initial_amount, alice); + approve!(client, TokenRef, token_y, dex, initial_amount, alice); + + let pool_key = PoolKey::new(token_x, token_y, fee_tier).unwrap(); + + let lower_tick_index = -20; + let middle_tick_index = -10; + let upper_tick_index = 10; + + let liquidity_delta = Liquidity::from_integer(1000000); + + let position = create_position!( + client, + ContractRef, + dex, + pool_key, + lower_tick_index, + upper_tick_index, + liquidity_delta, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + alice + ); + + let position = create_position!( + client, + ContractRef, + dex, + pool_key, + middle_tick_index, + upper_tick_index - 20, + liquidity_delta, + SqrtPrice::new(0), + SqrtPrice::max_instance(), + alice + ); + + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + + assert_eq!(pool.liquidity, liquidity_delta); + + let amount = 1000; + let swap_amount = TokenAmount(amount); + let bob = ink_e2e::bob(); + mint_with_aprove_for_bob!(client, TokenRef, token_x, dex, amount); + + let slippage = SqrtPrice::new(MIN_SQRT_PRICE); + let target_sqrt_price = quote!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + slippage, + alice + ) + .unwrap() + .target_sqrt_price; + + let before_dex_x = dex_balance!(TokenRef, client, token_x, dex); + let before_dex_y = dex_balance!(TokenRef, client, token_y, dex); + + swap!( + client, + ContractRef, + dex, + pool_key, + true, + swap_amount, + true, + target_sqrt_price, + bob + ); + + // Load states + let pool = get_pool!(client, ContractRef, dex, token_x, token_y, fee_tier).unwrap(); + let lower_tick = + get_tick!(client, ContractRef, dex, lower_tick_index, pool_key, alice).unwrap(); + let middle_tick = + get_tick!(client, ContractRef, dex, middle_tick_index, pool_key, alice).unwrap(); + let upper_tick = + get_tick!(client, ContractRef, dex, upper_tick_index, pool_key, alice).unwrap(); + let lower_tick_bit = + tickmap_bit!(client, ContractRef, dex, lower_tick_index, pool_key, alice); + let middle_tick_bit = + tickmap_bit!(client, ContractRef, dex, middle_tick_index, pool_key, alice); + let upper_tick_bit = + tickmap_bit!(client, ContractRef, dex, upper_tick_index, pool_key, alice); + let bob_x = balance_of!(TokenRef, client, token_x, Bob); + let bob_y = balance_of!(TokenRef, client, token_y, Bob); + let dex_x = dex_balance!(TokenRef, client, token_x, dex); + let dex_y = dex_balance!(TokenRef, client, token_y, dex); + let delta_dex_y = before_dex_y - dex_y; + let delta_dex_x = dex_x - before_dex_x; + let expected_y = amount - 10; + let expected_x = 0; + + // Check balances + assert_eq!(bob_x, expected_x); + assert_eq!(bob_y, expected_y); + assert_eq!(delta_dex_x, amount); + assert_eq!(delta_dex_y, expected_y); + + // Check Pool + assert_eq!(pool.fee_growth_global_y, FeeGrowth::new(0)); + assert_eq!( + pool.fee_growth_global_x, + FeeGrowth::new(40000000000000000000000) + ); + assert_eq!(pool.fee_protocol_token_y, TokenAmount(0)); + assert_eq!(pool.fee_protocol_token_x, TokenAmount(2)); + + // Check Ticks + assert_eq!(lower_tick.liquidity_change, liquidity_delta); + assert_eq!(middle_tick.liquidity_change, liquidity_delta); + assert_eq!(upper_tick.liquidity_change, liquidity_delta); + assert_eq!(upper_tick.fee_growth_outside_x, FeeGrowth::new(0)); + assert_eq!( + middle_tick.fee_growth_outside_x, + FeeGrowth::new(30000000000000000000000) + ); + assert_eq!(lower_tick.fee_growth_outside_x, FeeGrowth::new(0)); + assert!(lower_tick_bit); + assert!(middle_tick_bit); + assert!(upper_tick_bit); + + Ok(()) + } + #[ink_e2e::test] async fn test_swap_y_to_x(mut client: ink_e2e::Client) -> E2EResult<()> { let dex = create_dex!(client, ContractRef, Percentage::from_scale(6, 3));