1
// Copyright (C) Parity Technologies (UK) Ltd.
2
// This file is part of Polkadot.
3

            
4
// Substrate 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
// Substrate 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
//! Version 4 of the Cross-Consensus Message format data structures.
18

            
19
pub use super::v3::GetWeight;
20
use super::v3::{
21
	Instruction as OldInstruction, PalletInfo as OldPalletInfo,
22
	QueryResponseInfo as OldQueryResponseInfo, Response as OldResponse, Xcm as OldXcm,
23
};
24
use crate::DoubleEncoded;
25
use alloc::{vec, vec::Vec};
26
use bounded_collections::{parameter_types, BoundedVec};
27
use codec::{
28
	self, decode_vec_with_len, Compact, Decode, Encode, Error as CodecError, Input as CodecInput,
29
	MaxEncodedLen,
30
};
31
use core::{fmt::Debug, result};
32
use derivative::Derivative;
33
use scale_info::TypeInfo;
34

            
35
mod asset;
36
mod junction;
37
pub(crate) mod junctions;
38
mod location;
39
mod traits;
40

            
41
pub use asset::{
42
	Asset, AssetFilter, AssetId, AssetInstance, Assets, Fungibility, WildAsset, WildFungibility,
43
	MAX_ITEMS_IN_ASSETS,
44
};
45
pub use junction::{BodyId, BodyPart, Junction, NetworkId};
46
pub use junctions::Junctions;
47
pub use location::{Ancestor, AncestorThen, InteriorLocation, Location, Parent, ParentThen};
48
pub use traits::{
49
	send_xcm, validate_send, Error, ExecuteXcm, Outcome, PreparedMessage, Reanchorable, Result,
50
	SendError, SendResult, SendXcm, Weight, XcmHash,
51
};
52
// These parts of XCM v3 are unchanged in XCM v4, and are re-imported here.
53
pub use super::v3::{MaybeErrorCode, OriginKind, WeightLimit};
54

            
55
/// This module's XCM version.
56
pub const VERSION: super::Version = 4;
57

            
58
/// An identifier for a query.
59
pub type QueryId = u64;
60

            
61
38813
#[derive(Derivative, Default, Encode, TypeInfo)]
62
#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
63
#[codec(encode_bound())]
64
#[codec(decode_bound())]
65
#[scale_info(bounds(), skip_type_params(Call))]
66
pub struct Xcm<Call>(pub Vec<Instruction<Call>>);
67

            
68
pub const MAX_INSTRUCTIONS_TO_DECODE: u8 = 100;
69

            
70
environmental::environmental!(instructions_count: u8);
71

            
72
impl<Call> Decode for Xcm<Call> {
73
34455
	fn decode<I: CodecInput>(input: &mut I) -> core::result::Result<Self, CodecError> {
74
34455
		instructions_count::using_once(&mut 0, || {
75
34455
			let number_of_instructions: u32 = <Compact<u32>>::decode(input)?.into();
76
34368
			instructions_count::with(|count| {
77
34368
				*count = count.saturating_add(number_of_instructions as u8);
78
34368
				if *count > MAX_INSTRUCTIONS_TO_DECODE {
79
72
					return Err(CodecError::from("Max instructions exceeded"))
80
34296
				}
81
34296
				Ok(())
82
34368
			})
83
34368
			.expect("Called in `using` context and thus can not return `None`; qed")?;
84
34296
			let decoded_instructions = decode_vec_with_len(input, number_of_instructions as usize)?;
85
28332
			Ok(Self(decoded_instructions))
86
34455
		})
87
34455
	}
88
}
89

            
90
impl<Call> Xcm<Call> {
91
	/// Create an empty instance.
92
	pub fn new() -> Self {
93
		Self(vec![])
94
	}
95

            
96
	/// Return `true` if no instructions are held in `self`.
97
	pub fn is_empty(&self) -> bool {
98
		self.0.is_empty()
99
	}
100

            
101
	/// Return the number of instructions held in `self`.
102
	pub fn len(&self) -> usize {
103
		self.0.len()
104
	}
105

            
106
	/// Return a reference to the inner value.
107
	pub fn inner(&self) -> &[Instruction<Call>] {
108
		&self.0
109
	}
110

            
111
	/// Return a mutable reference to the inner value.
112
20142
	pub fn inner_mut(&mut self) -> &mut Vec<Instruction<Call>> {
113
20142
		&mut self.0
114
20142
	}
115

            
116
	/// Consume and return the inner value.
117
	pub fn into_inner(self) -> Vec<Instruction<Call>> {
118
		self.0
119
	}
120

            
121
	/// Return an iterator over references to the items.
122
	pub fn iter(&self) -> impl Iterator<Item = &Instruction<Call>> {
123
		self.0.iter()
124
	}
125

            
126
	/// Return an iterator over mutable references to the items.
127
	pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Instruction<Call>> {
128
		self.0.iter_mut()
129
	}
130

            
131
	/// Consume and return an iterator over the items.
132
3
	pub fn into_iter(self) -> impl Iterator<Item = Instruction<Call>> {
133
3
		self.0.into_iter()
134
3
	}
135

            
136
	/// Consume and either return `self` if it contains some instructions, or if it's empty, then
137
	/// instead return the result of `f`.
138
18063
	pub fn or_else(self, f: impl FnOnce() -> Self) -> Self {
139
18063
		if self.0.is_empty() {
140
17787
			f()
141
		} else {
142
276
			self
143
		}
144
18063
	}
145

            
146
	/// Return the first instruction, if any.
147
	pub fn first(&self) -> Option<&Instruction<Call>> {
148
		self.0.first()
149
	}
150

            
151
	/// Return the last instruction, if any.
152
6951
	pub fn last(&self) -> Option<&Instruction<Call>> {
153
6951
		self.0.last()
154
6951
	}
155

            
156
	/// Return the only instruction, contained in `Self`, iff only one exists (`None` otherwise).
157
	pub fn only(&self) -> Option<&Instruction<Call>> {
158
		if self.0.len() == 1 {
159
			self.0.first()
160
		} else {
161
			None
162
		}
163
	}
164

            
165
	/// Return the only instruction, contained in `Self`, iff only one exists (returns `self`
166
	/// otherwise).
167
	pub fn into_only(mut self) -> core::result::Result<Instruction<Call>, Self> {
168
		if self.0.len() == 1 {
169
			self.0.pop().ok_or(self)
170
		} else {
171
			Err(self)
172
		}
173
	}
174
}
175

            
176
impl<Call> From<Vec<Instruction<Call>>> for Xcm<Call> {
177
	fn from(c: Vec<Instruction<Call>>) -> Self {
178
		Self(c)
179
	}
180
}
181

            
182
impl<Call> From<Xcm<Call>> for Vec<Instruction<Call>> {
183
	fn from(c: Xcm<Call>) -> Self {
184
		c.0
185
	}
186
}
187

            
188
/// A prelude for importing all types typically used when interacting with XCM messages.
189
pub mod prelude {
190
	mod contents {
191
		pub use super::super::{
192
			send_xcm, validate_send, Ancestor, AncestorThen, Asset,
193
			AssetFilter::{self, *},
194
			AssetId,
195
			AssetInstance::{self, *},
196
			Assets, BodyId, BodyPart, Error as XcmError, ExecuteXcm,
197
			Fungibility::{self, *},
198
			Instruction::*,
199
			InteriorLocation,
200
			Junction::{self, *},
201
			Junctions::{self, Here},
202
			Location, MaybeErrorCode,
203
			NetworkId::{self, *},
204
			OriginKind, Outcome, PalletInfo, Parent, ParentThen, PreparedMessage, QueryId,
205
			QueryResponseInfo, Reanchorable, Response, Result as XcmResult, SendError, SendResult,
206
			SendXcm, Weight,
207
			WeightLimit::{self, *},
208
			WildAsset::{self, *},
209
			WildFungibility::{self, Fungible as WildFungible, NonFungible as WildNonFungible},
210
			XcmContext, XcmHash, XcmWeightInfo, VERSION as XCM_VERSION,
211
		};
212
	}
213
	pub use super::{Instruction, Xcm};
214
	pub use contents::*;
215
	pub mod opaque {
216
		pub use super::{
217
			super::opaque::{Instruction, Xcm},
218
			contents::*,
219
		};
220
	}
221
}
222

            
223
parameter_types! {
224
	pub MaxPalletNameLen: u32 = 48;
225
	/// Maximum size of the encoded error code coming from a `Dispatch` result, used for
226
	/// `MaybeErrorCode`. This is not (yet) enforced, so it's just an indication of expectation.
227
	pub MaxDispatchErrorLen: u32 = 128;
228
	pub MaxPalletsInfo: u32 = 64;
229
}
230

            
231
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
232
pub struct PalletInfo {
233
	#[codec(compact)]
234
	index: u32,
235
	name: BoundedVec<u8, MaxPalletNameLen>,
236
	module_name: BoundedVec<u8, MaxPalletNameLen>,
237
	#[codec(compact)]
238
	major: u32,
239
	#[codec(compact)]
240
	minor: u32,
241
	#[codec(compact)]
242
	patch: u32,
243
}
244

            
245
impl TryInto<OldPalletInfo> for PalletInfo {
246
	type Error = ();
247

            
248
	fn try_into(self) -> result::Result<OldPalletInfo, Self::Error> {
249
		OldPalletInfo::new(
250
			self.index,
251
			self.name.into_inner(),
252
			self.module_name.into_inner(),
253
			self.major,
254
			self.minor,
255
			self.patch,
256
		)
257
		.map_err(|_| ())
258
	}
259
}
260

            
261
impl PalletInfo {
262
264
	pub fn new(
263
264
		index: u32,
264
264
		name: Vec<u8>,
265
264
		module_name: Vec<u8>,
266
264
		major: u32,
267
264
		minor: u32,
268
264
		patch: u32,
269
264
	) -> result::Result<Self, Error> {
270
264
		let name = BoundedVec::try_from(name).map_err(|_| Error::Overflow)?;
271
264
		let module_name = BoundedVec::try_from(module_name).map_err(|_| Error::Overflow)?;
272

            
273
264
		Ok(Self { index, name, module_name, major, minor, patch })
274
264
	}
275
}
276

            
277
/// Response data to a query.
278
45
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
279
pub enum Response {
280
711
	/// No response. Serves as a neutral default.
281
711
	Null,
282
174
	/// Some assets.
283
174
	Assets(Assets),
284
102
	/// The outcome of an XCM instruction.
285
102
	ExecutionResult(Option<(u32, Error)>),
286
120
	/// An XCM version.
287
120
	Version(super::Version),
288
279
	/// The index, instance name, pallet name and version of some pallets.
289
279
	PalletsInfo(BoundedVec<PalletInfo, MaxPalletsInfo>),
290
252
	/// The status of a dispatch attempt using `Transact`.
291
252
	DispatchResult(MaybeErrorCode),
292
}
293

            
294
impl Default for Response {
295
	fn default() -> Self {
296
		Self::Null
297
	}
298
}
299

            
300
impl TryFrom<OldResponse> for Response {
301
	type Error = ();
302

            
303
1064
	fn try_from(old: OldResponse) -> result::Result<Self, Self::Error> {
304
		use OldResponse::*;
305
1064
		Ok(match old {
306
632
			Null => Self::Null,
307
56
			Assets(assets) => Self::Assets(assets.try_into()?),
308
232
			ExecutionResult(result) =>
309
232
				Self::ExecutionResult(result.map(|(num, old_error)| (num, old_error.into()))),
310
76
			Version(version) => Self::Version(version),
311
46
			PalletsInfo(pallet_info) => {
312
46
				let inner = pallet_info
313
46
					.into_iter()
314
46
					.map(TryInto::try_into)
315
46
					.collect::<result::Result<Vec<_>, _>>()?;
316
				Self::PalletsInfo(
317
46
					BoundedVec::<PalletInfo, MaxPalletsInfo>::try_from(inner).map_err(|_| ())?,
318
				)
319
			},
320
22
			DispatchResult(maybe_error) => Self::DispatchResult(maybe_error),
321
		})
322
1064
	}
323
}
324

            
325
/// Information regarding the composition of a query response.
326
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
327
pub struct QueryResponseInfo {
328
	/// The destination to which the query response message should be send.
329
	pub destination: Location,
330
	/// The `query_id` field of the `QueryResponse` message.
331
	#[codec(compact)]
332
	pub query_id: QueryId,
333
	/// The `max_weight` field of the `QueryResponse` message.
334
	pub max_weight: Weight,
335
}
336

            
337
impl TryFrom<OldQueryResponseInfo> for QueryResponseInfo {
338
	type Error = ();
339

            
340
466
	fn try_from(old: OldQueryResponseInfo) -> result::Result<Self, Self::Error> {
341
466
		Ok(Self {
342
466
			destination: old.destination.try_into()?,
343
466
			query_id: old.query_id,
344
466
			max_weight: old.max_weight,
345
		})
346
466
	}
347
}
348

            
349
/// Contextual data pertaining to a specific list of XCM instructions.
350
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)]
351
pub struct XcmContext {
352
	/// The current value of the Origin register of the `XCVM`.
353
	pub origin: Option<Location>,
354
	/// The identity of the XCM; this may be a hash of its versioned encoding but could also be
355
	/// a high-level identity set by an appropriate barrier.
356
	pub message_id: XcmHash,
357
	/// The current value of the Topic register of the `XCVM`.
358
	pub topic: Option<[u8; 32]>,
359
}
360

            
361
impl XcmContext {
362
	/// Constructor which sets the message ID to the supplied parameter and leaves the origin and
363
	/// topic unset.
364
	pub fn with_message_id(message_id: XcmHash) -> XcmContext {
365
		XcmContext { origin: None, message_id, topic: None }
366
	}
367
}
368

            
369
/// Cross-Consensus Message: A message from one consensus system to another.
370
///
371
/// Consensus systems that may send and receive messages include blockchains and smart contracts.
372
///
373
/// All messages are delivered from a known *origin*, expressed as a `Location`.
374
///
375
/// This is the inner XCM format and is version-sensitive. Messages are typically passed using the
376
/// outer XCM format, known as `VersionedXcm`.
377
#[derive(
378
1131096
	Derivative,
