|
| 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 | +} |
0 commit comments