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 3 of the Cross-Consensus Message format data structures.
18

            
19
#[allow(deprecated)]
20
use super::v2::{
21
	Instruction as OldInstruction, OriginKind as OldOriginKind, Response as OldResponse,
22
	WeightLimit as OldWeightLimit, Xcm as OldXcm,
23
};
24
use super::v4::{
25
	Instruction as NewInstruction, PalletInfo as NewPalletInfo,
26
	QueryResponseInfo as NewQueryResponseInfo, Response as NewResponse, Xcm as NewXcm,
27
};
28
use crate::DoubleEncoded;
29
use alloc::{vec, vec::Vec};
30
use bounded_collections::{parameter_types, BoundedVec};
31
use codec::{
32
	self, decode_vec_with_len, Compact, Decode, Encode, Error as CodecError, Input as CodecInput,
33
	MaxEncodedLen,
34
};
35
use core::{fmt::Debug, result};
36
use derivative::Derivative;
37
use scale_info::TypeInfo;
38

            
39
mod junction;
40
pub(crate) mod junctions;
41
mod multiasset;
42
mod multilocation;
43
mod traits;
44

            
45
pub use junction::{BodyId, BodyPart, Junction, NetworkId};
46
pub use junctions::Junctions;
47
pub use multiasset::{
48
	AssetId, AssetInstance, Fungibility, MultiAsset, MultiAssetFilter, MultiAssets,
49
	WildFungibility, WildMultiAsset, MAX_ITEMS_IN_MULTIASSETS,
50
};
51
pub use multilocation::{
52
	Ancestor, AncestorThen, InteriorMultiLocation, Location, MultiLocation, Parent, ParentThen,
53
};
54
pub use traits::{
55
	send_xcm, validate_send, Error, ExecuteXcm, GetWeight, Outcome, PreparedMessage, Result,
56
	SendError, SendResult, SendXcm, Weight, XcmHash,
57
};
58

            
59
/// Basically just the XCM (more general) version of `ParachainDispatchOrigin`.
60
45
#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
61
#[scale_info(replace_segment("staging_xcm", "xcm"))]
62
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
63
pub enum OriginKind {
64
11814
	/// Origin should just be the native dispatch origin representation for the sender in the
65
11814
	/// local runtime framework. For Cumulus/Frame chains this is the `Parachain` or `Relay` origin
66
11814
	/// if coming from a chain, though there may be others if the `MultiLocation` XCM origin has a
67
11814
	/// primary/native dispatch origin form.
68
11814
	Native,
69

            
70
93
	/// Origin should just be the standard account-based origin with the sovereign account of
71
93
	/// the sender. For Cumulus/Frame chains, this is the `Signed` origin.
72
93
	SovereignAccount,
73

            
74
75
	/// Origin should be the super-user. For Cumulus/Frame chains, this is the `Root` origin.
75
75
	/// This will not usually be an available option.
76
75
	Superuser,
77

            
78
54
	/// Origin should be interpreted as an XCM native origin and the `MultiLocation` should be
79
54
	/// encoded directly in the dispatch origin unchanged. For Cumulus/Frame chains, this will be
80
54
	/// the `pallet_xcm::Origin::Xcm` type.
81
54
	Xcm,
82
}
83

            
84
impl From<OldOriginKind> for OriginKind {
85
1035
	fn from(old: OldOriginKind) -> Self {
86
		use OldOriginKind::*;
87
1035
		match old {
88
800
			Native => Self::Native,
89
235
			SovereignAccount => Self::SovereignAccount,
90
			Superuser => Self::Superuser,
91
			Xcm => Self::Xcm,
92
		}
93
1035
	}
94
}
95

            
96
/// This module's XCM version.
97
pub const VERSION: super::Version = 3;
98

            
99
/// An identifier for a query.
100
pub type QueryId = u64;
101

            
102
26815
#[derive(Derivative, Default, Encode, TypeInfo)]
103
#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
104
#[codec(encode_bound())]
105
#[scale_info(bounds(), skip_type_params(Call))]
106
#[scale_info(replace_segment("staging_xcm", "xcm"))]
107
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
108
pub struct Xcm<Call>(pub Vec<Instruction<Call>>);
109

            
110
/// The maximal number of instructions in an XCM before decoding fails.
111
///
112
/// This is a deliberate limit - not a technical one.
113
pub const MAX_INSTRUCTIONS_TO_DECODE: u8 = 100;
114

            
115
environmental::environmental!(instructions_count: u8);
116

            
117
impl<Call> Decode for Xcm<Call> {
118
29787
	fn decode<I: CodecInput>(input: &mut I) -> core::result::Result<Self, CodecError> {
119
29787
		instructions_count::using_once(&mut 0, || {
120
29787
			let number_of_instructions: u32 = <Compact<u32>>::decode(input)?.into();
121
29667
			instructions_count::with(|count| {
122
29667
				*count = count.saturating_add(number_of_instructions as u8);
123
29667
				if *count > MAX_INSTRUCTIONS_TO_DECODE {
124
66
					return Err(CodecError::from("Max instructions exceeded"))
125
29601
				}
126
29601
				Ok(())
127
29667
			})
128
29667
			.unwrap_or(Ok(()))?;
129
29601
			let decoded_instructions = decode_vec_with_len(input, number_of_instructions as usize)?;
130
22443
			Ok(Self(decoded_instructions))
131
29787
		})
132
29787
	}
133
}
134

            
135
impl<Call> Xcm<Call> {
136
	/// Create an empty instance.
137
	pub fn new() -> Self {
138
		Self(vec![])
139
	}
140

            
141
	/// Return `true` if no instructions are held in `self`.
142
	pub fn is_empty(&self) -> bool {
143
		self.0.is_empty()
144
	}
145

            
146
	/// Return the number of instructions held in `self`.
147
	pub fn len(&self) -> usize {
148
		self.0.len()
149
	}
150

            
151
	/// Return a reference to the inner value.
152
	pub fn inner(&self) -> &[Instruction<Call>] {
153
		&self.0
154
	}
155

            
156
	/// Return a mutable reference to the inner value.
157
	pub fn inner_mut(&mut self) -> &mut Vec<Instruction<Call>> {
158
		&mut self.0
159
	}
160

            
161
	/// Consume and return the inner value.
162
	pub fn into_inner(self) -> Vec<Instruction<Call>> {
163
		self.0
164
	}
165

            
166
	/// Return an iterator over references to the items.
167
	pub fn iter(&self) -> impl Iterator<Item = &Instruction<Call>> {
168
		self.0.iter()
169
	}
170

            
171
	/// Return an iterator over mutable references to the items.
172
	pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Instruction<Call>> {
173
		self.0.iter_mut()
174
	}
175

            
176
	/// Consume and return an iterator over the items.
177
	pub fn into_iter(self) -> impl Iterator<Item = Instruction<Call>> {
178
		self.0.into_iter()
179
	}
180

            
181
	/// Consume and either return `self` if it contains some instructions, or if it's empty, then
182
	/// instead return the result of `f`.
183
	pub fn or_else(self, f: impl FnOnce() -> Self) -> Self {
184
		if self.0.is_empty() {
185
			f()
186
		} else {
187
			self
188
		}
189
	}
190

            
191
	/// Return the first instruction, if any.
192
	pub fn first(&self) -> Option<&Instruction<Call>> {
193
		self.0.first()
194
	}
195

            
196
	/// Return the last instruction, if any.
197
	pub fn last(&self) -> Option<&Instruction<Call>> {
198
		self.0.last()
199
	}
200

            
201
	/// Return the only instruction, contained in `Self`, iff only one exists (`None` otherwise).
202
	pub fn only(&self) -> Option<&Instruction<Call>> {
203
		if self.0.len() == 1 {
204
			self.0.first()
205
		} else {
206
			None
207
		}
208
	}
209

            
210
	/// Return the only instruction, contained in `Self`, iff only one exists (returns `self`
211
	/// otherwise).
212
	pub fn into_only(mut self) -> core::result::Result<Instruction<Call>, Self> {
213
		if self.0.len() == 1 {
214
			self.0.pop().ok_or(self)
215
		} else {
216
			Err(self)
217
		}
218
	}
219
}
220

            
221
impl<Call> From<Vec<Instruction<Call>>> for Xcm<Call> {
222
	fn from(c: Vec<Instruction<Call>>) -> Self {
223
		Self(c)
224
	}
225
}
226

            
227
impl<Call> From<Xcm<Call>> for Vec<Instruction<Call>> {
228
	fn from(c: Xcm<Call>) -> Self {
229
		c.0
230
	}
231
}
232

            
233
/// A prelude for importing all types typically used when interacting with XCM messages.
234
pub mod prelude {
235
	mod contents {
236
		pub use super::super::{
237
			send_xcm, validate_send, Ancestor, AncestorThen,
238
			AssetId::{self, *},
239
			AssetInstance::{self, *},
240
			BodyId, BodyPart, Error as XcmError, ExecuteXcm,
241
			Fungibility::{self, *},
242
			GetWeight,
243
			Instruction::*,
244
			InteriorMultiLocation,
245
			Junction::{self, *},
246
			Junctions::{self, *},
247
			Location, MaybeErrorCode, MultiAsset,
248
			MultiAssetFilter::{self, *},
249
			MultiAssets, MultiLocation,
250
			NetworkId::{self, *},
251
			OriginKind, Outcome, PalletInfo, Parent, ParentThen, PreparedMessage, QueryId,
252
			QueryResponseInfo, Response, Result as XcmResult, SendError, SendResult, SendXcm,
253
			Weight,
254
			WeightLimit::{self, *},
255
			WildFungibility::{self, Fungible as WildFungible, NonFungible as WildNonFungible},
256
			WildMultiAsset::{self, *},
257
			XcmContext, XcmHash, XcmWeightInfo, VERSION as XCM_VERSION,
258
		};
259
	}
260
	pub use super::{Instruction, Xcm};
261
	pub use contents::*;
262
	pub mod opaque {
263
		pub use super::{
264
			super::opaque::{Instruction, Xcm},
265
			contents::*,
266
		};
267
	}
268
}
269

            
270
parameter_types! {
271
	#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
272
	pub MaxPalletNameLen: u32 = 48;
273
	/// Maximum size of the encoded error code coming from a `Dispatch` result, used for
274
	/// `MaybeErrorCode`. This is not (yet) enforced, so it's just an indication of expectation.
275
	#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
276
	pub MaxDispatchErrorLen: u32 = 128;
277
	#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
278
	pub MaxPalletsInfo: u32 = 64;
279
}
280

            
281
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
282
#[scale_info(replace_segment("staging_xcm", "xcm"))]
283
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
284
pub struct PalletInfo {
285
	#[codec(compact)]
286
	pub index: u32,
287
	pub name: BoundedVec<u8, MaxPalletNameLen>,
288
	pub module_name: BoundedVec<u8, MaxPalletNameLen>,
289
	#[codec(compact)]
290
	pub major: u32,
291
	#[codec(compact)]
292
	pub minor: u32,
293
	#[codec(compact)]
294
	pub patch: u32,
295
}
296

            
297
impl PalletInfo {
298
	pub fn new(
299
		index: u32,
300
		name: Vec<u8>,
301
		module_name: Vec<u8>,
302
		major: u32,
303
		minor: u32,
304
		patch: u32,
305
	) -> result::Result<Self, Error> {
306
		let name = BoundedVec::try_from(name).map_err(|_| Error::Overflow)?;
307
		let module_name = BoundedVec::try_from(module_name).map_err(|_| Error::Overflow)?;
308

            
309
		Ok(Self { index, name, module_name, major, minor, patch })
310
	}
311
}
312

            
313
impl TryInto<NewPalletInfo> for PalletInfo {
314
	type Error = ();
315

            
316
264
	fn try_into(self) -> result::Result<NewPalletInfo, Self::Error> {
317
264
		NewPalletInfo::new(
318
264
			self.index,
319
264
			self.name.into_inner(),
320
264
			self.module_name.into_inner(),
321
264
			self.major,
322
264
			self.minor,
323
264
			self.patch,
324
264
		)
325
264
		.map_err(|_| ())
326
264
	}
327
}
328

            
329
39
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
330
#[scale_info(replace_segment("staging_xcm", "xcm"))]
331
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
332
pub enum MaybeErrorCode {
333
4059
	Success,
334
942
	Error(BoundedVec<u8, MaxDispatchErrorLen>),
335
1050
	TruncatedError(BoundedVec<u8, MaxDispatchErrorLen>),
336
}
337

            
338
impl From<Vec<u8>> for MaybeErrorCode {
339
2
	fn from(v: Vec<u8>) -> Self {
340
2
		match BoundedVec::try_from(v) {
341
2
			Ok(error) => MaybeErrorCode::Error(error),
342
			Err(error) => MaybeErrorCode::TruncatedError(BoundedVec::truncate_from(error)),
343
		}
344
2
	}
345
}
346

            
347
impl Default for MaybeErrorCode {
348
27916
	fn default() -> MaybeErrorCode {
349
27916
		MaybeErrorCode::Success
350
27916
	}
351
}
352

            
353
/// Response data to a query.
354
12
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
355
#[scale_info(replace_segment("staging_xcm", "xcm"))]
356
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
357
pub enum Response {
358
870
	/// No response. Serves as a neutral default.
359
870
	Null,
360
123
	/// Some assets.
361
123
	Assets(MultiAssets),
362
129
	/// The outcome of an XCM instruction.
363
129
	ExecutionResult(Option<(u32, Error)>),
364
69
	/// An XCM version.
365
69
	Version(super::Version),
366
225
	/// The index, instance name, pallet name and version of some pallets.
367
225
	PalletsInfo(BoundedVec<PalletInfo, MaxPalletsInfo>),
368
87
	/// The status of a dispatch attempt using `Transact`.
369
87
	DispatchResult(MaybeErrorCode),
370
}
371

            
372
impl Default for Response {
373
	fn default() -> Self {
374
		Self::Null
375
	}
376
}
377

            
378
impl TryFrom<NewResponse> for Response {
379
	type Error = ();
380

            
381
	fn try_from(new: NewResponse) -> result::Result<Self, Self::Error> {
382
		use NewResponse::*;
383
		Ok(match new {
384
			Null => Self::Null,
385
			Assets(assets) => Self::Assets(assets.try_into()?),
386
			ExecutionResult(result) =>
387
				Self::ExecutionResult(result.map(|(num, old_error)| (num, old_error.into()))),
388
			Version(version) => Self::Version(version),
389
			PalletsInfo(pallet_info) => {
390
				let inner = pallet_info
391
					.into_iter()
392
					.map(TryInto::try_into)
393
					.collect::<result::Result<Vec<_>, _>>()?;
394
				Self::PalletsInfo(
395
					BoundedVec::<PalletInfo, MaxPalletsInfo>::try_from(inner).map_err(|_| ())?,
396
				)
397
			},
398
			DispatchResult(maybe_error) =>
399
				Self::DispatchResult(maybe_error.try_into().map_err(|_| ())?),
400
		})
401
	}
402
}
403

            
404
/// Information regarding the composition of a query response.
405
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
406
#[scale_info(replace_segment("staging_xcm", "xcm"))]
407
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
408
pub struct QueryResponseInfo {
409
	/// The destination to which the query response message should be send.
410
	pub destination: MultiLocation,
411
	/// The `query_id` field of the `QueryResponse` message.
412
	#[codec(compact)]
413
	pub query_id: QueryId,
414
	/// The `max_weight` field of the `QueryResponse` message.
415
	pub max_weight: Weight,
416
}
417

            
418
impl TryFrom<NewQueryResponseInfo> for QueryResponseInfo {
419
	type Error = ();
420

            
421
	fn try_from(new: NewQueryResponseInfo) -> result::Result<Self, Self::Error> {
422
		Ok(Self {
423
			destination: new.destination.try_into()?,
424
			query_id: new.query_id,
425
			max_weight: new.max_weight,
426
		})
427
	}
428
}
429

            
430
/// An optional weight limit.
431
63
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
432
#[scale_info(replace_segment("staging_xcm", "xcm"))]
433
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
434
pub enum WeightLimit {
435
2307
	/// No weight limit imposed.
436
2307
	Unlimited,
437
369
	/// Weight limit imposed of the inner value.
438
369
	Limited(Weight),
439
}
440

            
441
impl From<Option<Weight>> for WeightLimit {
442
	fn from(x: Option<Weight>) -> Self {
443
		match x {
444
			Some(w) => WeightLimit::Limited(w),
445
			None => WeightLimit::Unlimited,
446
		}
447
	}
448
}
449

            
450
impl From<WeightLimit> for Option<Weight> {
451
212
	fn from(x: WeightLimit) -> Self {
452
212
		match x {
453
36
			WeightLimit::Limited(w) => Some(w),
454
176
			WeightLimit::Unlimited => None,
455
		}
456
212
	}
457
}
458

            
459
impl From<OldWeightLimit> for WeightLimit {
460
1005
	fn from(x: OldWeightLimit) -> Self {
461
		use OldWeightLimit::*;
462
1005
		match x {
463
70
			Limited(w) => Self::Limited(Weight::from_parts(w, DEFAULT_PROOF_SIZE)),
464
935
			Unlimited => Self::Unlimited,
465
		}
466
1005
	}
467
}
468

            
469
/// Contextual data pertaining to a specific list of XCM instructions.
470
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)]
471
pub struct XcmContext {
472
	/// The current value of the Origin register of the `XCVM`.
473
	pub origin: Option<MultiLocation>,
474
	/// The identity of the XCM; this may be a hash of its versioned encoding but could also be
475
	/// a high-level identity set by an appropriate barrier.
476
	pub message_id: XcmHash,
477
	/// The current value of the Topic register of the `XCVM`.
478
	pub topic: Option<[u8; 32]>,
479
}
480

            
481
impl XcmContext {
482
	/// Constructor which sets the message ID to the supplied parameter and leaves the origin and
483
	/// topic unset.
484
	#[deprecated = "Use `with_message_id` instead."]
485
	pub fn with_message_hash(message_id: XcmHash) -> XcmContext {
486
		XcmContext { origin: None, message_id, topic: None }
487
	}
488

            
489
	/// Constructor which sets the message ID to the supplied parameter and leaves the origin and
490
	/// topic unset.
491
	pub fn with_message_id(message_id: XcmHash) -> XcmContext {
492
		XcmContext { origin: None, message_id, topic: None }
493
	}
494
}
495

            
496
/// Cross-Consensus Message: A message from one consensus system to another.
497
///
498
/// Consensus systems that may send and receive messages include blockchains and smart contracts.
499
///
500
/// All messages are delivered from a known *origin*, expressed as a `MultiLocation`.
501
///
502
/// This is the inner XCM format and is version-sensitive. Messages are typically passed using the
503
/// outer XCM format, known as `VersionedXcm`.
504
#[derive(
505
738357
	Derivative,
