Skip to content

Commit

Permalink
Merge pull request #636 from galacticcouncil/fix/stableswap-asset-order
Browse files Browse the repository at this point in the history
fix: stableswap asset order
  • Loading branch information
enthusiastmartin authored Jul 7, 2023
2 parents 34e5951 + b5e5826 commit ed714e5
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 6 deletions.
4 changes: 2 additions & 2 deletions 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.1"
version = "7.4.2"

[dependencies]
primitive-types = {default-features = false, version = '0.12.0'}
Expand Down
108 changes: 108 additions & 0 deletions math/src/stableswap/tests/multi_assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,111 @@ fn calculate_withdraw_should_return_correct_amount_when_removing_provided_shares

assert_eq!(result, (4993u128, 0u128));
}

#[test]
fn calculate_out_given_in_with_fee_should_work_when_reserves_have_different_precision() {
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 result = calculate_out_given_in_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&balances,
1,
2,
1_000_000,
amp,
Permill::from_percent(1),
);
assert_eq!(result.unwrap(), (824_786_715_118_092_963, 8_331_178_940_586_797));

let result = calculate_out_given_in_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&balances,
2,
1,
1_000_000_000_000_000_000,
amp,
Permill::from_percent(1),
);
assert_eq!(result.unwrap(), (1_187_653, 11996));
}

#[test]
fn calculate_out_given_in_with_zero_fee_should_work_when_reserves_have_different_precision() {
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 result = calculate_out_given_in_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&balances,
1,
2,
1_000_000,
amp,
Permill::from_percent(0),
);
assert_eq!(result.unwrap(), (824_786_715_118_092_963 + 8_331_178_940_586_797, 0));

let result = 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),
);
assert_eq!(result.unwrap(), (1_187_653 + 11996, 0));
}

#[test]
fn calculate_in_given_out_with_fee_should_work_when_reserves_have_different_precision() {
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 result = calculate_in_given_out_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&balances,
1,
2,
1_000_000_000_000_000_000,
amp,
Permill::from_percent(1),
);
assert_eq!(result.unwrap(), (1212376, 12004));

let result = calculate_in_given_out_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&balances,
2,
1,
1_000_000,
amp,
Permill::from_percent(1),
);
assert_eq!(result.unwrap(), (841869902748480839, 8335345571767138));
}

#[test]
fn calculate_in_given_out_with_zero_fee_should_work_when_reserves_have_different_precision() {
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 result = calculate_in_given_out_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&balances,
1,
2,
1_000_000_000_000_000_000,
amp,
Permill::from_percent(0),
);
assert_eq!(result.unwrap(), (1212376 - 12004, 0));

