Skip to content

Commit 0e3c392

Browse files
[stable2503] Backport #7952 (#8082)
Backport #7952 into `stable2503` from raymondkfcheung. See the [documentation](https://github.com/paritytech/polkadot-sdk/blob/master/docs/BACKPORT.md) on how to use this bot. <!-- # To be used by other automation, do not modify: original-pr-number: #${pull_number} --> --------- Co-authored-by: Raymond Cheung <[email protected]>
1 parent bc61fd4 commit 0e3c392

7 files changed

Lines changed: 292 additions & 72 deletions

File tree

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// Copyright (C) Parity Technologies (UK) Ltd.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
use crate::{
17+
create_pool_with_wnd_on,
18+
imports::{
19+
asset_hub_westend_runtime::{ExistentialDeposit, Runtime},
20+
*,
21+
},
22+
};
23+
use asset_hub_westend_runtime::{
24+
xcm_config::WestendLocation, Balances, ForeignAssets, PolkadotXcm, RuntimeOrigin,
25+
};
26+
use emulated_integration_tests_common::{accounts::ALICE, xcm_emulator::TestExt};
27+
use frame_support::{
28+
assert_err_ignore_postinfo, assert_ok,
29+
traits::fungible::{Inspect, Mutate},
30+
};
31+
use parachains_common::{AccountId, Balance};
32+
use sp_tracing::capture_test_logs;
33+
use std::convert::Into;
34+
use xcm::latest::{Assets, Location, Xcm};
35+
36+
const UNITS: Balance = 1_000_000_000;
37+
38+
#[test]
39+
fn exchange_asset_success() {
40+
test_exchange_asset(true, 500 * UNITS, 665 * UNITS, true);
41+
}
42+
43+
#[test]
44+
fn exchange_asset_insufficient_liquidity() {
45+
let log_capture = capture_test_logs!({
46+
test_exchange_asset(true, 1_000 * UNITS, 2_000 * UNITS, false);
47+
});
48+
assert!(log_capture.contains("NoDeal"));
49+
}
50+
51+
#[test]
52+
fn exchange_asset_insufficient_balance() {
53+
let log_capture = capture_test_logs!({
54+
test_exchange_asset(true, 5_000 * UNITS, 1_665 * UNITS, false);
55+
});
56+
assert!(log_capture.contains("Funds are unavailable"));
57+
}
58+
59+
#[test]
60+
fn exchange_asset_pool_not_created() {
61+
test_exchange_asset(false, 500 * UNITS, 665 * UNITS, false);
62+
}
63+
64+
fn test_exchange_asset(
65+
create_pool: bool,
66+
give_amount: Balance,
67+
want_amount: Balance,
68+
should_succeed: bool,
69+
) {
70+
let alice: AccountId = Westend::account_id_of(ALICE);
71+
let native_asset_location = WestendLocation::get();
72+
let native_asset_id = AssetId(native_asset_location.clone());
73+
let origin = RuntimeOrigin::signed(alice.clone());
74+
let asset_location = Location::new(1, [Parachain(2001)]);
75+
let asset_id = AssetId(asset_location.clone());
76+
77+
// Setup initial state
78+
AssetHubWestend::execute_with(|| {
79+
assert_ok!(<Balances as Mutate<_>>::mint_into(
80+
&alice,
81+
ExistentialDeposit::get() + (1_000 * UNITS)
82+
));
83+
84+
assert_ok!(ForeignAssets::force_create(
85+
RuntimeOrigin::root(),
86+
asset_location.clone().into(),
87+
alice.clone().into(),
88+
true,
89+
1
90+
));
91+
});
92+
93+
if create_pool {
94+
create_pool_with_wnd_on!(AssetHubWestend, asset_location.clone(), true, alice.clone());
95+
}
96+
97+
// Execute and verify swap
98+
AssetHubWestend::execute_with(|| {
99+
let foreign_balance_before = ForeignAssets::balance(asset_location.clone(), &alice);
100+
let wnd_balance_before = Balances::total_balance(&alice);
101+
102+
let give: Assets = (native_asset_id, give_amount).into();
103+
let want: Assets = (asset_id, want_amount).into();
104+
let xcm = Xcm(vec![
105+
WithdrawAsset(give.clone().into()),
106+
ExchangeAsset { give: give.into(), want: want.into(), maximal: true },
107+
DepositAsset { assets: Wild(All), beneficiary: alice.clone().into() },
108+
]);
109+
110+
let result = PolkadotXcm::execute(origin, bx!(xcm::VersionedXcm::from(xcm)), Weight::MAX);
111+
112+
let foreign_balance_after = ForeignAssets::balance(asset_location, &alice);
113+
let wnd_balance_after = Balances::total_balance(&alice);
114+
115+
if should_succeed {
116+
assert_ok!(result);
117+
assert!(
118+
foreign_balance_after >= foreign_balance_before + want_amount,
119+
"Expected foreign balance to increase by at least {want_amount} units, got {foreign_balance_after} from {foreign_balance_before}"
120+
);
121+
assert_eq!(
122+
wnd_balance_after, wnd_balance_before - give_amount,
123+
"Expected WND balance to decrease by {give_amount} units, got {wnd_balance_after} from {wnd_balance_before}"
124+
);
125+
} else {
126+
assert_err_ignore_postinfo!(
127+
result,
128+
pallet_xcm::Error::<Runtime>::LocalExecutionIncomplete
129+
);
130+
assert_eq!(
131+
foreign_balance_after, foreign_balance_before,
132+
"Foreign balance changed unexpectedly: got {foreign_balance_after}, expected {foreign_balance_before}"
133+
);
134+
assert_eq!(
135+
wnd_balance_after, wnd_balance_before,
136+
"WND balance changed unexpectedly: got {wnd_balance_after}, expected {wnd_balance_before}"
137+
);
138+
}
139+
});
140+
}

cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// limitations under the License.
1515

1616
mod claim_assets;
17+
mod exchange_asset;
1718
mod fellowship_treasury;
1819
mod hybrid_transfers;
1920
mod reserve_transfer;

cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2162,7 +2162,54 @@ impl_runtime_apis! {
21622162
}
21632163

21642164
fn worst_case_asset_exchange() -> Result<(XcmAssets, XcmAssets), BenchmarkError> {
2165-
Err(BenchmarkError::Skip)
2165+
let native_asset_location = WestendLocation::get();
2166+
let native_asset_id = AssetId(native_asset_location.clone());
2167+
let (account, _) = pallet_xcm_benchmarks::account_and_location::<Runtime>(1);
2168+
let origin = RuntimeOrigin::signed(account.clone());
2169+
let asset_location = Location::new(1, [Parachain(2001)]);
2170+
let asset_id = AssetId(asset_location.clone());
2171+
2172+
assert_ok!(<Balances as fungible::Mutate<_>>::mint_into(
2173+
&account,
2174+
ExistentialDeposit::get() + (1_000 * UNITS)
2175+
));
2176+
2177+
assert_ok!(ForeignAssets::force_create(
2178+
RuntimeOrigin::root(),
2179+
asset_location.clone().into(),
2180+
account.clone().into(),
2181+
true,
2182+
1,
2183+
));
2184+
2185+
assert_ok!(ForeignAssets::mint(
2186+
origin.clone(),
2187+
asset_location.clone().into(),
2188+
account.clone().into(),
2189+
3_000 * UNITS,
2190+
));
2191+
2192+
assert_ok!(AssetConversion::create_pool(
2193+
origin.clone(),
2194+
native_asset_location.clone().into(),
2195+
asset_location.clone().into(),
2196+
));
2197+
2198+
assert_ok!(AssetConversion::add_liquidity(
2199+
origin,
2200+
native_asset_location.into(),
2201+
asset_location.into(),
2202+
1_000 * UNITS,
2203+
2_000 * UNITS,
2204+
1,
2205+
1,
2206+
account.into(),
2207+
));
2208+
2209+
let give_assets: XcmAssets = (native_asset_id, 500 * UNITS).into();
2210+
let receive_assets: XcmAssets = (asset_id, 660 * UNITS).into();
2211+
2212+
Ok((give_assets, receive_assets))
21662213
}
21672214

21682215
fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {

cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,11 @@ impl<Call> XcmWeightInfo<Call> for AssetHubWestendXcmWeight<Call> {
124124
fn deposit_reserve_asset(assets: &AssetFilter, _dest: &Location, _xcm: &Xcm<()>) -> Weight {
125125
assets.weigh_assets(XcmFungibleWeight::<Runtime>::deposit_reserve_asset())
126126
}
127-
fn exchange_asset(_give: &AssetFilter, _receive: &Assets, _maximal: &bool) -> Weight {
128-
XcmFungibleWeight::<Runtime>::exchange_asset()
127+
fn exchange_asset(give: &AssetFilter, receive: &Assets, _maximal: &bool) -> Weight {
128+
let base_weight = XcmGeneric::<Runtime>::exchange_asset();
129+
let give_weight = give.weigh_assets(base_weight);
130+
let receive_weight = receive.weigh_assets(base_weight);
131+
give_weight.max(receive_weight)
129132
}
130133
fn initiate_reserve_withdraw(
131134
assets: &AssetFilter,

0 commit comments

Comments
 (0)