379
	Encode,
380
762
	Decode,
381
	TypeInfo,
382
	xcm_procedural::XcmWeightInfoTrait,
383
	xcm_procedural::Builder,
384
)]
385
#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
386
#[codec(encode_bound())]
387
#[codec(decode_bound())]
388
#[scale_info(bounds(), skip_type_params(Call))]
389
pub enum Instruction<Call> {
390
242607
	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place them into the Holding
391
	/// Register.
392
	///
393
	/// - `assets`: The asset(s) to be withdrawn into holding.
394
	///
395
	/// Kind: *Command*.
396
	///
397
	/// Errors:
398
	#[builder(loads_holding)]
399
242607
	WithdrawAsset(Assets),
400

            
401
4236
	/// Asset(s) (`assets`) have been received into the ownership of this system on the `origin`
402
	/// system and equivalent derivatives should be placed into the Holding Register.
403
	///
404
	/// - `assets`: The asset(s) that are minted into holding.
405
	///
406
	/// Safety: `origin` must be trusted to have received and be storing `assets` such that they
407
	/// may later be withdrawn should this system send a corresponding message.
408
	///
409
	/// Kind: *Trusted Indication*.
410
	///
411
	/// Errors:
412
	#[builder(loads_holding)]
413
4236
	ReserveAssetDeposited(Assets),
414

            
415
2556
	/// Asset(s) (`assets`) have been destroyed on the `origin` system and equivalent assets should
416
	/// be created and placed into the Holding Register.
417
	///
418
	/// - `assets`: The asset(s) that are minted into the Holding Register.
419
	///
420
	/// Safety: `origin` must be trusted to have irrevocably destroyed the corresponding `assets`
421
	/// prior as a consequence of sending this message.
422
	///
423
	/// Kind: *Trusted Indication*.
424
	///
425
	/// Errors:
426
	#[builder(loads_holding)]
427
2556
	ReceiveTeleportedAsset(Assets),
428

            
429
1701
	/// Respond with information that the local system is expecting.
430
	///
431
	/// - `query_id`: The identifier of the query that resulted in this message being sent.
432
	/// - `response`: The message content.
433
	/// - `max_weight`: The maximum weight that handling this response should take.
434
	/// - `querier`: The location responsible for the initiation of the response, if there is one.
435
	///   In general this will tend to be the same location as the receiver of this message. NOTE:
436
	///   As usual, this is interpreted from the perspective of the receiving consensus system.
437
	///
438
	/// Safety: Since this is information only, there are no immediate concerns. However, it should
439
	/// be remembered that even if the Origin behaves reasonably, it can always be asked to make
440
	/// a response to a third-party chain who may or may not be expecting the response. Therefore
441
	/// the `querier` should be checked to match the expected value.
442
	///
443
	/// Kind: *Information*.
444
	///
445
	/// Errors:
446
	QueryResponse {
447
18
		#[codec(compact)]
448
18
		query_id: QueryId,
449
93
		response: Response,
450
51
		max_weight: Weight,
451
36
		querier: Option<Location>,
452
1701
	},
453

            
454
3684
	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets
455
	/// under the ownership of `beneficiary`.
456
	///
457
	/// - `assets`: The asset(s) to be withdrawn.
458
	/// - `beneficiary`: The new owner for the assets.
459
	///
460
	/// Safety: No concerns.
461
	///
462
	/// Kind: *Command*.
463
	///
464
	/// Errors:
465
3684
	TransferAsset { assets: Assets, beneficiary: Location },
466

            
467
921
	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets
468
	/// under the ownership of `dest` within this consensus system (i.e. its sovereign account).
469
	///
470
	/// Send an onward XCM message to `dest` of `ReserveAssetDeposited` with the given
471
	/// `xcm`.
472
	///
473
	/// - `assets`: The asset(s) to be withdrawn.
474
	/// - `dest`: The location whose sovereign account will own the assets and thus the effective
475
	///   beneficiary for the assets and the notification target for the reserve asset deposit
476
	///   message.
477
	/// - `xcm`: The instructions that should follow the `ReserveAssetDeposited` instruction, which
478
	///   is sent onwards to `dest`.
479
	///
480
	/// Safety: No concerns.
481
	///
482
	/// Kind: *Command*.
483
	///
484
	/// Errors:
485
921
	TransferReserveAsset { assets: Assets, dest: Location, xcm: Xcm<()> },
486

            
487
10641
	/// Apply the encoded transaction `call`, whose dispatch-origin should be `origin` as expressed
488
	/// by the kind of origin `origin_kind`.
489
	///
490
	/// The Transact Status Register is set according to the result of dispatching the call.
491
	///
492
	/// - `origin_kind`: The means of expressing the message origin as a dispatch origin.
493
	/// - `require_weight_at_most`: The weight of `call`; this should be at least the chain's
494
	///   calculated weight and will be used in the weight determination arithmetic.
495
	/// - `call`: The encoded transaction to be applied.
496
	///
497
	/// Safety: No concerns.
498
	///
499
	/// Kind: *Command*.
500
	///
501
	/// Errors:
502
10641
	Transact { origin_kind: OriginKind, require_weight_at_most: Weight, call: DoubleEncoded<Call> },
503

            
504
882
	/// A message to notify about a new incoming HRMP channel. This message is meant to be sent by
505
	/// the relay-chain to a para.
506
	///
507
	/// - `sender`: The sender in the to-be opened channel. Also, the initiator of the channel
508
	///   opening.
509
	/// - `max_message_size`: The maximum size of a message proposed by the sender.
510
	/// - `max_capacity`: The maximum number of messages that can be queued in the channel.
511
	///
512
	/// Safety: The message should originate directly from the relay-chain.
513
	///
514
	/// Kind: *System Notification*
515
	HrmpNewChannelOpenRequest {
516
21
		#[codec(compact)]
517
21
		sender: u32,
518
30
		#[codec(compact)]
519
30
		max_message_size: u32,
520
21
		#[codec(compact)]
521
21
		max_capacity: u32,
522
882
	},
523

            
524
3963
	/// A message to notify about that a previously sent open channel request has been accepted by
525
	/// the recipient. That means that the channel will be opened during the next relay-chain
526
	/// session change. This message is meant to be sent by the relay-chain to a para.
527
	///
528
	/// Safety: The message should originate directly from the relay-chain.
529
	///
530
	/// Kind: *System Notification*
531
	///
532
	/// Errors:
533
	HrmpChannelAccepted {
534
		// NOTE: We keep this as a structured item to a) keep it consistent with the other Hrmp
535
		// items; and b) because the field's meaning is not obvious/mentioned from the item name.
536
12
		#[codec(compact)]
537
12
		recipient: u32,
538
3963
	},
539

            
540
1827
	/// A message to notify that the other party in an open channel decided to close it. In
541
	/// particular, `initiator` is going to close the channel opened from `sender` to the
542
	/// `recipient`. The close will be enacted at the next relay-chain session change. This message
543
	/// is meant to be sent by the relay-chain to a para.
544
	///
545
	/// Safety: The message should originate directly from the relay-chain.
546
	///
547
	/// Kind: *System Notification*
548
	///
549
	/// Errors:
550
	HrmpChannelClosing {
551
21
		#[codec(compact)]
552
21
		initiator: u32,
553
21
		#[codec(compact)]
554
21
		sender: u32,
555
18
		#[codec(compact)]
556
18
		recipient: u32,
557
1827
	},
558

            
559
6735
	/// Clear the origin.
560
6735
	///
561
6735
	/// This may be used by the XCM author to ensure that later instructions cannot command the
562
6735
	/// authority of the origin (e.g. if they are being relayed from an untrusted source, as often
563
6735
	/// the case with `ReserveAssetDeposited`).
564
6735
	///
565
6735
	/// Safety: No concerns.
566
6735
	///
567
6735
	/// Kind: *Command*.
568
6735
	///
569
6735
	/// Errors:
570
6735
	ClearOrigin,
571

            
572
1875
	/// Mutate the origin to some interior location.
573
	///
574
	/// Kind: *Command*
575
	///
576
	/// Errors:
577
1875
	DescendOrigin(InteriorLocation),
578

            
579
1275
	/// Immediately report the contents of the Error Register to the given destination via XCM.
580
	///
581
	/// A `QueryResponse` message of type `ExecutionOutcome` is sent to the described destination.
582
	///
583
	/// - `response_info`: Information for making the response.
584
	///
585
	/// Kind: *Command*
586
	///
587
	/// Errors:
588
1275
	ReportError(QueryResponseInfo),
589

            
590
363
	/// Remove the asset(s) (`assets`) from the Holding Register and place equivalent assets under
591
	/// the ownership of `beneficiary` within this consensus system.
592
	///
593
	/// - `assets`: The asset(s) to remove from holding.
594
	/// - `beneficiary`: The new owner for the assets.
595
	///
596
	/// Kind: *Command*
597
	///
598
	/// Errors:
599
363
	DepositAsset { assets: AssetFilter, beneficiary: Location },
600

            
601
609
	/// Remove the asset(s) (`assets`) from the Holding Register and place equivalent assets under
602
	/// the ownership of `dest` within this consensus system (i.e. deposit them into its sovereign
603
	/// account).
604
	///
605
	/// Send an onward XCM message to `dest` of `ReserveAssetDeposited` with the given `effects`.
606
	///
607
	/// - `assets`: The asset(s) to remove from holding.
608
	/// - `dest`: The location whose sovereign account will own the assets and thus the effective
609
	///   beneficiary for the assets and the notification target for the reserve asset deposit
610
	///   message.
611
	/// - `xcm`: The orders that should follow the `ReserveAssetDeposited` instruction which is
612
	///   sent onwards to `dest`.
613
	///
614
	/// Kind: *Command*
615
	///
616
	/// Errors:
617
609
	DepositReserveAsset { assets: AssetFilter, dest: Location, xcm: Xcm<()> },
618

            
619
576
	/// Remove the asset(s) (`want`) from the Holding Register and replace them with alternative
620
	/// assets.
621
	///
622
	/// The minimum amount of assets to be received into the Holding Register for the order not to
623
	/// fail may be stated.
624
	///
625
	/// - `give`: The maximum amount of assets to remove from holding.
626
	/// - `want`: The minimum amount of assets which `give` should be exchanged for.
627
	/// - `maximal`: If `true`, then prefer to give as much as possible up to the limit of `give`
628
	///   and receive accordingly more. If `false`, then prefer to give as little as possible in
629
	///   order to receive as little as possible while receiving at least `want`.
630
	///
631
	/// Kind: *Command*
632
	///
633
	/// Errors:
634
576
	ExchangeAsset { give: AssetFilter, want: Assets, maximal: bool },
635

            
636
3339
	/// Remove the asset(s) (`assets`) from holding and send a `WithdrawAsset` XCM message to a
637
	/// reserve location.
638
	///
639
	/// - `assets`: The asset(s) to remove from holding.
640
	/// - `reserve`: A valid location that acts as a reserve for all asset(s) in `assets`. The
641
	///   sovereign account of this consensus system *on the reserve location* will have
642
	///   appropriate assets withdrawn and `effects` will be executed on them. There will typically
643
	///   be only one valid location on any given asset/chain combination.
644
	/// - `xcm`: The instructions to execute on the assets once withdrawn *on the reserve
645
	///   location*.
646
	///
647
	/// Kind: *Command*
648
	///
649
	/// Errors:
650
3339
	InitiateReserveWithdraw { assets: AssetFilter, reserve: Location, xcm: Xcm<()> },
651

            
652
1563
	/// Remove the asset(s) (`assets`) from holding and send a `ReceiveTeleportedAsset` XCM message
653
	/// to a `dest` location.
654
	///
655
	/// - `assets`: The asset(s) to remove from holding.
656
	/// - `dest`: A valid location that respects teleports coming from this location.
657
	/// - `xcm`: The instructions to execute on the assets once arrived *on the destination
658
	///   location*.
659
	///
660
	/// NOTE: The `dest` location *MUST* respect this origin as a valid teleportation origin for
661
	/// all `assets`. If it does not, then the assets may be lost.
662
	///
663
	/// Kind: *Command*
664
	///
665
	/// Errors:
666
1563
	InitiateTeleport { assets: AssetFilter, dest: Location, xcm: Xcm<()> },
667

            
668
1308
	/// Report to a given destination the contents of the Holding Register.
669
	///
670
	/// A `QueryResponse` message of type `Assets` is sent to the described destination.
671
	///
672
	/// - `response_info`: Information for making the response.
673
	/// - `assets`: A filter for the assets that should be reported back. The assets reported back
674
	///   will be, asset-wise, *the lesser of this value and the holding register*. No wildcards
675
	///   will be used when reporting assets back.
676
	///
677
	/// Kind: *Command*
678
	///
679
	/// Errors:
680
1308
	ReportHolding { response_info: QueryResponseInfo, assets: AssetFilter },
681

            
682
396
	/// Pay for the execution of some XCM `xcm` and `orders` with up to `weight`
683
	/// picoseconds of execution time, paying for this with up to `fees` from the Holding Register.
684
	///
685
	/// - `fees`: The asset(s) to remove from the Holding Register to pay for fees.
686
	/// - `weight_limit`: The maximum amount of weight to purchase; this must be at least the
687
	///   expected maximum weight of the total XCM to be executed for the
688
	///   `AllowTopLevelPaidExecutionFrom` barrier to allow the XCM be executed.
689
	///
690
	/// Kind: *Command*
691
	///
692
	/// Errors:
693
396
	BuyExecution { fees: Asset, weight_limit: WeightLimit },
694

            
695
11301
	/// Refund any surplus weight previously bought with `BuyExecution`.
696
11301
	///
697
11301
	/// Kind: *Command*
698
11301
	///
699
11301
	/// Errors: None.
700
11301
	RefundSurplus,
701

            
702
1707
	/// Set the Error Handler Register. This is code that should be called in the case of an error
703
	/// happening.
704
	///
705
	/// An error occurring within execution of this code will _NOT_ result in the error register
706
	/// being set, nor will an error handler be called due to it. The error handler and appendix
707
	/// may each still be set.
708
	///
709
	/// The apparent weight of this instruction is inclusive of the inner `Xcm`; the executing
710
	/// weight however includes only the difference between the previous handler and the new
711
	/// handler, which can reasonably be negative, which would result in a surplus.
712
	///
713
	/// Kind: *Command*
714
	///
715
	/// Errors: None.
716
1707
	SetErrorHandler(Xcm<Call>),
717

            
718
2532
	/// Set the Appendix Register. This is code that should be called after code execution
719
	/// (including the error handler if any) is finished. This will be called regardless of whether
720
	/// an error occurred.
721
	///
722
	/// Any error occurring due to execution of this code will result in the error register being
723
	/// set, and the error handler (if set) firing.
724
	///
725
	/// The apparent weight of this instruction is inclusive of the inner `Xcm`; the executing
726
	/// weight however includes only the difference between the previous appendix and the new
727
	/// appendix, which can reasonably be negative, which would result in a surplus.
728
	///
729
	/// Kind: *Command*
730
	///
731
	/// Errors: None.
732
2532
	SetAppendix(Xcm<Call>),
733

            
734
6771
	/// Clear the Error Register.
735
6771
	///
736
6771
	/// Kind: *Command*
737
6771
	///
738
6771
	/// Errors: None.
739
6771
	ClearError,
740

            
741
1953
	/// Create some assets which are being held on behalf of the origin.
742
	///
743
	/// - `assets`: The assets which are to be claimed. This must match exactly with the assets
744
	///   claimable by the origin of the ticket.
745
	/// - `ticket`: The ticket of the asset; this is an abstract identifier to help locate the
746
	///   asset.
747
	///
748
	/// Kind: *Command*
749
	///
750
	/// Errors:
751
	#[builder(loads_holding)]
752
1953
	ClaimAsset { assets: Assets, ticket: Location },
753

            
754
3801
	/// Always throws an error of type `Trap`.
755
	///
756
	/// Kind: *Command*
757
	///
758
	/// Errors:
759
	/// - `Trap`: All circumstances, whose inner value is the same as this item's inner value.
760
3801
	Trap(#[codec(compact)] u64),
761

            
762
3420
	/// Ask the destination system to respond with the most recent version of XCM that they
763
	/// support in a `QueryResponse` instruction. Any changes to this should also elicit similar
764
	/// responses when they happen.
765
	///
766
	/// - `query_id`: An identifier that will be replicated into the returned XCM message.
767
	/// - `max_response_weight`: The maximum amount of weight that the `QueryResponse` item which
768
	///   is sent as a reply may take to execute. NOTE: If this is unexpectedly large then the
769
	///   response may not execute at all.
770
	///
771
	/// Kind: *Command*
772
	///
773
	/// Errors: *Fallible*
774
	SubscribeVersion {
775
30
		#[codec(compact)]
776
30
		query_id: QueryId,
777
51
		max_response_weight: Weight,
778
3420
	},
779

            
780
3372
	/// Cancel the effect of a previous `SubscribeVersion` instruction.
781
3372
	///
782
3372
	/// Kind: *Command*
783
3372
	///
784
3372
	/// Errors: *Fallible*
785
3372
	UnsubscribeVersion,
786

            
787
624
	/// Reduce Holding by up to the given assets.
788
	///
789
	/// Holding is reduced by as much as possible up to the assets in the parameter. It is not an
790
	/// error if the Holding does not contain the assets (to make this an error, use `ExpectAsset`
791
	/// prior).
792
	///
793
	/// Kind: *Command*
794
	///
795
	/// Errors: *Infallible*
796
624
	BurnAsset(Assets),
797

            
798
1260
	/// Throw an error if Holding does not contain at least the given assets.
799
	///
800
	/// Kind: *Command*
801
	///
802
	/// Errors:
803
	/// - `ExpectationFalse`: If Holding Register does not contain the assets in the parameter.
804
1260
	ExpectAsset(Assets),
805

            
806
906
	/// Ensure that the Origin Register equals some given value and throw an error if not.
807
	///
808
	/// Kind: *Command*
809
	///
810
	/// Errors:
811
	/// - `ExpectationFalse`: If Origin Register is not equal to the parameter.
812
906
	ExpectOrigin(Option<Location>),
813

            
814
2349
	/// Ensure that the Error Register equals some given value and throw an error if not.
815
	///
816
	/// Kind: *Command*
817
	///
818
	/// Errors:
819
	/// - `ExpectationFalse`: If the value of the Error Register is not equal to the parameter.
820
2349
	ExpectError(Option<(u32, Error)>),
821

            
822
2532
	/// Ensure that the Transact Status Register equals some given value and throw an error if
823
	/// not.
824
	///
825
	/// Kind: *Command*
826
	///
827
	/// Errors:
828
	/// - `ExpectationFalse`: If the value of the Transact Status Register is not equal to the
829
	///   parameter.
830
2532
	ExpectTransactStatus(MaybeErrorCode),
831

            
832
1026
	/// Query the existence of a particular pallet type.
833
	///
834
	/// - `module_name`: The module name of the pallet to query.
835
	/// - `response_info`: Information for making the response.
836
	///
837
	/// Sends a `QueryResponse` to Origin whose data field `PalletsInfo` containing the information
838
	/// of all pallets on the local chain whose name is equal to `name`. This is empty in the case
839
	/// that the local chain is not based on Substrate Frame.
840
	///
841
	/// Safety: No concerns.
842
	///
843
	/// Kind: *Command*
844
	///
845
	/// Errors: *Fallible*.
846
1026
	QueryPallet { module_name: Vec<u8>, response_info: QueryResponseInfo },
847

            
848
864
	/// Ensure that a particular pallet with a particular version exists.
849
	///
850
	/// - `index: Compact`: The index which identifies the pallet. An error if no pallet exists at
851
	///   this index.
852
	/// - `name: Vec<u8>`: Name which must be equal to the name of the pallet.
853
	/// - `module_name: Vec<u8>`: Module name which must be equal to the name of the module in
854
	///   which the pallet exists.
855
	/// - `crate_major: Compact`: Version number which must be equal to the major version of the
856
	///   crate which implements the pallet.
857
	/// - `min_crate_minor: Compact`: Version number which must be at most the minor version of the
858
	///   crate which implements the pallet.
859
	///
860
	/// Safety: No concerns.
861
	///
862
	/// Kind: *Command*
863
	///
864
	/// Errors:
865
	/// - `ExpectationFalse`: In case any of the expectations are broken.
866
	ExpectPallet {
867
9
		#[codec(compact)]
868
9
		index: u32,
869
21
		name: Vec<u8>,
870
24
		module_name: Vec<u8>,
871
24
		#[codec(compact)]
872
24
		crate_major: u32,
873
9
		#[codec(compact)]
874
9
		min_crate_minor: u32,
875
864
	},
876

            
877
1881
	/// Send a `QueryResponse` message containing the value of the Transact Status Register to some
878
	/// destination.
879
	///
880
	/// - `query_response_info`: The information needed for constructing and sending the
881
	///   `QueryResponse` message.
882
	///
883
	/// Safety: No concerns.
884
	///
885
	/// Kind: *Command*
886
	///
887
	/// Errors: *Fallible*.
888
1881
	ReportTransactStatus(QueryResponseInfo),
889

            
890
4659
	/// Set the Transact Status Register to its default, cleared, value.
891
4659
	///
892
4659
	/// Safety: No concerns.
893
4659
	///
894
4659
	/// Kind: *Command*
895
4659
	///
896
4659
	/// Errors: *Infallible*.
897
4659
	ClearTransactStatus,
898

            
899
1557
	/// Set the Origin Register to be some child of the Universal Ancestor.
900
	///
901
	/// Safety: Should only be usable if the Origin is trusted to represent the Universal Ancestor
902
	/// child in general. In general, no Origin should be able to represent the Universal Ancestor
903
	/// child which is the root of the local consensus system since it would by extension
904
	/// allow it to act as any location within the local consensus.
905
	///
906
	/// The `Junction` parameter should generally be a `GlobalConsensus` variant since it is only
907
	/// these which are children of the Universal Ancestor.
908
	///
909
	/// Kind: *Command*
910
	///
911
	/// Errors: *Fallible*.
912
1557
	UniversalOrigin(Junction),
913

            
914
1386
	/// Send a message on to Non-Local Consensus system.
915
	///
916
	/// This will tend to utilize some extra-consensus mechanism, the obvious one being a bridge.
917
	/// A fee may be charged; this may be determined based on the contents of `xcm`. It will be
918
	/// taken from the Holding register.
919
	///
920
	/// - `network`: The remote consensus system to which the message should be exported.
921
	/// - `destination`: The location relative to the remote consensus system to which the message
922
	///   should be sent on arrival.
923
	/// - `xcm`: The message to be exported.
924
	///
925
	/// As an example, to export a message for execution on Statemine (parachain #1000 in the
926
	/// Kusama network), you would call with `network: NetworkId::Kusama` and
927
	/// `destination: [Parachain(1000)].into()`. Alternatively, to export a message for execution
928
	/// on Polkadot, you would call with `network: NetworkId:: Polkadot` and `destination: Here`.
929
	///
930
	/// Kind: *Command*
931
	///
932
	/// Errors: *Fallible*.
933
1386
	ExportMessage { network: NetworkId, destination: InteriorLocation, xcm: Xcm<()> },
934

            
935
768
	/// Lock the locally held asset and prevent further transfer or withdrawal.
936
	///
937
	/// This restriction may be removed by the `UnlockAsset` instruction being called with an
938
	/// Origin of `unlocker` and a `target` equal to the current `Origin`.
939
	///
940
	/// If the locking is successful, then a `NoteUnlockable` instruction is sent to `unlocker`.
941
	///
942
	/// - `asset`: The asset(s) which should be locked.
943
	/// - `unlocker`: The value which the Origin must be for a corresponding `UnlockAsset`
944
	///   instruction to work.
945
	///
946
	/// Kind: *Command*.
947
	///
948
	/// Errors:
949
768
	LockAsset { asset: Asset, unlocker: Location },
950

            
951
285
	/// Remove the lock over `asset` on this chain and (if nothing else is preventing it) allow the
952
	/// asset to be transferred.
953
	///
954
	/// - `asset`: The asset to be unlocked.
955
	/// - `target`: The owner of the asset on the local chain.
956
	///
957
	/// Safety: No concerns.
958
	///
959
	/// Kind: *Command*.
960
	///
961
	/// Errors:
962
285
	UnlockAsset { asset: Asset, target: Location },
963

            
964
582
	/// Asset (`asset`) has been locked on the `origin` system and may not be transferred. It may
965
	/// only be unlocked with the receipt of the `UnlockAsset` instruction from this chain.
966
	///
967
	/// - `asset`: The asset(s) which are now unlockable from this origin.
968
	/// - `owner`: The owner of the asset on the chain in which it was locked. This may be a
969
	///   location specific to the origin network.
970
	///
971
	/// Safety: `origin` must be trusted to have locked the corresponding `asset`
972
	/// prior as a consequence of sending this message.
973
	///
974
	/// Kind: *Trusted Indication*.
975
	///
976
	/// Errors:
977
582
	NoteUnlockable { asset: Asset, owner: Location },
978

            
979
429
	/// Send an `UnlockAsset` instruction to the `locker` for the given `asset`.
980
	///
981
	/// This may fail if the local system is making use of the fact that the asset is locked or,
982
	/// of course, if there is no record that the asset actually is locked.
983
	///
984
	/// - `asset`: The asset(s) to be unlocked.
985
	/// - `locker`: The location from which a previous `NoteUnlockable` was sent and to which an
986
	///   `UnlockAsset` should be sent.
987
	///
988
	/// Kind: *Command*.
989
	///
990
	/// Errors:
991
429
	RequestUnlock { asset: Asset, locker: Location },
992

            
993
525
	/// Sets the Fees Mode Register.
994
	///
995
	/// - `jit_withdraw`: The fees mode item; if set to `true` then fees for any instructions are
996
	///   withdrawn as needed using the same mechanism as `WithdrawAssets`.
997
	///
998
	/// Kind: *Command*.
999
	///
	/// Errors:
525
	SetFeesMode { jit_withdraw: bool },
4239
	/// Set the Topic Register.
	///
	/// The 32-byte array identifier in the parameter is not guaranteed to be
	/// unique; if such a property is desired, it is up to the code author to
	/// enforce uniqueness.
	///
	/// Safety: No concerns.
	///
	/// Kind: *Command*
	///
	/// Errors:
4239
	SetTopic([u8; 32]),
8271
	/// Clear the Topic Register.
8271
	///
8271
	/// Kind: *Command*
8271
	///
8271
	/// Errors: None.
8271
	ClearTopic,
1425
	/// Alter the current Origin to another given origin.
	///
	/// Kind: *Command*
	///
	/// Errors: If the existing state would not allow such a change.
1425
	AliasOrigin(Location),
1269
	/// A directive to indicate that the origin expects free execution of the message.
	///
	/// At execution time, this instruction just does a check on the Origin register.
	/// However, at the barrier stage messages starting with this instruction can be disregarded if
	/// the origin is not acceptable for free execution or the `weight_limit` is `Limited` and
	/// insufficient.
	///
	/// Kind: *Indication*
	///
	/// Errors: If the given origin is `Some` and not equal to the current Origin register.
1269
	UnpaidExecution { weight_limit: WeightLimit, check_origin: Option<Location> },
}
impl<Call> Xcm<Call> {
	pub fn into<C>(self) -> Xcm<C> {
		Xcm::from(self)
	}
	pub fn from<C>(xcm: Xcm<C>) -> Self {
		Self(xcm.0.into_iter().map(Instruction::<Call>::from).collect())
	}
}
impl<Call> Instruction<Call> {
	pub fn into<C>(self) -> Instruction<C> {
		Instruction::from(self)
	}
	pub fn from<C>(xcm: Instruction<C>) -> Self {
		use Instruction::*;
		match xcm {
			WithdrawAsset(assets) => WithdrawAsset(assets),
			ReserveAssetDeposited(assets) => ReserveAssetDeposited(assets),
			ReceiveTeleportedAsset(assets) => ReceiveTeleportedAsset(assets),
			QueryResponse { query_id, response, max_weight, querier } =>
				QueryResponse { query_id, response, max_weight, querier },
			TransferAsset { assets, beneficiary } => TransferAsset { assets, beneficiary },
			TransferReserveAsset { assets, dest, xcm } =>
				TransferReserveAsset { assets, dest, xcm },
			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
				HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity },
			HrmpChannelAccepted { recipient } => HrmpChannelAccepted { recipient },
			HrmpChannelClosing { initiator, sender, recipient } =>
				HrmpChannelClosing { initiator, sender, recipient },
			Transact { origin_kind, require_weight_at_most, call } =>
				Transact { origin_kind, require_weight_at_most, call: call.into() },
			ReportError(response_info) => ReportError(response_info),
			DepositAsset { assets, beneficiary } => DepositAsset { assets, beneficiary },
			DepositReserveAsset { assets, dest, xcm } => DepositReserveAsset { assets, dest, xcm },
			ExchangeAsset { give, want, maximal } => ExchangeAsset { give, want, maximal },
			InitiateReserveWithdraw { assets, reserve, xcm } =>
				InitiateReserveWithdraw { assets, reserve, xcm },
			InitiateTeleport { assets, dest, xcm } => InitiateTeleport { assets, dest, xcm },
			ReportHolding { response_info, assets } => ReportHolding { response_info, assets },
			BuyExecution { fees, weight_limit } => BuyExecution { fees, weight_limit },
			ClearOrigin => ClearOrigin,
			DescendOrigin(who) => DescendOrigin(who),
			RefundSurplus => RefundSurplus,
			SetErrorHandler(xcm) => SetErrorHandler(xcm.into()),
			SetAppendix(xcm) => SetAppendix(xcm.into()),
			ClearError => ClearError,
			ClaimAsset { assets, ticket } => ClaimAsset { assets, ticket },
			Trap(code) => Trap(code),
			SubscribeVersion { query_id, max_response_weight } =>
				SubscribeVersion { query_id, max_response_weight },
			UnsubscribeVersion => UnsubscribeVersion,
			BurnAsset(assets) => BurnAsset(assets),
			ExpectAsset(assets) => ExpectAsset(assets),
			ExpectOrigin(origin) => ExpectOrigin(origin),
			ExpectError(error) => ExpectError(error),
			ExpectTransactStatus(transact_status) => ExpectTransactStatus(transact_status),
			QueryPallet { module_name, response_info } =>
				QueryPallet { module_name, response_info },
			ExpectPallet { index, name, module_name, crate_major, min_crate_minor } =>
				ExpectPallet { index, name, module_name, crate_major, min_crate_minor },
			ReportTransactStatus(response_info) => ReportTransactStatus(response_info),
			ClearTransactStatus => ClearTransactStatus,
			UniversalOrigin(j) => UniversalOrigin(j),
			ExportMessage { network, destination, xcm } =>
				ExportMessage { network, destination, xcm },
			LockAsset { asset, unlocker } => LockAsset { asset, unlocker },
			UnlockAsset { asset, target } => UnlockAsset { asset, target },
			NoteUnlockable { asset, owner } => NoteUnlockable { asset, owner },
			RequestUnlock { asset, locker } => RequestUnlock { asset, locker },
			SetFeesMode { jit_withdraw } => SetFeesMode { jit_withdraw },
			SetTopic(topic) => SetTopic(topic),
			ClearTopic => ClearTopic,
			AliasOrigin(location) => AliasOrigin(location),
			UnpaidExecution { weight_limit, check_origin } =>
				UnpaidExecution { weight_limit, check_origin },
		}
	}
}
// TODO: Automate Generation
impl<Call, W: XcmWeightInfo<Call>> GetWeight<W> for Instruction<Call> {
	fn weight(&self) -> Weight {
		use Instruction::*;
		match self {
			WithdrawAsset(assets) => W::withdraw_asset(assets),
			ReserveAssetDeposited(assets) => W::reserve_asset_deposited(assets),
			ReceiveTeleportedAsset(assets) => W::receive_teleported_asset(assets),
			QueryResponse { query_id, response, max_weight, querier } =>
				W::query_response(query_id, response, max_weight, querier),
			TransferAsset { assets, beneficiary } => W::transfer_asset(assets, beneficiary),
			TransferReserveAsset { assets, dest, xcm } =>
				W::transfer_reserve_asset(&assets, dest, xcm),
			Transact { origin_kind, require_weight_at_most, call } =>
				W::transact(origin_kind, require_weight_at_most, call),
			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
				W::hrmp_new_channel_open_request(sender, max_message_size, max_capacity),
			HrmpChannelAccepted { recipient } => W::hrmp_channel_accepted(recipient),
			HrmpChannelClosing { initiator, sender, recipient } =>
				W::hrmp_channel_closing(initiator, sender, recipient),
			ClearOrigin => W::clear_origin(),
			DescendOrigin(who) => W::descend_origin(who),
			ReportError(response_info) => W::report_error(&response_info),
			DepositAsset { assets, beneficiary } => W::deposit_asset(assets, beneficiary),
			DepositReserveAsset { assets, dest, xcm } =>
				W::deposit_reserve_asset(assets, dest, xcm),
			ExchangeAsset { give, want, maximal } => W::exchange_asset(give, want, maximal),
			InitiateReserveWithdraw { assets, reserve, xcm } =>
				W::initiate_reserve_withdraw(assets, reserve, xcm),
			InitiateTeleport { assets, dest, xcm } => W::initiate_teleport(assets, dest, xcm),
			ReportHolding { response_info, assets } => W::report_holding(&response_info, &assets),
			BuyExecution { fees, weight_limit } => W::buy_execution(fees, weight_limit),
			RefundSurplus => W::refund_surplus(),
			SetErrorHandler(xcm) => W::set_error_handler(xcm),
			SetAppendix(xcm) => W::set_appendix(xcm),
			ClearError => W::clear_error(),
			ClaimAsset { assets, ticket } => W::claim_asset(assets, ticket),
			Trap(code) => W::trap(code),
			SubscribeVersion { query_id, max_response_weight } =>
				W::subscribe_version(query_id, max_response_weight),
			UnsubscribeVersion => W::unsubscribe_version(),
			BurnAsset(assets) => W::burn_asset(assets),
			ExpectAsset(assets) => W::expect_asset(assets),
			ExpectOrigin(origin) => W::expect_origin(origin),
			ExpectError(error) => W::expect_error(error),
			ExpectTransactStatus(transact_status) => W::expect_transact_status(transact_status),
			QueryPallet { module_name, response_info } =>
				W::query_pallet(module_name, response_info),
			ExpectPallet { index, name, module_name, crate_major, min_crate_minor } =>
				W::expect_pallet(index, name, module_name, crate_major, min_crate_minor),
			ReportTransactStatus(response_info) => W::report_transact_status(response_info),
			ClearTransactStatus => W::clear_transact_status(),
			UniversalOrigin(j) => W::universal_origin(j),
			ExportMessage { network, destination, xcm } =>
				W::export_message(network, destination, xcm),
			LockAsset { asset, unlocker } => W::lock_asset(asset, unlocker),
			UnlockAsset { asset, target } => W::unlock_asset(asset, target),
			NoteUnlockable { asset, owner } => W::note_unlockable(asset, owner),
			RequestUnlock { asset, locker } => W::request_unlock(asset, locker),
			SetFeesMode { jit_withdraw } => W::set_fees_mode(jit_withdraw),
			SetTopic(topic) => W::set_topic(topic),
			ClearTopic => W::clear_topic(),
			AliasOrigin(location) => W::alias_origin(location),
			UnpaidExecution { weight_limit, check_origin } =>
				W::unpaid_execution(weight_limit, check_origin),
		}
	}
}
pub mod opaque {
	/// The basic concrete type of `Xcm`, which doesn't make any assumptions about the
	/// format of a call other than it is pre-encoded.
	pub type Xcm = super::Xcm<()>;
	/// The basic concrete type of `Instruction`, which doesn't make any assumptions about the
	/// format of a call other than it is pre-encoded.
	pub type Instruction = super::Instruction<()>;
}
// Convert from a v3 XCM to a v4 XCM
impl<Call> TryFrom<OldXcm<Call>> for Xcm<Call> {
	type Error = ();
22563
	fn try_from(old_xcm: OldXcm<Call>) -> result::Result<Self, Self::Error> {
22563
		Ok(Xcm(old_xcm.0.into_iter().map(TryInto::try_into).collect::<result::Result<_, _>>()?))
22563
	}
}
// Convert from a v3 instruction to a v4 instruction
impl<Call> TryFrom<OldInstruction<Call>> for Instruction<Call> {
	type Error = ();
203529
	fn try_from(old_instruction: OldInstruction<Call>) -> result::Result<Self, Self::Error> {
		use OldInstruction::*;
1596
		Ok(match old_instruction {
131721
			WithdrawAsset(assets) => Self::WithdrawAsset(assets.try_into()?),
2811
			ReserveAssetDeposited(assets) => Self::ReserveAssetDeposited(assets.try_into()?),
1524
			ReceiveTeleportedAsset(assets) => Self::ReceiveTeleportedAsset(assets.try_into()?),
78
			QueryResponse { query_id, response, max_weight, querier: Some(querier) } =>
78
				Self::QueryResponse {
78
					query_id,
78
					querier: querier.try_into()?,
78
					response: response.try_into()?,
66
					max_weight,
				},
1518
			QueryResponse { query_id, response, max_weight, querier: None } =>
1518
				Self::QueryResponse {
1518
					query_id,
1518
					querier: None,
1518
					response: response.try_into()?,
1512
					max_weight,
				},
1509
			TransferAsset { assets, beneficiary } => Self::TransferAsset {
1509
				assets: assets.try_into()?,
1503
				beneficiary: beneficiary.try_into()?,
			},
1473
			TransferReserveAsset { assets, dest, xcm } => Self::TransferReserveAsset {
1473
				assets: assets.try_into()?,
1470
				dest: dest.try_into()?,
1470
				xcm: xcm.try_into()?,
			},
351
			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
351
				Self::HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity },
4944
			HrmpChannelAccepted { recipient } => Self::HrmpChannelAccepted { recipient },
1116
			HrmpChannelClosing { initiator, sender, recipient } =>
1116
				Self::HrmpChannelClosing { initiator, sender, recipient },
1278
			Transact { origin_kind, require_weight_at_most, call } =>
1278
				Self::Transact { origin_kind, require_weight_at_most, call: call.into() },
603
			ReportError(response_info) => Self::ReportError(QueryResponseInfo {
603
				query_id: response_info.query_id,
603
				destination: response_info.destination.try_into().map_err(|_| ())?,
603
				max_weight: response_info.max_weight,
			}),
735
			DepositAsset { assets, beneficiary } => {
735
				let beneficiary = beneficiary.try_into()?;
735
				let assets = assets.try_into()?;
657
				Self::DepositAsset { assets, beneficiary }
			},
2070
			DepositReserveAsset { assets, dest, xcm } => {
2070
				let dest = dest.try_into()?;
2070
				let xcm = xcm.try_into()?;
2040
				let assets = assets.try_into()?;
1995
				Self::DepositReserveAsset { assets, dest, xcm }
			},
507
			ExchangeAsset { give, want, maximal } => {
507
				let give = give.try_into()?;
429
				let want = want.try_into()?;
417
				Self::ExchangeAsset { give, want, maximal }
			},
3129
			InitiateReserveWithdraw { assets, reserve, xcm } => {
3129
				let assets = assets.try_into()?;
3033
				let reserve = reserve.try_into()?;
3033
				let xcm = xcm.try_into()?;
2835
				Self::InitiateReserveWithdraw { assets, reserve, xcm }
			},
1713
			InitiateTeleport { assets, dest, xcm } => {
1713
				let assets = assets.try_into()?;
1626
				let dest = dest.try_into()?;
1626
				let xcm = xcm.try_into()?;
1602
				Self::InitiateTeleport { assets, dest, xcm }
			},
747
			ReportHolding { response_info, assets } => {
747
				let response_info = QueryResponseInfo {
747
					destination: response_info.destination.try_into().map_err(|_| ())?,
747
					query_id: response_info.query_id,
747
					max_weight: response_info.max_weight,
747
				};
747
				Self::ReportHolding { response_info, assets: assets.try_into()? }
			},
564
			BuyExecution { fees, weight_limit } => {
564
				let fees = fees.try_into()?;
477
				let weight_limit = weight_limit.into();
477
				Self::BuyExecution { fees, weight_limit }
			},
16266
			ClearOrigin => Self::ClearOrigin,
627
			DescendOrigin(who) => Self::DescendOrigin(who.try_into()?),
8013
			RefundSurplus => Self::RefundSurplus,
1491
			SetErrorHandler(xcm) => Self::SetErrorHandler(xcm.try_into()?),
2247
			SetAppendix(xcm) => Self::SetAppendix(xcm.try_into()?),
1668
			ClearError => Self::ClearError,
558
			ClaimAsset { assets, ticket } => {
558
				let assets = assets.try_into()?;
558
				let ticket = ticket.try_into()?;
558
				Self::ClaimAsset { assets, ticket }
			},
1578
			Trap(code) => Self::Trap(code),
1332
			SubscribeVersion { query_id, max_response_weight } =>
1332
				Self::SubscribeVersion { query_id, max_response_weight },
2010
			UnsubscribeVersion => Self::UnsubscribeVersion,
120
			BurnAsset(assets) => Self::BurnAsset(assets.try_into()?),
144
			ExpectAsset(assets) => Self::ExpectAsset(assets.try_into()?),
213
			ExpectOrigin(maybe_location) => Self::ExpectOrigin(
213
				maybe_location.map(|location| location.try_into()).transpose().map_err(|_| ())?,
			),
330
			ExpectError(maybe_error) => Self::ExpectError(
330
				maybe_error.map(|error| error.try_into()).transpose().map_err(|_| ())?,
			),
954
			ExpectTransactStatus(maybe_error_code) => Self::ExpectTransactStatus(maybe_error_code),
408
			QueryPallet { module_name, response_info } => Self::QueryPallet {
408
				module_name,
408
				response_info: response_info.try_into().map_err(|_| ())?,
			},
228
			ExpectPallet { index, name, module_name, crate_major, min_crate_minor } =>
228
				Self::ExpectPallet { index, name, module_name, crate_major, min_crate_minor },
291
			ReportTransactStatus(response_info) =>
291
				Self::ReportTransactStatus(response_info.try_into().map_err(|_| ())?),
2211
			ClearTransactStatus => Self::ClearTransactStatus,
387
			UniversalOrigin(junction) =>
387
				Self::UniversalOrigin(junction.try_into().map_err(|_| ())?),
777
			ExportMessage { network, destination, xcm } => Self::ExportMessage {
777
				network: network.into(),
777
				destination: destination.try_into().map_err(|_| ())?,
777
				xcm: xcm.try_into().map_err(|_| ())?,
			},
168
			LockAsset { asset, unlocker } => Self::LockAsset {
168
				asset: asset.try_into().map_err(|_| ())?,
165
				unlocker: unlocker.try_into().map_err(|_| ())?,
			},
120
			UnlockAsset { asset, target } => Self::UnlockAsset {
120
				asset: asset.try_into().map_err(|_| ())?,
114
				target: target.try_into().map_err(|_| ())?,
			},
66
			NoteUnlockable { asset, owner } => Self::NoteUnlockable {
66
				asset: asset.try_into().map_err(|_| ())?,
63
				owner: owner.try_into().map_err(|_| ())?,
			},
165
			RequestUnlock { asset, locker } => Self::RequestUnlock {
165
				asset: asset.try_into().map_err(|_| ())?,
159
				locker: locker.try_into().map_err(|_| ())?,
			},
87
			SetFeesMode { jit_withdraw } => Self::SetFeesMode { jit_withdraw },
675
			SetTopic(topic) => Self::SetTopic(topic),
1392
			ClearTopic => Self::ClearTopic,
234
			AliasOrigin(location) => Self::AliasOrigin(location.try_into().map_err(|_| ())?),
378
			UnpaidExecution { weight_limit, check_origin } => Self::UnpaidExecution {
378
				weight_limit,
378
				check_origin: check_origin
378
					.map(|location| location.try_into())
378
					.transpose()
378
					.map_err(|_| ())?,
			},
		})
203529
	}
}
#[cfg(test)]
mod tests {
	use super::{prelude::*, *};
	use crate::v3::{
		Junctions::Here as OldHere, MultiAssetFilter as OldMultiAssetFilter,
		WildMultiAsset as OldWildMultiAsset,
	};
	#[test]
	fn basic_roundtrip_works() {
		let xcm = Xcm::<()>(vec![TransferAsset {
			assets: (Here, 1u128).into(),
			beneficiary: Here.into(),
		}]);
		let old_xcm = OldXcm::<()>(vec![OldInstruction::TransferAsset {
			assets: (OldHere, 1u128).into(),
			beneficiary: OldHere.into(),
		}]);
		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
		assert_eq!(new_xcm, xcm);
	}
	#[test]
	fn teleport_roundtrip_works() {
		let xcm = Xcm::<()>(vec![
			ReceiveTeleportedAsset((Here, 1u128).into()),
			ClearOrigin,
			DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
		]);
		let old_xcm: OldXcm<()> = OldXcm::<()>(vec![
			OldInstruction::ReceiveTeleportedAsset((OldHere, 1u128).into()),
			OldInstruction::ClearOrigin,
			OldInstruction::DepositAsset {
				assets: crate::v3::MultiAssetFilter::Wild(crate::v3::WildMultiAsset::AllCounted(1)),
				beneficiary: OldHere.into(),
			},
		]);
		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
		assert_eq!(new_xcm, xcm);
	}
	#[test]
	fn reserve_deposit_roundtrip_works() {
		let xcm = Xcm::<()>(vec![
			ReserveAssetDeposited((Here, 1u128).into()),
			ClearOrigin,
			BuyExecution {
				fees: (Here, 1u128).into(),
				weight_limit: Some(Weight::from_parts(1, 1)).into(),
			},
			DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
		]);
		let old_xcm = OldXcm::<()>(vec![
			OldInstruction::ReserveAssetDeposited((OldHere, 1u128).into()),
			OldInstruction::ClearOrigin,
			OldInstruction::BuyExecution {
				fees: (OldHere, 1u128).into(),
				weight_limit: WeightLimit::Limited(Weight::from_parts(1, 1)),
			},
			OldInstruction::DepositAsset {
				assets: crate::v3::MultiAssetFilter::Wild(crate::v3::WildMultiAsset::AllCounted(1)),
				beneficiary: OldHere.into(),
			},
		]);
		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
		assert_eq!(new_xcm, xcm);
	}
	#[test]
	fn deposit_asset_roundtrip_works() {
		let xcm = Xcm::<()>(vec![
			WithdrawAsset((Here, 1u128).into()),
			DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Here.into() },
		]);
		let old_xcm = OldXcm::<()>(vec![
			OldInstruction::WithdrawAsset((OldHere, 1u128).into()),
			OldInstruction::DepositAsset {
				assets: OldMultiAssetFilter::Wild(OldWildMultiAsset::AllCounted(1)),
				beneficiary: OldHere.into(),
			},
		]);
		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
		assert_eq!(new_xcm, xcm);
	}
	#[test]
	fn deposit_reserve_asset_roundtrip_works() {
		let xcm = Xcm::<()>(vec![
			WithdrawAsset((Here, 1u128).into()),
			DepositReserveAsset {
				assets: Wild(AllCounted(1)),
				dest: Here.into(),
				xcm: Xcm::<()>(vec![]),
			},
		]);
		let old_xcm = OldXcm::<()>(vec![
			OldInstruction::WithdrawAsset((OldHere, 1u128).into()),
			OldInstruction::DepositReserveAsset {
				assets: OldMultiAssetFilter::Wild(OldWildMultiAsset::AllCounted(1)),
				dest: OldHere.into(),
				xcm: OldXcm::<()>(vec![]),
			},
		]);
		assert_eq!(old_xcm, OldXcm::<()>::try_from(xcm.clone()).unwrap());
		let new_xcm: Xcm<()> = old_xcm.try_into().unwrap();
		assert_eq!(new_xcm, xcm);
	}
	#[test]
	fn decoding_respects_limit() {
		let max_xcm = Xcm::<()>(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE as usize]);
		let encoded = max_xcm.encode();
		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_ok());
		let big_xcm = Xcm::<()>(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE as usize + 1]);
		let encoded = big_xcm.encode();
		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
		let nested_xcm = Xcm::<()>(vec![
			DepositReserveAsset {
				assets: All.into(),
				dest: Here.into(),
				xcm: max_xcm,
			};
			(MAX_INSTRUCTIONS_TO_DECODE / 2) as usize
		]);
		let encoded = nested_xcm.encode();
		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
		let even_more_nested_xcm = Xcm::<()>(vec![SetAppendix(nested_xcm); 64]);
		let encoded = even_more_nested_xcm.encode();
		assert_eq!(encoded.len(), 342530);
		// This should not decode since the limit is 100
		assert_eq!(MAX_INSTRUCTIONS_TO_DECODE, 100, "precondition");
		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
	}
}