let result = calculate_in_given_out_with_fee::<D_ITERATIONS, Y_ITERATIONS>(
&balances,
2,
1,
1_000_000,
amp,
Permill::from_percent(0),
);
assert_eq!(result.unwrap(), (841869902748480839 - 8335345571767138, 0));
}
2 changes: 1 addition & 1 deletion pallets/stableswap/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = 'pallet-stableswap'
version = '2.1.0'
version = '2.1.1'
description = 'AMM for correlated assets'
authors = ['GalacticCouncil']
edition = '2021'
Expand Down
3 changes: 1 addition & 2 deletions pallets/stableswap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,6 @@ pub mod pallet {
ensure!(amount_out >= min_buy_amount, Error::<T>::BuyLimitNotReached);

let pool_account = Self::pool_account(pool_id);

T::Currency::transfer(asset_in, &who, &pool_account, amount_in)?;
T::Currency::transfer(asset_out, &pool_account, &who, amount_out)?;

Expand Down Expand Up @@ -746,8 +745,8 @@ pub mod pallet {
impl<T: Config> Pallet<T> {
fn calculate_out_amount(
pool_id: T::AssetId,
asset_out: T::AssetId,
asset_in: T::AssetId,
asset_out: T::AssetId,
amount_in: Balance,
) -> Result<(Balance, Balance), DispatchError> {
let pool = Pools::<T>::get(pool_id).ok_or(Error::<T>::PoolNotFound)?;
Expand Down
138 changes: 138 additions & 0 deletions pallets/stableswap/src/tests/trades.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,3 +502,141 @@ fn buy_should_fail_when_insufficient_amount_is_provided() {
);
});
}

#[test]
fn sell_should_work_when_pool_have_asset_with_various_decimals() {
let asset_a: AssetId = 1;
let asset_b: AssetId = 2;
let asset_c: AssetId = 3;
ExtBuilder::default()
.with_endowed_accounts(vec![(BOB, 1, 200 * ONE), (ALICE, 1, 200 * ONE), (ALICE, 2, 200 * ONE)])
.with_registered_asset("one".as_bytes().to_vec(), 1)
.with_registered_asset("two".as_bytes().to_vec(), 2)
.with_registered_asset("three".as_bytes().to_vec(), 3)
.with_endowed_accounts(vec![
(BOB, asset_c, ONE * 1_000_000),
(ALICE, asset_a, 2000 * ONE),
(ALICE, asset_b, 4000 * ONE),
(ALICE, asset_c, 10000 * ONE * 1_000_000),
])
.with_pool(
ALICE,
PoolInfo::<AssetId, u64> {
assets: vec![asset_a, asset_b, asset_c].try_into().unwrap(),
initial_amplification: NonZeroU16::new(1000).unwrap(),
final_amplification: NonZeroU16::new(1000).unwrap(),
initial_block: 0,
trade_fee: Permill::from_percent(0),
withdraw_fee: Permill::from_percent(0),
final_block: 0,
},
InitialLiquidity {
account: ALICE,
assets: vec![
AssetBalance {
asset_id: asset_a,
amount: 1_000_000_000,
},
AssetBalance {
asset_id: asset_b,
amount: 3_000_000_000,
},
AssetBalance {
asset_id: asset_c,
amount: 5000 * ONE * 1_000_000,
},
],
},
)
.build()
.execute_with(|| {
let pool_id = get_pool_id_at(0);

assert_ok!(Stableswap::sell(
RuntimeOrigin::signed(BOB),
pool_id,
asset_c,
asset_b,
ONE * 1_000_000,
0,
));

let expected = 1_199_649;

let pool_account = pool_account(pool_id);

assert_balance!(BOB, asset_c, 0);
assert_balance!(BOB, asset_b, expected);
assert_balance!(pool_account, asset_c, 5_001_000_000_000_000_000_000);
assert_balance!(pool_account, asset_b, 3_000_000_000 - expected);
});
}

#[test]
fn buy_should_work_when_pool_have_asset_with_various_decimals() {
let asset_a: AssetId = 1;
let asset_b: AssetId = 2;
let asset_c: AssetId = 3;
ExtBuilder::default()
.with_endowed_accounts(vec![(BOB, 1, 200 * ONE), (ALICE, 1, 200 * ONE), (ALICE, 2, 200 * ONE)])
.with_registered_asset("one".as_bytes().to_vec(), 1)
.with_registered_asset("two".as_bytes().to_vec(), 2)
.with_registered_asset("three".as_bytes().to_vec(), 3)
.with_endowed_accounts(vec![
(BOB, asset_c, ONE * 1_000_000),
(ALICE, asset_a, 2000 * ONE),
(ALICE, asset_b, 4000 * ONE),
(ALICE, asset_c, 10000 * ONE * 1_000_000),
])
.with_pool(
ALICE,
PoolInfo::<AssetId, u64> {
assets: vec![asset_a, asset_b, asset_c].try_into().unwrap(),
initial_amplification: NonZeroU16::new(1000).unwrap(),
final_amplification: NonZeroU16::new(1000).unwrap(),
initial_block: 0,
trade_fee: Permill::from_percent(0),
withdraw_fee: Permill::from_percent(0),
final_block: 0,
},
InitialLiquidity {
account: ALICE,
assets: vec![
AssetBalance {
asset_id: asset_a,
amount: 1_000_000_000,
},
AssetBalance {
asset_id: asset_b,
amount: 3_000_000_000,
},
AssetBalance {
asset_id: asset_c,
amount: 5000 * ONE * 1_000_000,
},
],
},
)
.build()
.execute_with(|| {
let pool_id = get_pool_id_at(0);

assert_ok!(Stableswap::buy(
RuntimeOrigin::signed(BOB),
pool_id,
asset_b,
asset_c,
1_199_649,
2 * ONE * 1_000_000,
));

let expected = 1_199_649;

let pool_account = pool_account(pool_id);

assert_balance!(BOB, asset_c, 1_174_293_340_450);
assert_balance!(BOB, asset_b, expected);
assert_balance!(pool_account, asset_c, 5000999998825706659550);
assert_balance!(pool_account, asset_b, 3_000_000_000 - expected);
});
}

0 comments on commit ed714e5

Please sign in to comment.