referrerpolicy=no-referrer-when-downgrade

staging_xcm_builder/
test_utils.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17// Shared test utilities and implementations for the XCM Builder.
18
19use alloc::vec::Vec;
20use frame_support::{
21	parameter_types,
22	traits::{Contains, CrateVersion, PalletInfoData, PalletsInfoAccess},
23};
24pub use xcm::latest::{prelude::*, Weight};
25use xcm_executor::traits::{ClaimAssets, DropAssets, VersionChangeNotifier};
26pub use xcm_executor::{
27	traits::{
28		AssetExchange, AssetLock, ConvertOrigin, Enact, LockError, OnResponse, TransactAsset,
29	},
30	AssetsInHolding, Config,
31};
32
33parameter_types! {
34	pub static SubscriptionRequests: Vec<(Location, Option<(QueryId, Weight)>)> = vec![];
35	pub static MaxAssetsIntoHolding: u32 = 4;
36}
37
38pub struct TestSubscriptionService;
39
40impl VersionChangeNotifier for TestSubscriptionService {
41	fn start(
42		location: &Location,
43		query_id: QueryId,
44		max_weight: Weight,
45		_context: &XcmContext,
46	) -> XcmResult {
47		let mut r = SubscriptionRequests::get();
48		r.push((location.clone(), Some((query_id, max_weight))));
49		SubscriptionRequests::set(r);
50		Ok(())
51	}
52	fn stop(location: &Location, _context: &XcmContext) -> XcmResult {
53		let mut r = SubscriptionRequests::get();
54		r.retain(|(l, _q)| l != location);
55		r.push((location.clone(), None));
56		SubscriptionRequests::set(r);
57		Ok(())
58	}
59	fn is_subscribed(location: &Location) -> bool {
60		let r = SubscriptionRequests::get();
61		r.iter().any(|(l, q)| l == location && q.is_some())
62	}
63}
64
65parameter_types! {
66	pub static TrappedAssets: Vec<(Location, Assets)> = vec![];
67}
68
69pub struct TestAssetTrap;
70
71impl DropAssets for TestAssetTrap {
72	fn drop_assets(origin: &Location, assets: AssetsInHolding, _context: &XcmContext) -> Weight {
73		let mut t: Vec<(Location, Assets)> = TrappedAssets::get();
74		t.push((origin.clone(), assets.into()));
75		TrappedAssets::set(t);
76		Weight::from_parts(5, 5)
77	}
78}
79
80impl ClaimAssets for TestAssetTrap {
81	fn claim_assets(
82		origin: &Location,
83		ticket: &Location,
84		what: &Assets,
85		_context: &XcmContext,
86	) -> bool {
87		let mut t: Vec<(Location, Assets)> = TrappedAssets::get();
88		if let (0, [GeneralIndex(i)]) = ticket.unpack() {
89			if let Some((l, a)) = t.get(*i as usize) {
90				if l == origin && a == what {
91					t.swap_remove(*i as usize);
92					TrappedAssets::set(t);
93					return true
94				}
95			}
96		}
97		false
98	}
99}
100
101pub struct TestAssetExchanger;
102
103impl AssetExchange for TestAssetExchanger {
104	fn exchange_asset(
105		_origin: Option<&Location>,
106		_give: AssetsInHolding,
107		want: &Assets,
108		_maximal: bool,
109	) -> Result<AssetsInHolding, AssetsInHolding> {
110		Ok(want.clone().into())
111	}
112
113	fn quote_exchange_price(give: &Assets, _want: &Assets, _maximal: bool) -> Option<Assets> {
114		Some(give.clone())
115	}
116}
117
118pub struct TestPalletsInfo;
119impl PalletsInfoAccess for TestPalletsInfo {
120	fn count() -> usize {
121		2
122	}
123	fn infos() -> Vec<PalletInfoData> {
124		vec![
125			PalletInfoData {
126				index: 0,
127				name: "System",
128				module_name: "pallet_system",
129				crate_version: CrateVersion { major: 1, minor: 10, patch: 1 },
130			},
131			PalletInfoData {
132				index: 1,
133				name: "Balances",
134				module_name: "pallet_balances",
135				crate_version: CrateVersion { major: 1, minor: 42, patch: 69 },
136			},
137		]
138	}
139}
140
141pub struct TestUniversalAliases;
142impl Contains<(Location, Junction)> for TestUniversalAliases {
143	fn contains(aliases: &(Location, Junction)) -> bool {
144		&aliases.0 == &Here.into_location() && &aliases.1 == &GlobalConsensus(ByGenesis([0; 32]))
145	}
146}
147
148parameter_types! {
149	pub static LockedAssets: Vec<(Location, Asset)> = vec![];
150}
151
152pub struct TestLockTicket(Location, Asset);
153impl Enact for TestLockTicket {
154	fn enact(self) -> Result<(), LockError> {
155		let mut locked_assets = LockedAssets::get();
156		locked_assets.push((self.0, self.1));
157		LockedAssets::set(locked_assets);
158		Ok(())
159	}
160}
161pub struct TestUnlockTicket(Location, Asset);
162impl Enact for TestUnlockTicket {
163	fn enact(self) -> Result<(), LockError> {
164		let mut locked_assets = LockedAssets::get();
165		if let Some((idx, _)) = locked_assets
166			.iter()
167			.enumerate()
168			.find(|(_, (origin, asset))| origin == &self.0 && asset == &self.1)
169		{
170			locked_assets.remove(idx);
171		}
172		LockedAssets::set(locked_assets);
173		Ok(())
174	}
175}
176pub struct TestReduceTicket;
177impl Enact for TestReduceTicket {
178	fn enact(self) -> Result<(), LockError> {
179		Ok(())
180	}
181}
182
183pub struct TestAssetLocker;
184impl AssetLock for TestAssetLocker {
185	type LockTicket = TestLockTicket;
186	type UnlockTicket = TestUnlockTicket;
187	type ReduceTicket = TestReduceTicket;
188
189	fn prepare_lock(
190		unlocker: Location,
191		asset: Asset,
192		_owner: Location,
193	) -> Result<TestLockTicket, LockError> {
194		Ok(TestLockTicket(unlocker, asset))
195	}
196
197	fn prepare_unlock(
198		unlocker: Location,
199		asset: Asset,
200		_owner: Location,
201	) -> Result<TestUnlockTicket, LockError> {
202		Ok(TestUnlockTicket(unlocker, asset))
203	}
204
205	fn note_unlockable(
206		_locker: Location,
207		_asset: Asset,
208		_owner: Location,
209	) -> Result<(), LockError> {
210		Ok(())
211	}
212
213	fn prepare_reduce_unlockable(
214		_locker: Location,
215		_asset: Asset,
216		_owner: Location,
217	) -> Result<TestReduceTicket, LockError> {
218		Ok(TestReduceTicket)
219	}
220}