Skip to content

Commit

Permalink
Merge pull request #637 from galacticcouncil/stableswap-invariants
Browse files Browse the repository at this point in the history
test: stableswap - add additional invariants tests
  • Loading branch information
enthusiastmartin authored Jul 31, 2023
2 parents 6173a8b + ca7d4c4 commit 0a1fc28
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion math/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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'}
Expand Down
69 changes: 69 additions & 0 deletions math/src/stableswap/tests/invariants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,72 @@ proptest! {
assert!(y >= reserve_a);
}
}

fn decimals() -> impl Strategy<Value = u32> {
prop_oneof![Just(6), Just(8), Just(10), Just(12), Just(18)]
}

fn reserve(max: Balance, precision: u32) -> impl Strategy<Value = Balance> {
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<Balance> {
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<Balance>, 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::<D_ITERATIONS>(&reserves, amp).unwrap();
let result = calculate_in_given_out::<D_ITERATIONS,Y_ITERATIONS>(&reserves, 0, 1, 10u128.pow(dec_1), amp);
if let Some(amount_in) = result {
let d1 = calculate_d::<D_ITERATIONS>(&[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::<D_ITERATIONS>(&reserves, amp).unwrap();
let result = calculate_out_given_in::<D_ITERATIONS,Y_ITERATIONS>(&reserves, 0, 1, 10u128.pow(dec_1), amp);
if let Some(amount_out) = result {
let d1 = calculate_d::<D_ITERATIONS>(&[reserves[0] + 10u128.pow(dec_1), reserves[1] - amount_out, reserves[2]], amp).unwrap();
assert!(d1 >= d0);
}
}
}
172 changes: 172 additions & 0 deletions math/src/stableswap/tests/multi_assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,3 +455,175 @@ 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::<D_ITERATIONS>(&balances, amp).unwrap();
let result = calculate_out_given_in_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&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_after = calculate_d::<D_ITERATIONS>(&updated_reserves, amp).unwrap();
assert!(d_after >= d_before);
assert_eq!(result.unwrap(), (1_000_079_930_281_397_674, 0));

let (amount_out, fee) = calculate_out_given_in_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&balances,
2,
1,
1_000_000_000_000_000_000,
amp,
Permill::from_percent(0),
)
.unwrap();
assert_eq!((amount_out, fee), (999_919_974_816_739_669, 0));
let updated_reserves = [
balances[0],
balances[1] - amount_out,
balances[2] + 1_000_000_000_000_000_000,
];
let d_after = calculate_d::<D_ITERATIONS>(&updated_reserves, amp).unwrap();
assert!(d_after >= 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::<D_ITERATIONS>(&balances, amp).unwrap();
let result = calculate_out_given_in_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&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_after = calculate_d::<D_ITERATIONS>(&updated_reserves, amp).unwrap();
assert!(d_after >= d_before);
assert_eq!(result.unwrap(), (833_117_894_058_679_760, 0));

let (amount_out, fee) = calculate_out_given_in_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&balances,
2,
1,
1_000_000_000_000_000_000,
amp,
Permill::from_percent(0),
)
.unwrap();
assert_eq!((amount_out, fee), (1_187_653 + 11996, 0));
let updated_reserves = [
balances[0],
balances[1] - amount_out,
balances[2] + 1_000_000_000_000_000_000,
];
let d_after = calculate_d::<D_ITERATIONS>(&updated_reserves, amp).unwrap();
assert!(d_after >= 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::<D_ITERATIONS>(&balances, amp).unwrap();
let result = calculate_out_given_in_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&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_after = calculate_d::<D_ITERATIONS>(&updated_reserves, amp).unwrap();
assert!(d_after >= d_before);
assert_eq!(result.unwrap(), (1_000_079_930_281_397_674, 0));

let (amount_in, fee) = calculate_in_given_out_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&balances,
1,
2,
1_000_079_930_281_397_674,
amp,
Permill::from_percent(0),
)
.unwrap();
assert_eq!((amount_in, fee), (1000000000000000000, 0));
let updated_reserves = [
balances[0],
balances[1] + amount_in,
balances[2] - 1_000_079_930_281_397_674,
];
let d_after = calculate_d::<D_ITERATIONS>(&updated_reserves, amp).unwrap();
assert!(d_after >= 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::<D_ITERATIONS>(&balances, amp).unwrap();
let result = calculate_out_given_in_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&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_after = calculate_d::<D_ITERATIONS>(&updated_reserves, amp).unwrap();
assert!(d_after >= d_before);
assert_eq!(result.unwrap(), (833_117_894_058_679_760, 0));

let (amount_in, fee) = calculate_in_given_out_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&balances,
1,
2,
833_117_894_058_679_760,
amp,
Permill::from_percent(0),
)
.unwrap();
assert_eq!((amount_in, fee), (1000001, 0));
let updated_reserves = [
balances[0],
balances[1] + amount_in,
balances[2] - 833_117_894_058_679_760,
];
let d_after = calculate_d::<D_ITERATIONS>(&updated_reserves, amp).unwrap();
assert!(d_after >= d_before);
}

0 comments on commit 0a1fc28

Please sign in to comment.