506
	Encode,
507
885
	Decode,
508
	TypeInfo,
509
	xcm_procedural::XcmWeightInfoTrait,
510
	xcm_procedural::Builder,
511
)]
512
#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
513
#[codec(encode_bound())]
514
#[codec(decode_bound())]
515
#[scale_info(bounds(), skip_type_params(Call))]
516
#[scale_info(replace_segment("staging_xcm", "xcm"))]
517
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
518
pub enum Instruction<Call> {
519
192999
	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place them into the Holding
520
	/// Register.
521
	///
522
	/// - `assets`: The asset(s) to be withdrawn into holding.
523
	///
524
	/// Kind: *Command*.
525
	///
526
	/// Errors:
527
	#[builder(loads_holding)]
528
192999
	WithdrawAsset(MultiAssets),
529

            
530
4299
	/// Asset(s) (`assets`) have been received into the ownership of this system on the `origin`
531
	/// system and equivalent derivatives should be placed into the Holding Register.
532
	///
533
	/// - `assets`: The asset(s) that are minted into holding.
534
	///
535
	/// Safety: `origin` must be trusted to have received and be storing `assets` such that they
536
	/// may later be withdrawn should this system send a corresponding message.
537
	///
538
	/// Kind: *Trusted Indication*.
539
	///
540
	/// Errors:
541
	#[builder(loads_holding)]
542
4299
	ReserveAssetDeposited(MultiAssets),
543

            
544
2019
	/// Asset(s) (`assets`) have been destroyed on the `origin` system and equivalent assets should
545
	/// be created and placed into the Holding Register.
546
	///
547
	/// - `assets`: The asset(s) that are minted into the Holding Register.
548
	///
549
	/// Safety: `origin` must be trusted to have irrevocably destroyed the corresponding `assets`
550
	/// prior as a consequence of sending this message.
551
	///
552
	/// Kind: *Trusted Indication*.
553
	///
554
	/// Errors:
555
	#[builder(loads_holding)]
556
2019
	ReceiveTeleportedAsset(MultiAssets),
557

            
558
1545
	/// Respond with information that the local system is expecting.
559
	///
560
	/// - `query_id`: The identifier of the query that resulted in this message being sent.
561
	/// - `response`: The message content.
562
	/// - `max_weight`: The maximum weight that handling this response should take.
563
	/// - `querier`: The location responsible for the initiation of the response, if there is one.
564
	///   In general this will tend to be the same location as the receiver of this message. NOTE:
565
	///   As usual, this is interpreted from the perspective of the receiving consensus system.
566
	///
567
	/// Safety: Since this is information only, there are no immediate concerns. However, it should
568
	/// be remembered that even if the Origin behaves reasonably, it can always be asked to make
569
	/// a response to a third-party chain who may or may not be expecting the response. Therefore
570
	/// the `querier` should be checked to match the expected value.
571
	///
572
	/// Kind: *Information*.
573
	///
574
	/// Errors:
575
	QueryResponse {
576
30
		#[codec(compact)]
577
30
		query_id: QueryId,
578
168
		response: Response,
579
45
		max_weight: Weight,
580
69
		querier: Option<MultiLocation>,
581
1545
	},
582

            
583
1821
	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets
584
	/// under the ownership of `beneficiary`.
585
	///
586
	/// - `assets`: The asset(s) to be withdrawn.
587
	/// - `beneficiary`: The new owner for the assets.
588
	///
589
	/// Safety: No concerns.
590
	///
591
	/// Kind: *Command*.
592
	///
593
	/// Errors:
594
1821
	TransferAsset { assets: MultiAssets, beneficiary: MultiLocation },
595

            
596
1635
	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets
597
	/// under the ownership of `dest` within this consensus system (i.e. its sovereign account).
598
	///
599
	/// Send an onward XCM message to `dest` of `ReserveAssetDeposited` with the given
600
	/// `xcm`.
601
	///
602
	/// - `assets`: The asset(s) to be withdrawn.
603
	/// - `dest`: The location whose sovereign account will own the assets and thus the effective
604
	///   beneficiary for the assets and the notification target for the reserve asset deposit
605
	///   message.
606
	/// - `xcm`: The instructions that should follow the `ReserveAssetDeposited` instruction, which
607
	///   is sent onwards to `dest`.
608
	///
609
	/// Safety: No concerns.
610
	///
611
	/// Kind: *Command*.
612
	///
613
	/// Errors:
614
1635
	TransferReserveAsset { assets: MultiAssets, dest: MultiLocation, xcm: Xcm<()> },
615

            
616
1440
	/// Apply the encoded transaction `call`, whose dispatch-origin should be `origin` as expressed
617
	/// by the kind of origin `origin_kind`.
618
	///
619
	/// The Transact Status Register is set according to the result of dispatching the call.
620
	///
621
	/// - `origin_kind`: The means of expressing the message origin as a dispatch origin.
622
	/// - `require_weight_at_most`: The weight of `call`; this should be at least the chain's
623
	///   calculated weight and will be used in the weight determination arithmetic.
624
	/// - `call`: The encoded transaction to be applied.
625
	///
626
	/// Safety: No concerns.
627
	///
628
	/// Kind: *Command*.
629
	///
630
	/// Errors:
631
1440
	Transact { origin_kind: OriginKind, require_weight_at_most: Weight, call: DoubleEncoded<Call> },
632

            
633
603
	/// A message to notify about a new incoming HRMP channel. This message is meant to be sent by
634
	/// the relay-chain to a para.
635
	///
636
	/// - `sender`: The sender in the to-be opened channel. Also, the initiator of the channel
637
	///   opening.
638
	/// - `max_message_size`: The maximum size of a message proposed by the sender.
639
	/// - `max_capacity`: The maximum number of messages that can be queued in the channel.
640
	///
641
	/// Safety: The message should originate directly from the relay-chain.
642
	///
643
	/// Kind: *System Notification*
644
	HrmpNewChannelOpenRequest {
645
12
		#[codec(compact)]
646
12
		sender: u32,
647
9
		#[codec(compact)]
648
9
		max_message_size: u32,
649
18
		#[codec(compact)]
650
18
		max_capacity: u32,
651
603
	},
652

            
653
5691
	/// A message to notify about that a previously sent open channel request has been accepted by
654
	/// the recipient. That means that the channel will be opened during the next relay-chain
655
	/// session change. This message is meant to be sent by the relay-chain to a para.
656
	///
657
	/// Safety: The message should originate directly from the relay-chain.
658
	///
659
	/// Kind: *System Notification*
660
	///
661
	/// Errors:
662
	HrmpChannelAccepted {
663
		// NOTE: We keep this as a structured item to a) keep it consistent with the other Hrmp
664
		// items; and b) because the field's meaning is not obvious/mentioned from the item name.
665
18
		#[codec(compact)]
666
18
		recipient: u32,
667
5691
	},
668

            
669
1530
	/// A message to notify that the other party in an open channel decided to close it. In
670
	/// particular, `initiator` is going to close the channel opened from `sender` to the
671
	/// `recipient`. The close will be enacted at the next relay-chain session change. This message
672
	/// is meant to be sent by the relay-chain to a para.
673
	///
674
	/// Safety: The message should originate directly from the relay-chain.
675
	///
676
	/// Kind: *System Notification*
677
	///
678
	/// Errors:
679
	HrmpChannelClosing {
680
9
		#[codec(compact)]
681
9
		initiator: u32,
682
9
		#[codec(compact)]
683
9
		sender: u32,
684
9
		#[codec(compact)]
685
9
		recipient: u32,
686
1530
	},
687

            
688
26736
	/// Clear the origin.
689
26736
	///
690
26736
	/// This may be used by the XCM author to ensure that later instructions cannot command the
691
26736
	/// authority of the origin (e.g. if they are being relayed from an untrusted source, as often
692
26736
	/// the case with `ReserveAssetDeposited`).
693
26736
	///
694
26736
	/// Safety: No concerns.
695
26736
	///
696
26736
	/// Kind: *Command*.
697
26736
	///
698
26736
	/// Errors:
699
26736
	ClearOrigin,
700

            
701
624
	/// Mutate the origin to some interior location.
702
	///
703
	/// Kind: *Command*
704
	///
705
	/// Errors:
706
624
	DescendOrigin(InteriorMultiLocation),
707

            
708
1077
	/// Immediately report the contents of the Error Register to the given destination via XCM.
709
	///
710
	/// A `QueryResponse` message of type `ExecutionOutcome` is sent to the described destination.
711
	///
712
	/// - `response_info`: Information for making the response.
713
	///
714
	/// Kind: *Command*
715
	///
716
	/// Errors:
717
1077
	ReportError(QueryResponseInfo),
718

            
719
774
	/// Remove the asset(s) (`assets`) from the Holding Register and place equivalent assets under
720
	/// the ownership of `beneficiary` within this consensus system.
721
	///
722
	/// - `assets`: The asset(s) to remove from holding.
723
	/// - `beneficiary`: The new owner for the assets.
724
	///
725
	/// Kind: *Command*
726
	///
727
	/// Errors:
728
774
	DepositAsset { assets: MultiAssetFilter, beneficiary: MultiLocation },
729

            
730
957
	/// Remove the asset(s) (`assets`) from the Holding Register and place equivalent assets under
731
	/// the ownership of `dest` within this consensus system (i.e. deposit them into its sovereign
732
	/// account).
733
	///
734
	/// Send an onward XCM message to `dest` of `ReserveAssetDeposited` with the given `effects`.
735
	///
736
	/// - `assets`: The asset(s) to remove from holding.
737
	/// - `dest`: The location whose sovereign account will own the assets and thus the effective
738
	///   beneficiary for the assets and the notification target for the reserve asset deposit
739
	///   message.
740
	/// - `xcm`: The orders that should follow the `ReserveAssetDeposited` instruction which is
741
	///   sent onwards to `dest`.
742
	///
743
	/// Kind: *Command*
744
	///
745
	/// Errors:
746
957
	DepositReserveAsset { assets: MultiAssetFilter, dest: MultiLocation, xcm: Xcm<()> },
747

            
748
1020
	/// Remove the asset(s) (`want`) from the Holding Register and replace them with alternative
749
	/// assets.
750
	///
751
	/// The minimum amount of assets to be received into the Holding Register for the order not to
752
	/// fail may be stated.
753
	///
754
	/// - `give`: The maximum amount of assets to remove from holding.
755
	/// - `want`: The minimum amount of assets which `give` should be exchanged for.
756
	/// - `maximal`: If `true`, then prefer to give as much as possible up to the limit of `give`
757
	///   and receive accordingly more. If `false`, then prefer to give as little as possible in
758
	///   order to receive as little as possible while receiving at least `want`.
759
	///
760
	/// Kind: *Command*
761
	///
762
	/// Errors:
763
1020
	ExchangeAsset { give: MultiAssetFilter, want: MultiAssets, maximal: bool },
764

            
765
4830
	/// Remove the asset(s) (`assets`) from holding and send a `WithdrawAsset` XCM message to a
766
	/// reserve location.
767
	///
768
	/// - `assets`: The asset(s) to remove from holding.
769
	/// - `reserve`: A valid location that acts as a reserve for all asset(s) in `assets`. The
770
	///   sovereign account of this consensus system *on the reserve location* will have
771
	///   appropriate assets withdrawn and `effects` will be executed on them. There will typically
772
	///   be only one valid location on any given asset/chain combination.
773
	/// - `xcm`: The instructions to execute on the assets once withdrawn *on the reserve
774
	///   location*.
775
	///
776
	/// Kind: *Command*
777
	///
778
	/// Errors:
779
4830
	InitiateReserveWithdraw { assets: MultiAssetFilter, reserve: MultiLocation, xcm: Xcm<()> },
780

            
781
2271
	/// Remove the asset(s) (`assets`) from holding and send a `ReceiveTeleportedAsset` XCM message
782
	/// to a `dest` location.
783
	///
784
	/// - `assets`: The asset(s) to remove from holding.
785
	/// - `dest`: A valid location that respects teleports coming from this location.
786
	/// - `xcm`: The instructions to execute on the assets once arrived *on the destination
787
	///   location*.
788
	///
789
	/// NOTE: The `dest` location *MUST* respect this origin as a valid teleportation origin for
790
	/// all `assets`. If it does not, then the assets may be lost.
791
	///
792
	/// Kind: *Command*
793
	///
794
	/// Errors:
795
2271
	InitiateTeleport { assets: MultiAssetFilter, dest: MultiLocation, xcm: Xcm<()> },
796

            
797
624
	/// Report to a given destination the contents of the Holding Register.
798
	///
799
	/// A `QueryResponse` message of type `Assets` is sent to the described destination.
800
	///
801
	/// - `response_info`: Information for making the response.
802
	/// - `assets`: A filter for the assets that should be reported back. The assets reported back
803
	///   will be, asset-wise, *the lesser of this value and the holding register*. No wildcards
804
	///   will be used when reporting assets back.
805
	///
806
	/// Kind: *Command*
807
	///
808
	/// Errors:
809
624
	ReportHolding { response_info: QueryResponseInfo, assets: MultiAssetFilter },
810

            
811
162
	/// Pay for the execution of some XCM `xcm` and `orders` with up to `weight`
812
	/// picoseconds of execution time, paying for this with up to `fees` from the Holding Register.
813
	///
814
	/// - `fees`: The asset(s) to remove from the Holding Register to pay for fees.
815
	/// - `weight_limit`: The maximum amount of weight to purchase; this must be at least the
816
	///   expected maximum weight of the total XCM to be executed for the
817
	///   `AllowTopLevelPaidExecutionFrom` barrier to allow the XCM be executed.
818
	///
819
	/// Kind: *Command*
820
	///
821
	/// Errors:
822
162
	BuyExecution { fees: MultiAsset, weight_limit: WeightLimit },
823

            
824
13221
	/// Refund any surplus weight previously bought with `BuyExecution`.
825
13221
	///
826
13221
	/// Kind: *Command*
827
13221
	///
828
13221
	/// Errors: None.
829
13221
	RefundSurplus,
830

            
831
4008
	/// Set the Error Handler Register. This is code that should be called in the case of an error
832
	/// happening.
833
	///
834
	/// An error occurring within execution of this code will _NOT_ result in the error register
835
	/// being set, nor will an error handler be called due to it. The error handler and appendix
836
	/// may each still be set.
837
	///
838
	/// The apparent weight of this instruction is inclusive of the inner `Xcm`; the executing
839
	/// weight however includes only the difference between the previous handler and the new
840
	/// handler, which can reasonably be negative, which would result in a surplus.
841
	///
842
	/// Kind: *Command*
843
	///
844
	/// Errors: None.
845
4008
	SetErrorHandler(Xcm<Call>),
846

            
847
2865
	/// Set the Appendix Register. This is code that should be called after code execution
848
	/// (including the error handler if any) is finished. This will be called regardless of whether
849
	/// an error occurred.
850
	///
851
	/// Any error occurring due to execution of this code will result in the error register being
852
	/// set, and the error handler (if set) firing.
853
	///
854
	/// The apparent weight of this instruction is inclusive of the inner `Xcm`; the executing
855
	/// weight however includes only the difference between the previous appendix and the new
856
	/// appendix, which can reasonably be negative, which would result in a surplus.
857
	///
858
	/// Kind: *Command*
859
	///
860
	/// Errors: None.
861
2865
	SetAppendix(Xcm<Call>),
862

            
863
3498
	/// Clear the Error Register.
864
3498
	///
865
3498
	/// Kind: *Command*
866
3498
	///
867
3498
	/// Errors: None.
868
3498
	ClearError,
869

            
870
1191
	/// Create some assets which are being held on behalf of the origin.
871
	///
872
	/// - `assets`: The assets which are to be claimed. This must match exactly with the assets
873
	///   claimable by the origin of the ticket.
874
	/// - `ticket`: The ticket of the asset; this is an abstract identifier to help locate the
875
	///   asset.
876
	///
877
	/// Kind: *Command*
878
	///
879
	/// Errors:
880
	#[builder(loads_holding)]
881
1191
	ClaimAsset { assets: MultiAssets, ticket: MultiLocation },
882

            
883
2043
	/// Always throws an error of type `Trap`.
884
	///
885
	/// Kind: *Command*
886
	///
887
	/// Errors:
888
	/// - `Trap`: All circumstances, whose inner value is the same as this item's inner value.
889
2043
	Trap(#[codec(compact)] u64),
890

            
891
1650
	/// Ask the destination system to respond with the most recent version of XCM that they
892
	/// support in a `QueryResponse` instruction. Any changes to this should also elicit similar
893
	/// responses when they happen.
894
	///
895
	/// - `query_id`: An identifier that will be replicated into the returned XCM message.
896
	/// - `max_response_weight`: The maximum amount of weight that the `QueryResponse` item which
897
	///   is sent as a reply may take to execute. NOTE: If this is unexpectedly large then the
898
	///   response may not execute at all.
899
	///
900
	/// Kind: *Command*
901
	///
902
	/// Errors: *Fallible*
903
	SubscribeVersion {
904
12
		#[codec(compact)]
905
12
		query_id: QueryId,
906
18
		max_response_weight: Weight,
907
1650
	},
908

            
909
2526
	/// Cancel the effect of a previous `SubscribeVersion` instruction.
910
2526
	///
911
2526
	/// Kind: *Command*
912
2526
	///
913
2526
	/// Errors: *Fallible*
914
2526
	UnsubscribeVersion,
915

            
916
513
	/// Reduce Holding by up to the given assets.
917
	///
918
	/// Holding is reduced by as much as possible up to the assets in the parameter. It is not an
919
	/// error if the Holding does not contain the assets (to make this an error, use `ExpectAsset`
920
	/// prior).
921
	///
922
	/// Kind: *Command*
923
	///
924
	/// Errors: *Infallible*
925
513
	BurnAsset(MultiAssets),
926

            
927
606
	/// Throw an error if Holding does not contain at least the given assets.
928
	///
929
	/// Kind: *Command*
930
	///
931
	/// Errors:
932
	/// - `ExpectationFalse`: If Holding Register does not contain the assets in the parameter.
933
606
	ExpectAsset(MultiAssets),
934

            
935
399
	/// Ensure that the Origin Register equals some given value and throw an error if not.
936
	///
937
	/// Kind: *Command*
938
	///
939
	/// Errors:
940
	/// - `ExpectationFalse`: If Origin Register is not equal to the parameter.
941
399
	ExpectOrigin(Option<MultiLocation>),
942

            
943
609
	/// Ensure that the Error Register equals some given value and throw an error if not.
944
	///
945
	/// Kind: *Command*
946
	///
947
	/// Errors:
948
	/// - `ExpectationFalse`: If the value of the Error Register is not equal to the parameter.
949
609
	ExpectError(Option<(u32, Error)>),
950

            
951
3219
	/// Ensure that the Transact Status Register equals some given value and throw an error if
952
	/// not.
953
	///
954
	/// Kind: *Command*
955
	///
956
	/// Errors:
957
	/// - `ExpectationFalse`: If the value of the Transact Status Register is not equal to the
958
	///   parameter.
959
3219
	ExpectTransactStatus(MaybeErrorCode),
960

            
961
1698
	/// Query the existence of a particular pallet type.
962
	///
963
	/// - `module_name`: The module name of the pallet to query.
964
	/// - `response_info`: Information for making the response.
965
	///
966
	/// Sends a `QueryResponse` to Origin whose data field `PalletsInfo` containing the information
967
	/// of all pallets on the local chain whose name is equal to `name`. This is empty in the case
968
	/// that the local chain is not based on Substrate Frame.
969
	///
970
	/// Safety: No concerns.
971
	///
972
	/// Kind: *Command*
973
	///
974
	/// Errors: *Fallible*.
975
1698
	QueryPallet { module_name: Vec<u8>, response_info: QueryResponseInfo },
976

            
977
828
	/// Ensure that a particular pallet with a particular version exists.
978
	///
979
	/// - `index: Compact`: The index which identifies the pallet. An error if no pallet exists at
980
	///   this index.
981
	/// - `name: Vec<u8>`: Name which must be equal to the name of the pallet.
982
	/// - `module_name: Vec<u8>`: Module name which must be equal to the name of the module in
983
	///   which the pallet exists.
984
	/// - `crate_major: Compact`: Version number which must be equal to the major version of the
985
	///   crate which implements the pallet.
986
	/// - `min_crate_minor: Compact`: Version number which must be at most the minor version of the
987
	///   crate which implements the pallet.
988
	///
989
	/// Safety: No concerns.
990
	///
991
	/// Kind: *Command*
992
	///
993
	/// Errors:
994
	/// - `ExpectationFalse`: In case any of the expectations are broken.
995
	ExpectPallet {
996
6
		#[codec(compact)]
997
6
		index: u32,
998
15
		name: Vec<u8>,
999
12
		module_name: Vec<u8>,
15
		#[codec(compact)]
15
		crate_major: u32,
9
		#[codec(compact)]
9
		min_crate_minor: u32,
828
	},
828
	/// Send a `QueryResponse` message containing the value of the Transact Status Register to some
	/// destination.
	///
	/// - `query_response_info`: The information needed for constructing and sending the
	///   `QueryResponse` message.
	///
	/// Safety: No concerns.
	///
	/// Kind: *Command*
	///
	/// Errors: *Fallible*.
828
	ReportTransactStatus(QueryResponseInfo),
8355
	/// Set the Transact Status Register to its default, cleared, value.
8355
	///
8355
	/// Safety: No concerns.
8355
	///
8355
	/// Kind: *Command*
8355
	///
8355
	/// Errors: *Infallible*.
8355
	ClearTransactStatus,
2028
	/// Set the Origin Register to be some child of the Universal Ancestor.
	///
	/// Safety: Should only be usable if the Origin is trusted to represent the Universal Ancestor
	/// child in general. In general, no Origin should be able to represent the Universal Ancestor
	/// child which is the root of the local consensus system since it would by extension
	/// allow it to act as any location within the local consensus.
	///
	/// The `Junction` parameter should generally be a `GlobalConsensus` variant since it is only
	/// these which are children of the Universal Ancestor.
	///
	/// Kind: *Command*
	///
	/// Errors: *Fallible*.
2028
	UniversalOrigin(Junction),
2247
	/// Send a message on to Non-Local Consensus system.
	///
	/// This will tend to utilize some extra-consensus mechanism, the obvious one being a bridge.
	/// A fee may be charged; this may be determined based on the contents of `xcm`. It will be
	/// taken from the Holding register.
	///
	/// - `network`: The remote consensus system to which the message should be exported.
	/// - `destination`: The location relative to the remote consensus system to which the message
	///   should be sent on arrival.
	/// - `xcm`: The message to be exported.
	///
	/// As an example, to export a message for execution on Asset Hub (parachain #1000 in the
	/// Kusama network), you would call with `network: NetworkId::Kusama` and
	/// `destination: X1(Parachain(1000))`. Alternatively, to export a message for execution on
	/// Polkadot, you would call with `network: NetworkId:: Polkadot` and `destination: Here`.
	///
	/// Kind: *Command*
	///
	/// Errors: *Fallible*.
2247
	ExportMessage { network: NetworkId, destination: InteriorMultiLocation, xcm: Xcm<()> },
339
	/// Lock the locally held asset and prevent further transfer or withdrawal.
	///
	/// This restriction may be removed by the `UnlockAsset` instruction being called with an
	/// Origin of `unlocker` and a `target` equal to the current `Origin`.
	///
	/// If the locking is successful, then a `NoteUnlockable` instruction is sent to `unlocker`.
	///
	/// - `asset`: The asset(s) which should be locked.
	/// - `unlocker`: The value which the Origin must be for a corresponding `UnlockAsset`
	///   instruction to work.
	///
	/// Kind: *Command*.
	///
	/// Errors:
339
	LockAsset { asset: MultiAsset, unlocker: MultiLocation },
225
	/// Remove the lock over `asset` on this chain and (if nothing else is preventing it) allow the
	/// asset to be transferred.
	///
	/// - `asset`: The asset to be unlocked.
	/// - `target`: The owner of the asset on the local chain.
	///
	/// Safety: No concerns.
	///
	/// Kind: *Command*.
	///
	/// Errors:
225
	UnlockAsset { asset: MultiAsset, target: MultiLocation },
180
	/// Asset (`asset`) has been locked on the `origin` system and may not be transferred. It may
	/// only be unlocked with the receipt of the `UnlockAsset` instruction from this chain.
	///
	/// - `asset`: The asset(s) which are now unlockable from this origin.
	/// - `owner`: The owner of the asset on the chain in which it was locked. This may be a
	///   location specific to the origin network.
	///
	/// Safety: `origin` must be trusted to have locked the corresponding `asset`
	/// prior as a consequence of sending this message.
	///
	/// Kind: *Trusted Indication*.
	///
	/// Errors:
180
	NoteUnlockable { asset: MultiAsset, owner: MultiLocation },
213
	/// Send an `UnlockAsset` instruction to the `locker` for the given `asset`.
	///
	/// This may fail if the local system is making use of the fact that the asset is locked or,
	/// of course, if there is no record that the asset actually is locked.
	///
	/// - `asset`: The asset(s) to be unlocked.
	/// - `locker`: The location from which a previous `NoteUnlockable` was sent and to which an
	///   `UnlockAsset` should be sent.
	///
	/// Kind: *Command*.
	///
	/// Errors:
213
	RequestUnlock { asset: MultiAsset, locker: MultiLocation },
393
	/// Sets the Fees Mode Register.
	///
	/// - `jit_withdraw`: The fees mode item; if set to `true` then fees for any instructions are
	///   withdrawn as needed using the same mechanism as `WithdrawAssets`.
	///
	/// Kind: *Command*.
	///
	/// Errors:
393
	SetFeesMode { jit_withdraw: bool },
1674
	/// 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:
1674
	SetTopic([u8; 32]),
6339
	/// Clear the Topic Register.
6339
	///
6339
	/// Kind: *Command*
6339
	///
6339
	/// Errors: None.
6339
	ClearTopic,
519
	/// Alter the current Origin to another given origin.
	///
	/// Kind: *Command*
	///
	/// Errors: If the existing state would not allow such a change.
519
	AliasOrigin(MultiLocation),
711
	/// 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.
711
	UnpaidExecution { weight_limit: WeightLimit, check_origin: Option<MultiLocation> },
}
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 v2 response to a v3 response.
impl TryFrom<OldResponse> for Response {
	type Error = ();
930
	fn try_from(old_response: OldResponse) -> result::Result<Self, ()> {
930
		match old_response {
30
			OldResponse::Assets(assets) => Ok(Self::Assets(assets.try_into()?)),
52
			OldResponse::Version(version) => Ok(Self::Version(version)),
284
			OldResponse::ExecutionResult(error) => Ok(Self::ExecutionResult(match error {
248
				Some((i, e)) => Some((i, e.try_into()?)),
36
				None => None,
			})),
564
			OldResponse::Null => Ok(Self::Null),
		}
930
	}
}
// Convert from a v2 XCM to a v3 XCM.
#[allow(deprecated)]
impl<Call> TryFrom<OldXcm<Call>> for Xcm<Call> {
	type Error = ();
12825
	fn try_from(old_xcm: OldXcm<Call>) -> result::Result<Self, ()> {
12825
		Ok(Xcm(old_xcm.0.into_iter().map(TryInto::try_into).collect::<result::Result<_, _>>()?))
12825
	}
}
// Convert from a v4 XCM to a v3 XCM.
impl<Call> TryFrom<NewXcm<Call>> for Xcm<Call> {
	type Error = ();
	fn try_from(new_xcm: NewXcm<Call>) -> result::Result<Self, Self::Error> {
		Ok(Xcm(new_xcm.0.into_iter().map(TryInto::try_into).collect::<result::Result<_, _>>()?))
	}
}
// Convert from a v4 instruction to a v3 instruction.
impl<Call> TryFrom<NewInstruction<Call>> for Instruction<Call> {
	type Error = ();
	fn try_from(new_instruction: NewInstruction<Call>) -> result::Result<Self, Self::Error> {
		use NewInstruction::*;
		Ok(match new_instruction {
			WithdrawAsset(assets) => Self::WithdrawAsset(assets.try_into()?),
			ReserveAssetDeposited(assets) => Self::ReserveAssetDeposited(assets.try_into()?),
			ReceiveTeleportedAsset(assets) => Self::ReceiveTeleportedAsset(assets.try_into()?),
			QueryResponse { query_id, response, max_weight, querier: Some(querier) } =>
				Self::QueryResponse {
					query_id,
					querier: querier.try_into()?,
					response: response.try_into()?,
					max_weight,
				},
			QueryResponse { query_id, response, max_weight, querier: None } =>
				Self::QueryResponse {
					query_id,
					querier: None,
					response: response.try_into()?,
					max_weight,
				},
			TransferAsset { assets, beneficiary } => Self::TransferAsset {
				assets: assets.try_into()?,
				beneficiary: beneficiary.try_into()?,
			},
			TransferReserveAsset { assets, dest, xcm } => Self::TransferReserveAsset {
				assets: assets.try_into()?,
				dest: dest.try_into()?,
				xcm: xcm.try_into()?,
			},
			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
				Self::HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity },
			HrmpChannelAccepted { recipient } => Self::HrmpChannelAccepted { recipient },
			HrmpChannelClosing { initiator, sender, recipient } =>
				Self::HrmpChannelClosing { initiator, sender, recipient },
			Transact { origin_kind, require_weight_at_most, call } =>
				Self::Transact { origin_kind, require_weight_at_most, call: call.into() },
			ReportError(response_info) => Self::ReportError(QueryResponseInfo {
				query_id: response_info.query_id,
				destination: response_info.destination.try_into().map_err(|_| ())?,
				max_weight: response_info.max_weight,
			}),
			DepositAsset { assets, beneficiary } => {
				let beneficiary = beneficiary.try_into()?;
				let assets = assets.try_into()?;
				Self::DepositAsset { assets, beneficiary }
			},
			DepositReserveAsset { assets, dest, xcm } => {
				let dest = dest.try_into()?;
				let xcm = xcm.try_into()?;
				let assets = assets.try_into()?;
				Self::DepositReserveAsset { assets, dest, xcm }
			},
			ExchangeAsset { give, want, maximal } => {
				let give = give.try_into()?;
				let want = want.try_into()?;
				Self::ExchangeAsset { give, want, maximal }
			},
			InitiateReserveWithdraw { assets, reserve, xcm } => {
				// No `max_assets` here, so if there's a connt, then we cannot translate.
				let assets = assets.try_into()?;
				let reserve = reserve.try_into()?;
				let xcm = xcm.try_into()?;
				Self::InitiateReserveWithdraw { assets, reserve, xcm }
			},
			InitiateTeleport { assets, dest, xcm } => {
				// No `max_assets` here, so if there's a connt, then we cannot translate.
				let assets = assets.try_into()?;
				let dest = dest.try_into()?;
				let xcm = xcm.try_into()?;
				Self::InitiateTeleport { assets, dest, xcm }
			},
			ReportHolding { response_info, assets } => {
				let response_info = QueryResponseInfo {
					destination: response_info.destination.try_into().map_err(|_| ())?,
					query_id: response_info.query_id,
					max_weight: response_info.max_weight,
				};
				Self::ReportHolding { response_info, assets: assets.try_into()? }
			},
			BuyExecution { fees, weight_limit } => {
				let fees = fees.try_into()?;
				let weight_limit = weight_limit.into();
				Self::BuyExecution { fees, weight_limit }
			},
			ClearOrigin => Self::ClearOrigin,
			DescendOrigin(who) => Self::DescendOrigin(who.try_into()?),
			RefundSurplus => Self::RefundSurplus,
			SetErrorHandler(xcm) => Self::SetErrorHandler(xcm.try_into()?),
			SetAppendix(xcm) => Self::SetAppendix(xcm.try_into()?),
			ClearError => Self::ClearError,
			ClaimAsset { assets, ticket } => {
				let assets = assets.try_into()?;
				let ticket = ticket.try_into()?;
				Self::ClaimAsset { assets, ticket }
			},
			Trap(code) => Self::Trap(code),
			SubscribeVersion { query_id, max_response_weight } =>
				Self::SubscribeVersion { query_id, max_response_weight },
			UnsubscribeVersion => Self::UnsubscribeVersion,
			BurnAsset(assets) => Self::BurnAsset(assets.try_into()?),
			ExpectAsset(assets) => Self::ExpectAsset(assets.try_into()?),
			ExpectOrigin(maybe_origin) =>
				Self::ExpectOrigin(maybe_origin.map(|origin| origin.try_into()).transpose()?),
			ExpectError(maybe_error) => Self::ExpectError(maybe_error),
			ExpectTransactStatus(maybe_error_code) => Self::ExpectTransactStatus(maybe_error_code),
			QueryPallet { module_name, response_info } =>
				Self::QueryPallet { module_name, response_info: response_info.try_into()? },
			ExpectPallet { index, name, module_name, crate_major, min_crate_minor } =>
				Self::ExpectPallet { index, name, module_name, crate_major, min_crate_minor },
			ReportTransactStatus(response_info) =>
				Self::ReportTransactStatus(response_info.try_into()?),
			ClearTransactStatus => Self::ClearTransactStatus,
			UniversalOrigin(junction) => Self::UniversalOrigin(junction.try_into()?),
			ExportMessage { network, destination, xcm } => Self::ExportMessage {
				network: network.into(),
				destination: destination.try_into()?,
				xcm: xcm.try_into()?,
			},
			LockAsset { asset, unlocker } =>
				Self::LockAsset { asset: asset.try_into()?, unlocker: unlocker.try_into()? },
			UnlockAsset { asset, target } =>
				Self::UnlockAsset { asset: asset.try_into()?, target: target.try_into()? },
			NoteUnlockable { asset, owner } =>
				Self::NoteUnlockable { asset: asset.try_into()?, owner: owner.try_into()? },
			RequestUnlock { asset, locker } =>
				Self::RequestUnlock { asset: asset.try_into()?, locker: locker.try_into()? },
			SetFeesMode { jit_withdraw } => Self::SetFeesMode { jit_withdraw },
			SetTopic(topic) => Self::SetTopic(topic),
			ClearTopic => Self::ClearTopic,
			AliasOrigin(location) => Self::AliasOrigin(location.try_into()?),
			UnpaidExecution { weight_limit, check_origin } => Self::UnpaidExecution {
				weight_limit,
				check_origin: check_origin.map(|origin| origin.try_into()).transpose()?,
			},
		})
	}
}
/// Default value for the proof size weight component when converting from V2. Set at 64 KB.
/// NOTE: Make sure this is removed after we properly account for PoV weights.
const DEFAULT_PROOF_SIZE: u64 = 64 * 1024;
// Convert from a v2 instruction to a v3 instruction.
impl<Call> TryFrom<OldInstruction<Call>> for Instruction<Call> {
	type Error = ();
111108
	fn try_from(old_instruction: OldInstruction<Call>) -> result::Result<Self, ()> {
		use OldInstruction::*;
111108
		Ok(match old_instruction {
83001
			WithdrawAsset(assets) => Self::WithdrawAsset(assets.try_into()?),
1185
			ReserveAssetDeposited(assets) => Self::ReserveAssetDeposited(assets.try_into()?),
663
			ReceiveTeleportedAsset(assets) => Self::ReceiveTeleportedAsset(assets.try_into()?),
1395
			QueryResponse { query_id, response, max_weight } => Self::QueryResponse {
1395
				query_id,
1395
				response: response.try_into()?,
1305
				max_weight: Weight::from_parts(max_weight, DEFAULT_PROOF_SIZE),
1305
				querier: None,
			},
1011
			TransferAsset { assets, beneficiary } => Self::TransferAsset {
1011
				assets: assets.try_into()?,
921
				beneficiary: beneficiary.try_into()?,
			},
690
			TransferReserveAsset { assets, dest, xcm } => Self::TransferReserveAsset {
690
				assets: assets.try_into()?,
687
				dest: dest.try_into()?,
687
				xcm: xcm.try_into()?,
			},
120
			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
120
				Self::HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity },
2394
			HrmpChannelAccepted { recipient } => Self::HrmpChannelAccepted { recipient },
603
			HrmpChannelClosing { initiator, sender, recipient } =>
603
				Self::HrmpChannelClosing { initiator, sender, recipient },
621
			Transact { origin_type, require_weight_at_most, call } => Self::Transact {
621
				origin_kind: origin_type.into(),
621
				require_weight_at_most: Weight::from_parts(
621
					require_weight_at_most,
621
					DEFAULT_PROOF_SIZE,
621
				),
621
				call: call.into(),
621
			},
483
			ReportError { query_id, dest, max_response_weight } => {
483
				let response_info = QueryResponseInfo {
483
					destination: dest.try_into()?,
483
					query_id,
483
					max_weight: Weight::from_parts(max_response_weight, DEFAULT_PROOF_SIZE),
483
				};
483
				Self::ReportError(response_info)
			},
549
			DepositAsset { assets, max_assets, beneficiary } => Self::DepositAsset {
549
				assets: (assets, max_assets).try_into()?,
507
				beneficiary: beneficiary.try_into()?,
			},
1911
			DepositReserveAsset { assets, max_assets, dest, xcm } => {
1911
				let assets = (assets, max_assets).try_into()?;
1875
				Self::DepositReserveAsset { assets, dest: dest.try_into()?, xcm: xcm.try_into()? }
			},
405
			ExchangeAsset { give, receive } => {
405
				let give = give.try_into()?;
366
				let want = receive.try_into()?;
366
				Self::ExchangeAsset { give, want, maximal: true }
			},
2058
			InitiateReserveWithdraw { assets, reserve, xcm } => Self::InitiateReserveWithdraw {
2058
				assets: assets.try_into()?,
1854
				reserve: reserve.try_into()?,
1851
				xcm: xcm.try_into()?,
			},
1473
			InitiateTeleport { assets, dest, xcm } => Self::InitiateTeleport {
1473
				assets: assets.try_into()?,
1326
				dest: dest.try_into()?,
1320
				xcm: xcm.try_into()?,
			},
882
			QueryHolding { query_id, dest, assets, max_response_weight } => {
831
				let response_info = QueryResponseInfo {
882
					destination: dest.try_into()?,
831
					query_id,
831
					max_weight: Weight::from_parts(max_response_weight, DEFAULT_PROOF_SIZE),
831
				};
831
				Self::ReportHolding { response_info, assets: assets.try_into()? }
			},
759
			BuyExecution { fees, weight_limit } =>
759
				Self::BuyExecution { fees: fees.try_into()?, weight_limit: weight_limit.into() },
2541
			ClearOrigin => Self::ClearOrigin,
222
			DescendOrigin(who) => Self::DescendOrigin(who.try_into()?),
3405
			RefundSurplus => Self::RefundSurplus,
693
			SetErrorHandler(xcm) => Self::SetErrorHandler(xcm.try_into()?),
630
			SetAppendix(xcm) => Self::SetAppendix(xcm.try_into()?),
897
			ClearError => Self::ClearError,
261
			ClaimAsset { assets, ticket } => {
261
				let assets = assets.try_into()?;
261
				let ticket = ticket.try_into()?;
261
				Self::ClaimAsset { assets, ticket }
			},
798
			Trap(code) => Self::Trap(code),
378
			SubscribeVersion { query_id, max_response_weight } => Self::SubscribeVersion {
378
				query_id,
378
				max_response_weight: Weight::from_parts(max_response_weight, DEFAULT_PROOF_SIZE),
378
			},
1080
			UnsubscribeVersion => Self::UnsubscribeVersion,
		})
111108
	}
}
#[cfg(test)]
mod tests {
	use super::{prelude::*, *};
	#[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());
	}
}