From 1e694f71410ed97a16742f1412aa31af28430777 Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 10 Jul 2023 11:52:19 +0200 Subject: [PATCH 1/3] test: stableswap - add additioanl invariants tests --- Cargo.lock | 2 +- math/Cargo.toml | 2 +- math/src/stableswap/tests/invariants.rs | 69 +++++++++++++++++++ math/src/stableswap/tests/multi_assets.rs | 84 +++++++++++++++++++++++ 4 files changed, 155 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d908e9410..f72050c7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3685,7 +3685,7 @@ dependencies = [ [[package]] name = "hydra-dx-math" -version = "7.4.2" +version = "7.4.3" dependencies = [ "approx", "criterion", diff --git a/math/Cargo.toml b/math/Cargo.toml index 47191d1c9..c6005ee41 100644 --- a/math/Cargo.toml +++ b/math/Cargo.toml @@ -6,7 +6,7 @@ license = 'Apache-2.0' name = "hydra-dx-math" description = "A collection of utilities to make performing liquidity pool calculations more convenient." repository = 'https://github.com/galacticcouncil/hydradx-math' -version = "7.4.2" +version = "7.4.3" [dependencies] primitive-types = {default-features = false, version = '0.12.0'} diff --git a/math/src/stableswap/tests/invariants.rs b/math/src/stableswap/tests/invariants.rs index a730aeda7..919b3af02 100644 --- a/math/src/stableswap/tests/invariants.rs +++ b/math/src/stableswap/tests/invariants.rs @@ -145,3 +145,72 @@ proptest! { assert!(y >= reserve_a); } } + +fn decimals() -> impl Strategy { + prop_oneof![Just(6), Just(8), Just(10), Just(12), Just(18)] +} + +fn reserve(max: Balance, precision: u32) -> impl Strategy { + let min_reserve = 5 * 10u128.pow(precision) + 10u128.pow(precision); + let max_reserve = max * 10u128.pow(precision); + min_reserve..max_reserve +} + +prop_compose! { + fn generate_reserves(dec_1: u32, dec_2: u32, dec_3: u32) + ( + reserve_1 in reserve(1_000, dec_1), + reserve_2 in reserve(1_000, dec_2), + reserve_3 in reserve(1_000, dec_3), + ) + -> Vec { + vec![reserve_1, reserve_2, reserve_3] + } +} + +prop_compose! { + fn some_pool_reserves() + ( + dec_1 in decimals(), + dec_2 in decimals(), + dec_3 in decimals(), + ) + ( + dec_1 in Just(dec_1), + r in generate_reserves(dec_1, dec_2, dec_3), + ) + -> (Vec, u32) { + (r, dec_1) + } +} +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn in_given_out_should_work_when_reserves_have_various_decimals( + (reserves, dec_1) in some_pool_reserves(), + amp in amplification(), + ) { + let d0 = calculate_d::(&reserves, amp).unwrap(); + let result = calculate_in_given_out::(&reserves, 0, 1, 10u128.pow(dec_1), amp); + if let Some(amount_in) = result { + let d1 = calculate_d::(&[reserves[0] + amount_in, reserves[1] - 10u128.pow(dec_1), reserves[2]], amp).unwrap(); + assert!(d1 >= d0); + } + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1000))] + #[test] + fn out_given_in_should_work_when_reserves_have_various_decimals( + (reserves, dec_1) in some_pool_reserves(), + amp in amplification(), + ) { + let d0 = calculate_d::(&reserves, amp).unwrap(); + let result = calculate_out_given_in::(&reserves, 0, 1, 10u128.pow(dec_1), amp); + if let Some(amount_out) = result { + let d1 = calculate_d::(&[reserves[0] + 10u128.pow(dec_1), reserves[1] - amount_out, reserves[2]], amp).unwrap(); + assert!(d1 >= d0); + } + } +} diff --git a/math/src/stableswap/tests/multi_assets.rs b/math/src/stableswap/tests/multi_assets.rs index 7d1fb0fde..616253d10 100644 --- a/math/src/stableswap/tests/multi_assets.rs +++ b/math/src/stableswap/tests/multi_assets.rs @@ -455,3 +455,87 @@ fn calculate_in_given_out_with_zero_fee_should_work_when_reserves_have_different ); assert_eq!(result.unwrap(), (841869902748480839 - 8335345571767138, 0)); } + +#[test] +fn test_compare_precision_results_01() { + let amp = 1000_u128; + + let balances: [Balance; 3] = [ + 1_000_000_000_000_000_000_000, + 3_000_000_000_000_000_000_000, + 5_000_000_000_000_000_000_000, + ]; + + let d_before = calculate_d::(&balances, amp).unwrap(); + let result = calculate_out_given_in_with_fee::( + &balances, + 1, + 2, + 1_000_000_000_000_000_000, + amp, + Permill::from_percent(0), + ); + let updated_reserves = [ + balances[0], + balances[1] + 1_000_000_000_000_000_000, + balances[2] - result.unwrap().0, + ]; + let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_aftere >= d_before); + assert_eq!(result.unwrap(), (1_000_079_930_281_397_674, 0)); + + let result = calculate_out_given_in_with_fee::( + &balances, + 2, + 1, + 1_000_000_000_000_000_000, + amp, + Permill::from_percent(0), + ); + assert_eq!(result.unwrap(), (999_919_974_816_739_669, 0)); + let updated_reserves = [ + balances[0], + balances[1] - result.unwrap().0, + balances[2] + 1_000_000_000_000_000_000, + ]; + let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_aftere >= d_before); +} + +#[test] +fn test_compare_precision_results_02() { + let amp = 1000_u128; + + let balances: [Balance; 3] = [1_000_000_000, 3_000_000_000, 5_000_000_000_000_000_000_000]; + + let d_before = calculate_d::(&balances, amp).unwrap(); + let result = calculate_out_given_in_with_fee::( + &balances, + 1, + 2, + 1_000_000, + amp, + Permill::from_percent(0), + ); + let updated_reserves = [balances[0], balances[1] + 1_000_000, balances[2] - result.unwrap().0]; + let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_aftere >= d_before); + assert_eq!(result.unwrap(), (833_117_894_058_679_760, 0)); + + let result = calculate_out_given_in_with_fee::( + &balances, + 2, + 1, + 1_000_000_000_000_000_000, + amp, + Permill::from_percent(0), + ); + assert_eq!(result.unwrap(), (1_187_653 + 11996, 0)); + let updated_reserves = [ + balances[0], + balances[1] - result.unwrap().0, + balances[2] + 1_000_000_000_000_000_000, + ]; + let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_aftere >= d_before); +} From 95f1b2e4db072ce576c94b6517196feea302feb4 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 12 Jul 2023 09:47:50 +0200 Subject: [PATCH 2/3] additional comparison tests --- math/src/stableswap/tests/multi_assets.rs | 84 +++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/math/src/stableswap/tests/multi_assets.rs b/math/src/stableswap/tests/multi_assets.rs index 616253d10..81da6415f 100644 --- a/math/src/stableswap/tests/multi_assets.rs +++ b/math/src/stableswap/tests/multi_assets.rs @@ -539,3 +539,87 @@ fn test_compare_precision_results_02() { let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); assert!(d_aftere >= d_before); } + +#[test] +fn test_compare_precision_results_03() { + let amp = 1000_u128; + + let balances: [Balance; 3] = [ + 1_000_000_000_000_000_000_000, + 3_000_000_000_000_000_000_000, + 5_000_000_000_000_000_000_000, + ]; + + let d_before = calculate_d::(&balances, amp).unwrap(); + let result = calculate_out_given_in_with_fee::( + &balances, + 1, + 2, + 1_000_000_000_000_000_000, + amp, + Permill::from_percent(0), + ); + let updated_reserves = [ + balances[0], + balances[1] + 1_000_000_000_000_000_000, + balances[2] - result.unwrap().0, + ]; + let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_aftere >= d_before); + assert_eq!(result.unwrap(), (1_000_079_930_281_397_674, 0)); + + let result = calculate_in_given_out_with_fee::( + &balances, + 1, + 2, + 1_000_079_930_281_397_674, + amp, + Permill::from_percent(0), + ); + assert_eq!(result.unwrap(), (1000000000000000000, 0)); + let updated_reserves = [ + balances[0], + balances[1] + result.unwrap().0, + balances[2] - 1_000_079_930_281_397_674, + ]; + let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_aftere >= d_before); +} + +#[test] +fn test_compare_precision_results_04() { + let amp = 1000_u128; + + let balances: [Balance; 3] = [1_000_000_000, 3_000_000_000, 5_000_000_000_000_000_000_000]; + + let d_before = calculate_d::(&balances, amp).unwrap(); + let result = calculate_out_given_in_with_fee::( + &balances, + 1, + 2, + 1_000_000, + amp, + Permill::from_percent(0), + ); + let updated_reserves = [balances[0], balances[1] + 1_000_000, balances[2] - result.unwrap().0]; + let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_aftere >= d_before); + assert_eq!(result.unwrap(), (833_117_894_058_679_760, 0)); + + let result = calculate_in_given_out_with_fee::( + &balances, + 1, + 2, + 833_117_894_058_679_760, + amp, + Permill::from_percent(0), + ); + assert_eq!(result.unwrap(), (1000001, 0)); + let updated_reserves = [ + balances[0], + balances[1] + result.unwrap().0, + balances[2] - 833_117_894_058_679_760, + ]; + let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_aftere >= d_before); +} From 484ad40d857bddad8e59da65834e0702e7f70c95 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 28 Jul 2023 13:06:56 +0200 Subject: [PATCH 3/3] review comments --- Cargo.lock | 2 +- math/Cargo.toml | 2 +- math/src/stableswap/tests/multi_assets.rs | 68 ++++++++++++----------- 3 files changed, 38 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62e192956..77bd9f06b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "hydra-dx-math" -version = "7.4.3" +version = "7.4.4" dependencies = [ "approx", "criterion", diff --git a/math/Cargo.toml b/math/Cargo.toml index c6005ee41..bb0d25c17 100644 --- a/math/Cargo.toml +++ b/math/Cargo.toml @@ -6,7 +6,7 @@ license = 'Apache-2.0' name = "hydra-dx-math" description = "A collection of utilities to make performing liquidity pool calculations more convenient." repository = 'https://github.com/galacticcouncil/hydradx-math' -version = "7.4.3" +version = "7.4.4" [dependencies] primitive-types = {default-features = false, version = '0.12.0'} diff --git a/math/src/stableswap/tests/multi_assets.rs b/math/src/stableswap/tests/multi_assets.rs index 81da6415f..a7a40aabc 100644 --- a/math/src/stableswap/tests/multi_assets.rs +++ b/math/src/stableswap/tests/multi_assets.rs @@ -480,26 +480,27 @@ fn test_compare_precision_results_01() { balances[1] + 1_000_000_000_000_000_000, balances[2] - result.unwrap().0, ]; - let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); - assert!(d_aftere >= d_before); + let d_after = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_after >= d_before); assert_eq!(result.unwrap(), (1_000_079_930_281_397_674, 0)); - let result = calculate_out_given_in_with_fee::( + let (amount_out, fee) = calculate_out_given_in_with_fee::( &balances, 2, 1, 1_000_000_000_000_000_000, amp, Permill::from_percent(0), - ); - assert_eq!(result.unwrap(), (999_919_974_816_739_669, 0)); + ) + .unwrap(); + assert_eq!((amount_out, fee), (999_919_974_816_739_669, 0)); let updated_reserves = [ balances[0], - balances[1] - result.unwrap().0, + balances[1] - amount_out, balances[2] + 1_000_000_000_000_000_000, ]; - let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); - assert!(d_aftere >= d_before); + let d_after = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_after >= d_before); } #[test] @@ -518,26 +519,27 @@ fn test_compare_precision_results_02() { Permill::from_percent(0), ); let updated_reserves = [balances[0], balances[1] + 1_000_000, balances[2] - result.unwrap().0]; - let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); - assert!(d_aftere >= d_before); + let d_after = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_after >= d_before); assert_eq!(result.unwrap(), (833_117_894_058_679_760, 0)); - let result = calculate_out_given_in_with_fee::( + let (amount_out, fee) = calculate_out_given_in_with_fee::( &balances, 2, 1, 1_000_000_000_000_000_000, amp, Permill::from_percent(0), - ); - assert_eq!(result.unwrap(), (1_187_653 + 11996, 0)); + ) + .unwrap(); + assert_eq!((amount_out, fee), (1_187_653 + 11996, 0)); let updated_reserves = [ balances[0], - balances[1] - result.unwrap().0, + balances[1] - amount_out, balances[2] + 1_000_000_000_000_000_000, ]; - let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); - assert!(d_aftere >= d_before); + let d_after = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_after >= d_before); } #[test] @@ -564,26 +566,27 @@ fn test_compare_precision_results_03() { balances[1] + 1_000_000_000_000_000_000, balances[2] - result.unwrap().0, ]; - let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); - assert!(d_aftere >= d_before); + let d_after = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_after >= d_before); assert_eq!(result.unwrap(), (1_000_079_930_281_397_674, 0)); - let result = calculate_in_given_out_with_fee::( + let (amount_in, fee) = calculate_in_given_out_with_fee::( &balances, 1, 2, 1_000_079_930_281_397_674, amp, Permill::from_percent(0), - ); - assert_eq!(result.unwrap(), (1000000000000000000, 0)); + ) + .unwrap(); + assert_eq!((amount_in, fee), (1000000000000000000, 0)); let updated_reserves = [ balances[0], - balances[1] + result.unwrap().0, + balances[1] + amount_in, balances[2] - 1_000_079_930_281_397_674, ]; - let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); - assert!(d_aftere >= d_before); + let d_after = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_after >= d_before); } #[test] @@ -602,24 +605,25 @@ fn test_compare_precision_results_04() { Permill::from_percent(0), ); let updated_reserves = [balances[0], balances[1] + 1_000_000, balances[2] - result.unwrap().0]; - let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); - assert!(d_aftere >= d_before); + let d_after = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_after >= d_before); assert_eq!(result.unwrap(), (833_117_894_058_679_760, 0)); - let result = calculate_in_given_out_with_fee::( + let (amount_in, fee) = calculate_in_given_out_with_fee::( &balances, 1, 2, 833_117_894_058_679_760, amp, Permill::from_percent(0), - ); - assert_eq!(result.unwrap(), (1000001, 0)); + ) + .unwrap(); + assert_eq!((amount_in, fee), (1000001, 0)); let updated_reserves = [ balances[0], - balances[1] + result.unwrap().0, + balances[1] + amount_in, balances[2] - 833_117_894_058_679_760, ]; - let d_aftere = calculate_d::(&updated_reserves, amp).unwrap(); - assert!(d_aftere >= d_before); + let d_after = calculate_d::(&updated_reserves, amp).unwrap(); + assert!(d_after >= d_before); }