From 4d96dc49d0678435cad7836a98bd08a78419eea6 Mon Sep 17 00:00:00 2001 From: Martin Hloska Date: Sat, 2 Mar 2024 23:39:32 +0100 Subject: [PATCH 1/2] stableswap dont allow same assets trades --- Cargo.lock | 4 +- pallets/stableswap/Cargo.toml | 2 +- pallets/stableswap/src/lib.rs | 4 ++ pallets/stableswap/src/tests/trades.rs | 86 ++++++++++++++++++++++++++ runtime/hydradx/Cargo.toml | 2 +- runtime/hydradx/src/lib.rs | 2 +- 6 files changed, 95 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 147584418..023248904 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4621,7 +4621,7 @@ dependencies = [ [[package]] name = "hydradx-runtime" -version = "219.0.0" +version = "220.0.0" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", @@ -8417,7 +8417,7 @@ dependencies = [ [[package]] name = "pallet-stableswap" -version = "3.4.4" +version = "3.5.0" dependencies = [ "bitflags 1.3.2", "frame-benchmarking", diff --git a/pallets/stableswap/Cargo.toml b/pallets/stableswap/Cargo.toml index fda85f6b9..a49599419 100644 --- a/pallets/stableswap/Cargo.toml +++ b/pallets/stableswap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'pallet-stableswap' -version = '3.4.4' +version = '3.5.0' description = 'AMM for correlated assets' authors = ['GalacticCouncil'] edition = '2021' diff --git a/pallets/stableswap/src/lib.rs b/pallets/stableswap/src/lib.rs index a11dc2a54..65b336311 100644 --- a/pallets/stableswap/src/lib.rs +++ b/pallets/stableswap/src/lib.rs @@ -724,6 +724,8 @@ pub mod pallet { ) -> DispatchResult { let who = ensure_signed(origin)?; + ensure!(asset_in != asset_out, Error::::NotAllowed); + ensure!( Self::is_asset_allowed(pool_id, asset_in, Tradability::SELL) && Self::is_asset_allowed(pool_id, asset_out, Tradability::BUY), @@ -794,6 +796,8 @@ pub mod pallet { ) -> DispatchResult { let who = ensure_signed(origin)?; + ensure!(asset_in != asset_out, Error::::NotAllowed); + ensure!( Self::is_asset_allowed(pool_id, asset_in, Tradability::SELL) && Self::is_asset_allowed(pool_id, asset_out, Tradability::BUY), diff --git a/pallets/stableswap/src/tests/trades.rs b/pallets/stableswap/src/tests/trades.rs index 52fed36be..d27b7fd44 100644 --- a/pallets/stableswap/src/tests/trades.rs +++ b/pallets/stableswap/src/tests/trades.rs @@ -666,3 +666,89 @@ fn buy_should_work_when_assets_have_different_decimals() { assert_balance!(pool_account, asset_b, to_precision!(70, dec_b)); }); } + +#[test] +fn sell_should_fail_when_trading_same_assets() { + let asset_a: AssetId = 1; + let asset_b: AssetId = 2; + 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, 12) + .with_registered_asset("two".as_bytes().to_vec(), 2, 12) + .with_pool( + ALICE, + PoolInfo:: { + assets: vec![asset_a, asset_b].try_into().unwrap(), + initial_amplification: NonZeroU16::new(100).unwrap(), + final_amplification: NonZeroU16::new(100).unwrap(), + initial_block: 0, + final_block: 0, + fee: Permill::from_percent(0), + }, + InitialLiquidity { + account: ALICE, + assets: vec![ + AssetAmount::new(asset_a, 100 * ONE), + AssetAmount::new(asset_b, 100 * ONE), + ], + }, + ) + .build() + .execute_with(|| { + let pool_id = get_pool_id_at(0); + assert_noop!( + Stableswap::sell( + RuntimeOrigin::signed(BOB), + pool_id, + asset_a, + asset_a, + 30 * ONE, + 25 * ONE, + ), + Error::::NotAllowed + ); + }); +} + +#[test] +fn buy_should_fail_when_trading_same_assets() { + let asset_a: AssetId = 1; + let asset_b: AssetId = 2; + 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, 12) + .with_registered_asset("two".as_bytes().to_vec(), 2, 12) + .with_pool( + ALICE, + PoolInfo:: { + assets: vec![asset_a, asset_b].try_into().unwrap(), + initial_amplification: NonZeroU16::new(100).unwrap(), + final_amplification: NonZeroU16::new(100).unwrap(), + initial_block: 0, + final_block: 0, + fee: Permill::from_percent(0), + }, + InitialLiquidity { + account: ALICE, + assets: vec![ + AssetAmount::new(asset_a, 100 * ONE), + AssetAmount::new(asset_b, 100 * ONE), + ], + }, + ) + .build() + .execute_with(|| { + let pool_id = get_pool_id_at(0); + assert_noop!( + Stableswap::buy( + RuntimeOrigin::signed(BOB), + pool_id, + asset_a, + asset_a, + 30 * ONE, + 25 * ONE, + ), + Error::::NotAllowed + ); + }); +} diff --git a/runtime/hydradx/Cargo.toml b/runtime/hydradx/Cargo.toml index cae647349..e82095ada 100644 --- a/runtime/hydradx/Cargo.toml +++ b/runtime/hydradx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hydradx-runtime" -version = "219.0.0" +version = "220.0.0" authors = ["GalacticCouncil"] edition = "2021" license = "Apache 2.0" diff --git a/runtime/hydradx/src/lib.rs b/runtime/hydradx/src/lib.rs index 12c71594c..858d6ef36 100644 --- a/runtime/hydradx/src/lib.rs +++ b/runtime/hydradx/src/lib.rs @@ -107,7 +107,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("hydradx"), impl_name: create_runtime_str!("hydradx"), authoring_version: 1, - spec_version: 219, + spec_version: 220, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 50bccc09522d1d072ed815f2afdbc8385301ec0e Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 4 Mar 2024 15:51:48 +0100 Subject: [PATCH 2/2] ensure ourter and math --- Cargo.lock | 4 ++-- math/Cargo.toml | 2 +- math/src/stableswap/math.rs | 12 ++++++++++++ pallets/route-executor/Cargo.toml | 2 +- pallets/route-executor/src/lib.rs | 6 ++++++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 023248904..232b7e828 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4461,7 +4461,7 @@ dependencies = [ [[package]] name = "hydra-dx-math" -version = "8.0.0" +version = "8.0.1" dependencies = [ "approx", "criterion", @@ -8318,7 +8318,7 @@ dependencies = [ [[package]] name = "pallet-route-executor" -version = "2.0.2" +version = "2.0.3" dependencies = [ "frame-benchmarking", "frame-support", diff --git a/math/Cargo.toml b/math/Cargo.toml index fe2bda60e..92c6467ca 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 = "8.0.0" +version = "8.0.1" [dependencies] primitive-types = {default-features = false, version = '0.12.0'} diff --git a/math/src/stableswap/math.rs b/math/src/stableswap/math.rs index ba001673f..0dc33b3c5 100644 --- a/math/src/stableswap/math.rs +++ b/math/src/stableswap/math.rs @@ -27,6 +27,9 @@ pub fn calculate_out_given_in( amount_in: Balance, amplification: Balance, ) -> Option { + if idx_in == idx_out { + return None; + } if idx_in >= initial_reserves.len() || idx_out >= initial_reserves.len() { return None; } @@ -58,6 +61,9 @@ pub fn calculate_in_given_out( amount_out: Balance, amplification: Balance, ) -> Option { + if idx_in == idx_out { + return None; + } if idx_in >= initial_reserves.len() || idx_out >= initial_reserves.len() { return None; } @@ -88,6 +94,9 @@ pub fn calculate_out_given_in_with_fee( amplification: Balance, fee: Permill, ) -> Option<(Balance, Balance)> { + if idx_in == idx_out { + return None; + } let amount_out = calculate_out_given_in::(initial_reserves, idx_in, idx_out, amount_in, amplification)?; let fee_amount = calculate_fee_amount(amount_out, fee, Rounding::Down); let amount_out = amount_out.checked_sub(fee_amount)?; @@ -103,6 +112,9 @@ pub fn calculate_in_given_out_with_fee( amplification: Balance, fee: Permill, ) -> Option<(Balance, Balance)> { + if idx_in == idx_out { + return None; + } let amount_in = calculate_in_given_out::(initial_reserves, idx_in, idx_out, amount_out, amplification)?; let fee_amount = calculate_fee_amount(amount_in, fee, Rounding::Up); let amount_in = amount_in.checked_add(fee_amount)?; diff --git a/pallets/route-executor/Cargo.toml b/pallets/route-executor/Cargo.toml index 986f570db..5abde9b34 100644 --- a/pallets/route-executor/Cargo.toml +++ b/pallets/route-executor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'pallet-route-executor' -version = '2.0.2' +version = '2.0.3' description = 'A pallet to execute a route containing a sequence of trades' authors = ['GalacticCouncil'] edition = '2021' diff --git a/pallets/route-executor/src/lib.rs b/pallets/route-executor/src/lib.rs index cc6fdacc9..a25f7fd49 100644 --- a/pallets/route-executor/src/lib.rs +++ b/pallets/route-executor/src/lib.rs @@ -143,6 +143,8 @@ pub mod pallet { RouteUpdateIsNotSuccessful, ///Insufficient asset is not supported for on chain routing InsufficientAssetNotSupported, + /// Trading same assets is not allowed. + NotAllowed, } /// Storing routes for asset pairs @@ -182,6 +184,9 @@ pub mod pallet { route: Vec>, ) -> DispatchResult { let who = ensure_signed(origin.clone())?; + + ensure!(asset_in != asset_out, Error::::NotAllowed); + Self::ensure_route_size(route.len())?; let asset_pair = AssetPair::new(asset_in, asset_out); @@ -251,6 +256,7 @@ pub mod pallet { max_amount_in: T::Balance, route: Vec>, ) -> DispatchResult { + ensure!(asset_in != asset_out, Error::::NotAllowed); Self::ensure_route_size(route.len())?; let asset_pair = AssetPair::new(asset_in, asset_out);