1
// Copyright (C) Parity Technologies (UK) Ltd.
2
// This file is part of Cumulus.
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 Cumulus.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! # XCM Version 2
18
//!
19
//! WARNING: DEPRECATED, please use version 3 or 4.
20
//!
21
//! Version 2 of the Cross-Consensus Message format data structures. The comprehensive list of
22
//! changes can be found in
23
//! [this PR description](https://github.com/paritytech/polkadot/pull/3629#issue-968428279).
24
//!
25
//! ## Changes to be aware of
26
//! The biggest change here is the restructuring of XCM messages: instead of having `Order` and
27
//! `Xcm` types, the `Xcm` type now simply wraps a `Vec` containing `Instruction`s. However, most
28
//! changes should still be automatically convertible via the `try_from` and `from` conversion
29
//! functions.
30
//!
31
//! ### Junction
32
//! - No special attention necessary
33
//!
34
//! ### `MultiLocation`
35
//! - No special attention necessary
36
//!
37
//! ### `MultiAsset`
38
//! - No special attention necessary
39
//!
40
//! ### XCM and Order
41
//! - `Xcm` and `Order` variants are now combined under a single `Instruction` enum.
42
//! - `Order` is now obsolete and replaced entirely by `Instruction`.
43
//! - `Xcm` is now a simple wrapper around a `Vec<Instruction>`.
44
//! - During conversion from `Order` to `Instruction`, we do not handle `BuyExecution`s that have
45
//!   nested XCMs, i.e. if the `instructions` field in the `BuyExecution` enum struct variant is not
46
//!   empty, then the conversion will fail. To address this, rewrite the XCM using `Instruction`s in
47
//!   chronological order.
48
//! - During conversion from `Xcm` to `Instruction`, we do not handle `RelayedFrom` messages at all.
49
//!
50
//! ### XCM Pallet
51
//! - The `Weigher` configuration item must have sensible weights defined for `BuyExecution` and
52
//!   `DepositAsset` instructions. Failing that, dispatch calls to `teleport_assets` and
53
//!   `reserve_transfer_assets` will fail with `UnweighableMessage`.
54

            
55
use super::{
56
	v3::{
57
		BodyId as NewBodyId, BodyPart as NewBodyPart, Instruction as NewInstruction,
58
		NetworkId as NewNetworkId, OriginKind as NewOriginKind, Response as NewResponse,
59
		WeightLimit as NewWeightLimit, Xcm as NewXcm,
60
	},
61
	DoubleEncoded,
62
};
63
use alloc::{vec, vec::Vec};
64
use bounded_collections::{ConstU32, WeakBoundedVec};
65
use codec::{
66
	self, decode_vec_with_len, Compact, Decode, Encode, Error as CodecError, Input as CodecInput,
67
	MaxEncodedLen,
68
};
69
use core::{fmt::Debug, result};
70
use derivative::Derivative;
71
use scale_info::TypeInfo;
72

            
73
mod junction;
74
mod multiasset;
75
mod multilocation;
76
mod traits;
77

            
78
pub use junction::Junction;
79
pub use multiasset::{
80
	AssetId, AssetInstance, Fungibility, MultiAsset, MultiAssetFilter, MultiAssets,
81
	WildFungibility, WildMultiAsset,
82
};
83
pub use multilocation::{
84
	Ancestor, AncestorThen, InteriorMultiLocation, Junctions, MultiLocation, Parent, ParentThen,
85
};
86
pub use traits::{Error, ExecuteXcm, GetWeight, Outcome, Result, SendError, SendResult, SendXcm};
87

            
88
/// Basically just the XCM (more general) version of `ParachainDispatchOrigin`.
89
27
#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
90
#[scale_info(replace_segment("staging_xcm", "xcm"))]
91
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
92
pub enum OriginKind {
93
2733
	/// Origin should just be the native dispatch origin representation for the sender in the
94
2733
	/// local runtime framework. For Cumulus/Frame chains this is the `Parachain` or `Relay` origin
95
2733
	/// if coming from a chain, though there may be others if the `MultiLocation` XCM origin has a
96
2733
	/// primary/native dispatch origin form.
97
2733
	Native,
98

            
99
189
	/// Origin should just be the standard account-based origin with the sovereign account of
100
189
	/// the sender. For Cumulus/Frame chains, this is the `Signed` origin.
101
189
	SovereignAccount,
102

            
103
3
	/// Origin should be the super-user. For Cumulus/Frame chains, this is the `Root` origin.
104
3
	/// This will not usually be an available option.
105
3
	Superuser,
106

            
107
9
	/// Origin should be interpreted as an XCM native origin and the `MultiLocation` should be
108
9
	/// encoded directly in the dispatch origin unchanged. For Cumulus/Frame chains, this will be
109
9
	/// the `pallet_xcm::Origin::Xcm` type.
110
9
	Xcm,
111
}
112

            
113
impl From<NewOriginKind> for OriginKind {
114
	fn from(new: NewOriginKind) -> Self {
115
		use NewOriginKind::*;
116
		match new {
117
			Native => Self::Native,
118
			SovereignAccount => Self::SovereignAccount,
119
			Superuser => Self::Superuser,
120
			Xcm => Self::Xcm,
121
		}
122
	}
123
}
124

            
125
/// A global identifier of an account-bearing consensus system.
126
51
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
127
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
128
#[scale_info(replace_segment("staging_xcm", "xcm"))]
129
pub enum NetworkId {
130
1599
	/// Unidentified/any.
131
1599
	Any,
132
2112
	/// Some named network.
133
2112
	Named(WeakBoundedVec<u8, ConstU32<32>>),
134
1392
	/// The Polkadot Relay chain
135
1392
	Polkadot,
136
561
	/// Kusama.
137
561
	Kusama,
138
}
139

            
140
impl TryFrom<Option<NewNetworkId>> for NetworkId {
141
	type Error = ();
142
	fn try_from(new: Option<NewNetworkId>) -> result::Result<NetworkId, ()> {
143
		match new {
144
			None => Ok(NetworkId::Any),
145
			Some(id) => Self::try_from(id),
146
		}
147
	}
148
}
149

            
150
impl TryFrom<NewNetworkId> for NetworkId {
151
	type Error = ();
152
	fn try_from(new: NewNetworkId) -> result::Result<NetworkId, ()> {
153
		use NewNetworkId::*;
154
		match new {
155
			Polkadot => Ok(NetworkId::Polkadot),
156
			Kusama => Ok(NetworkId::Kusama),
157
			_ => Err(()),
158
		}
159
	}
160
}
161

            
162
/// An identifier of a pluralistic body.
163
15
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
164
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
165
#[scale_info(replace_segment("staging_xcm", "xcm"))]
166
pub enum BodyId {
167
840
	/// The only body in its context.
168
840
	Unit,
169
273
	/// A named body.
170
273
	Named(WeakBoundedVec<u8, ConstU32<32>>),
171
102
	/// An indexed body.
172
102
	Index(#[codec(compact)] u32),
173
66
	/// The unambiguous executive body (for Polkadot, this would be the Polkadot council).
174
66
	Executive,
175
264
	/// The unambiguous technical body (for Polkadot, this would be the Technical Committee).
176
264
	Technical,
177
36
	/// The unambiguous legislative body (for Polkadot, this could be considered the opinion of a
178
36
	/// majority of lock-voters).
179
36
	Legislative,
180
60
	/// The unambiguous judicial body (this doesn't exist on Polkadot, but if it were to get a
181
60
	/// "grand oracle", it may be considered as that).
182
60
	Judicial,
183
30
	/// The unambiguous defense body (for Polkadot, an opinion on the topic given via a public
184
30
	/// referendum on the `staking_admin` track).
185
30
	Defense,
186
99
	/// The unambiguous administration body (for Polkadot, an opinion on the topic given via a
187
99
	/// public referendum on the `general_admin` track).
188
99
	Administration,
189
15
	/// The unambiguous treasury body (for Polkadot, an opinion on the topic given via a public
190
15
	/// referendum on the `treasurer` track).
191
15
	Treasury,
192
}
193

            
194
impl From<NewBodyId> for BodyId {
195
	fn from(n: NewBodyId) -> Self {
196
		use NewBodyId::*;
197
		match n {
198
			Unit => Self::Unit,
199
			Moniker(n) => Self::Named(
200
				n[..]
201
					.to_vec()
202
					.try_into()
203
					.expect("array size is 4 and so will never be out of bounds; qed"),
204
			),
205
			Index(n) => Self::Index(n),
206
			Executive => Self::Executive,
207
			Technical => Self::Technical,
208
			Legislative => Self::Legislative,
209
			Judicial => Self::Judicial,
210
			Defense => Self::Defense,
211
			Administration => Self::Administration,
212
			Treasury => Self::Treasury,
213
		}
214
	}
215
}
216

            
217
/// A part of a pluralistic body.
218
36
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
219
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
220
#[scale_info(replace_segment("staging_xcm", "xcm"))]
221
pub enum BodyPart {
222
1056
	/// The body's declaration, under whatever means it decides.
223
1056
	Voice,
224
360
	/// A given number of members of the body.
225
	Members {
226
6
		#[codec(compact)]
227
6
		count: u32,
228
360
	},
229
48
	/// A given number of members of the body, out of some larger caucus.
230
	Fraction {
231
6
		#[codec(compact)]
232
6
		nom: u32,
233
3
		#[codec(compact)]
234
3
		denom: u32,
235
48
	},
236
123
	/// No less than the given proportion of members of the body.
237
	AtLeastProportion {
238
6
		#[codec(compact)]
239
6
		nom: u32,
240
3
		#[codec(compact)]
241
3
		denom: u32,
242
123
	},
243
153
	/// More than the given proportion of members of the body.
244
	MoreThanProportion {
245
3
		#[codec(compact)]
246
3
		nom: u32,
247
		#[codec(compact)]
248
		denom: u32,
249
153
	},
250
}
251

            
252
impl BodyPart {
253
	/// Returns `true` if the part represents a strict majority (> 50%) of the body in question.
254
	pub fn is_majority(&self) -> bool {
255
		match self {
256
			BodyPart::Fraction { nom, denom } if *nom * 2 > *denom => true,
257
			BodyPart::AtLeastProportion { nom, denom } if *nom * 2 > *denom => true,
258
			BodyPart::MoreThanProportion { nom, denom } if *nom * 2 >= *denom => true,
259
			_ => false,
260
		}
261
	}
262
}
263

            
264
impl From<NewBodyPart> for BodyPart {
265
	fn from(n: NewBodyPart) -> Self {
266
		use NewBodyPart::*;
267
		match n {
268
			Voice => Self::Voice,
269
			Members { count } => Self::Members { count },
270
			Fraction { nom, denom } => Self::Fraction { nom, denom },
271
			AtLeastProportion { nom, denom } => Self::AtLeastProportion { nom, denom },
272
			MoreThanProportion { nom, denom } => Self::MoreThanProportion { nom, denom },
273
		}
274
	}
275
}
276

            
277
/// This module's XCM version.
278
pub const VERSION: super::Version = 2;
279

            
280
/// An identifier for a query.
281
pub type QueryId = u64;
282

            
283
/// DEPRECATED. Please use XCMv3 or XCMv4 instead.
284
30513
#[derive(Derivative, Default, Encode, TypeInfo)]
285
#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
286
#[codec(encode_bound())]
287
#[codec(decode_bound())]
288
#[scale_info(bounds(), skip_type_params(RuntimeCall))]
289
#[scale_info(replace_segment("staging_xcm", "xcm"))]
290
pub struct Xcm<RuntimeCall>(pub Vec<Instruction<RuntimeCall>>);
291

            
292
environmental::environmental!(instructions_count: u8);
293

            
294
impl<Call> Decode for Xcm<Call> {
295
29685
	fn decode<I: CodecInput>(input: &mut I) -> core::result::Result<Self, CodecError> {
296
29685
		instructions_count::using_once(&mut 0, || {
297
29685
			let number_of_instructions: u32 = <Compact<u32>>::decode(input)?.into();
298
29586
			instructions_count::with(|count| {
299
29586
				*count = count.saturating_add(number_of_instructions as u8);
300
29586
				if *count > MAX_INSTRUCTIONS_TO_DECODE {
301
78
					return Err(CodecError::from("Max instructions exceeded"))
302
29508
				}
303
29508
				Ok(())
304
29586
			})
305
29586
			.unwrap_or(Ok(()))?;
306
29508
			let decoded_instructions = decode_vec_with_len(input, number_of_instructions as usize)?;
307
23514
			Ok(Self(decoded_instructions))
308
29685
		})
309
29685
	}
310
}
311

            
312
/// The maximal number of instructions in an XCM before decoding fails.
313
///
314
/// This is a deliberate limit - not a technical one.
315
pub const MAX_INSTRUCTIONS_TO_DECODE: u8 = 100;
316

            
317
impl<RuntimeCall> Xcm<RuntimeCall> {
318
	/// Create an empty instance.
319
	pub fn new() -> Self {
320
		Self(vec![])
321
	}
322

            
323
	/// Return `true` if no instructions are held in `self`.
324
	pub fn is_empty(&self) -> bool {
325
		self.0.is_empty()
326
	}
327

            
328
	/// Return the number of instructions held in `self`.
329
	pub fn len(&self) -> usize {
330
		self.0.len()
331
	}
332

            
333
	/// Consume and either return `self` if it contains some instructions, or if it's empty, then
334
	/// instead return the result of `f`.
335
	pub fn or_else(self, f: impl FnOnce() -> Self) -> Self {
336
		if self.0.is_empty() {
337
			f()
338
		} else {
339
			self
340
		}
341
	}
342

            
343
	/// Return the first instruction, if any.
344
	pub fn first(&self) -> Option<&Instruction<RuntimeCall>> {
345
		self.0.first()
346
	}
347

            
348
	/// Return the last instruction, if any.
349
	pub fn last(&self) -> Option<&Instruction<RuntimeCall>> {
350
		self.0.last()
351
	}
352

            
353
	/// Return the only instruction, contained in `Self`, iff only one exists (`None` otherwise).
354
	pub fn only(&self) -> Option<&Instruction<RuntimeCall>> {
355
		if self.0.len() == 1 {
356
			self.0.first()
357
		} else {
358
			None
359
		}
360
	}
361

            
362
	/// Return the only instruction, contained in `Self`, iff only one exists (returns `self`
363
	/// otherwise).
364
	pub fn into_only(mut self) -> core::result::Result<Instruction<RuntimeCall>, Self> {
365
		if self.0.len() == 1 {
366
			self.0.pop().ok_or(self)
367
		} else {
368
			Err(self)
369
		}
370
	}
371
}
372

            
373
/// A prelude for importing all types typically used when interacting with XCM messages.
374
pub mod prelude {
375
	mod contents {
376
		pub use super::super::{
377
			Ancestor, AncestorThen,
378
			AssetId::{self, *},
379
			AssetInstance::{self, *},
380
			BodyId, BodyPart, Error as XcmError, ExecuteXcm,
381
			Fungibility::{self, *},
382
			Instruction::*,
383
			InteriorMultiLocation,
384
			Junction::{self, *},
385
			Junctions::{self, *},
386
			MultiAsset,
387
			MultiAssetFilter::{self, *},
388
			MultiAssets, MultiLocation,
389
			NetworkId::{self, *},
390
			OriginKind, Outcome, Parent, ParentThen, QueryId, Response, Result as XcmResult,
391
			SendError, SendResult, SendXcm,
392
			WeightLimit::{self, *},
393
			WildFungibility::{self, Fungible as WildFungible, NonFungible as WildNonFungible},
394
			WildMultiAsset::{self, *},
395
			XcmWeightInfo, VERSION as XCM_VERSION,
396
		};
397
	}
398
	pub use super::{Instruction, Xcm};
399
	pub use contents::*;
400
	pub mod opaque {
401
		pub use super::{
402
			super::opaque::{Instruction, Xcm},
403
			contents::*,
404
		};
405
	}
406
}
407

            
408
/// Response data to a query.
409
24
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
410
#[scale_info(replace_segment("staging_xcm", "xcm"))]
411
pub enum Response {
412
1725
	/// No response. Serves as a neutral default.
413
1725
	Null,
414
159
	/// Some assets.
415
159
	Assets(MultiAssets),
416
894
	/// The outcome of an XCM instruction.
417
894
	ExecutionResult(Option<(u32, Error)>),
418
90
	/// An XCM version.
419
90
	Version(super::Version),
420
}
421

            
422
impl Default for Response {
423
	fn default() -> Self {
424
		Self::Null
425
	}
426
}
427

            
428
/// An optional weight limit.
429
45
#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
430
#[scale_info(replace_segment("staging_xcm", "xcm"))]
431
pub enum WeightLimit {
432
1992
	/// No weight limit imposed.
433
1992
	Unlimited,
434
282
	/// Weight limit imposed of the inner value.
435
282
	Limited(#[codec(compact)] u64),
436
}
437

            
438
impl From<Option<u64>> for WeightLimit {
439
	fn from(x: Option<u64>) -> Self {
440
		match x {
441
			Some(w) => WeightLimit::Limited(w),
442
			None => WeightLimit::Unlimited,
443
		}
444
	}
445
}
446

            
447
impl From<WeightLimit> for Option<u64> {
448
	fn from(x: WeightLimit) -> Self {
449
		match x {
450
			WeightLimit::Limited(w) => Some(w),
451
			WeightLimit::Unlimited => None,
452
		}
453
	}
454
}
455

            
456
impl TryFrom<NewWeightLimit> for WeightLimit {
457
	type Error = ();
458
	fn try_from(x: NewWeightLimit) -> result::Result<Self, Self::Error> {
459
		use NewWeightLimit::*;
460
		match x {
461
			Limited(w) => Ok(Self::Limited(w.ref_time())),
462
			Unlimited => Ok(Self::Unlimited),
463
		}
464
	}
465
}
466

            
467
/// Local weight type; execution time in picoseconds.
468
pub type Weight = u64;
469

            
470
/// Cross-Consensus Message: A message from one consensus system to another.
471
///
472
/// Consensus systems that may send and receive messages include blockchains and smart contracts.
473
///
474
/// All messages are delivered from a known *origin*, expressed as a `MultiLocation`.
475
///
476
/// This is the inner XCM format and is version-sensitive. Messages are typically passed using the
477
/// outer XCM format, known as `VersionedXcm`.
478
753323
#[derive(Derivative, Encode, Decode, TypeInfo, xcm_procedural::XcmWeightInfoTrait)]
479
#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
480
#[codec(encode_bound())]
481
#[codec(decode_bound())]
482
#[scale_info(bounds(), skip_type_params(RuntimeCall))]
483
#[scale_info(replace_segment("staging_xcm", "xcm"))]
484
pub enum Instruction<RuntimeCall> {
485
231474
	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place them into the Holding
486
	/// Register.
487
	///
488
	/// - `assets`: The asset(s) to be withdrawn into holding.
489
	///
490
	/// Kind: *Command*.
491
	///
492
	/// Errors:
493
231474
	WithdrawAsset(MultiAssets),
494

            
495
2649
	/// Asset(s) (`assets`) have been received into the ownership of this system on the `origin`
496
	/// system and equivalent derivatives should be placed into the Holding Register.
497
	///
498
	/// - `assets`: The asset(s) that are minted into holding.
499
	///
500
	/// Safety: `origin` must be trusted to have received and be storing `assets` such that they
501
	/// may later be withdrawn should this system send a corresponding message.
502
	///
503
	/// Kind: *Trusted Indication*.
504
	///
505
	/// Errors:
506
2649
	ReserveAssetDeposited(MultiAssets),
507

            
508
1710
	/// Asset(s) (`assets`) have been destroyed on the `origin` system and equivalent assets should
509
	/// be created and placed into the Holding Register.
510
	///
511
	/// - `assets`: The asset(s) that are minted into the Holding Register.
512
	///
513
	/// Safety: `origin` must be trusted to have irrevocably destroyed the corresponding `assets`
514
	/// prior as a consequence of sending this message.
515
	///
516
	/// Kind: *Trusted Indication*.
517
	///
518
	/// Errors:
519
1710
	ReceiveTeleportedAsset(MultiAssets),
520

            
521
2901
	/// Respond with information that the local system is expecting.
522
	///
523
	/// - `query_id`: The identifier of the query that resulted in this message being sent.
524
	/// - `response`: The message content.
525
	/// - `max_weight`: The maximum weight that handling this response should take.
526
	///
527
	/// Safety: No concerns.
528
	///
529
	/// Kind: *Information*.
530
	///
531
	/// Errors:
532
	QueryResponse {
533
9
		#[codec(compact)]
534
9
		query_id: QueryId,
535
87
		response: Response,
536
33
		#[codec(compact)]
537
33
		max_weight: u64,
538
2901
	},
539

            
540
3177
	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets
541
	/// under the ownership of `beneficiary`.
542
	///
543
	/// - `assets`: The asset(s) to be withdrawn.
544
	/// - `beneficiary`: The new owner for the assets.
545
	///
546
	/// Safety: No concerns.
547
	///
548
	/// Kind: *Command*.
549
	///
550
	/// Errors:
551
3177
	TransferAsset { assets: MultiAssets, beneficiary: MultiLocation },
552

            
553
2028
	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets
554
	/// under the ownership of `dest` within this consensus system (i.e. its sovereign account).
555
	///
556
	/// Send an onward XCM message to `dest` of `ReserveAssetDeposited` with the given
557
	/// `xcm`.
558
	///
559
	/// - `assets`: The asset(s) to be withdrawn.
560
	/// - `dest`: The location whose sovereign account will own the assets and thus the effective
561
	///   beneficiary for the assets and the notification target for the reserve asset deposit
562
	///   message.
563
	/// - `xcm`: The instructions that should follow the `ReserveAssetDeposited` instruction, which
564
	///   is sent onwards to `dest`.
565
	///
566
	/// Safety: No concerns.
567
	///
568
	/// Kind: *Command*.
569
	///
570
	/// Errors:
571
2028
	TransferReserveAsset { assets: MultiAssets, dest: MultiLocation, xcm: Xcm<()> },
572

            
573
2961
	/// Apply the encoded transaction `call`, whose dispatch-origin should be `origin` as expressed
574
	/// by the kind of origin `origin_type`.
575
	///
576
	/// - `origin_type`: The means of expressing the message origin as a dispatch origin.
577
	/// - `max_weight`: The weight of `call`; this should be at least the chain's calculated weight
578
	///   and will be used in the weight determination arithmetic.
579
	/// - `call`: The encoded transaction to be applied.
580
	///
581
	/// Safety: No concerns.
582
	///
583
	/// Kind: *Command*.
584
	///
585
	/// Errors:
586
	Transact {
587
27
		origin_type: OriginKind,
588
27
		#[codec(compact)]
589
27
		require_weight_at_most: u64,
590
15
		call: DoubleEncoded<RuntimeCall>,
591
2961
	},
592

            
593
783
	/// A message to notify about a new incoming HRMP channel. This message is meant to be sent by
594
	/// the relay-chain to a para.
595
	///
596
	/// - `sender`: The sender in the to-be opened channel. Also, the initiator of the channel
597
	///   opening.
598
	/// - `max_message_size`: The maximum size of a message proposed by the sender.
599
	/// - `max_capacity`: The maximum number of messages that can be queued in the channel.
600
	///
601
	/// Safety: The message should originate directly from the relay-chain.
602
	///
603
	/// Kind: *System Notification*
604
	HrmpNewChannelOpenRequest {
605
15
		#[codec(compact)]
606
15
		sender: u32,
607
18
		#[codec(compact)]
608
18
		max_message_size: u32,
609
12
		#[codec(compact)]
610
12
		max_capacity: u32,
611
783
	},
612

            
613
3888
	/// A message to notify about that a previously sent open channel request has been accepted by
614
	/// the recipient. That means that the channel will be opened during the next relay-chain
615
	/// session change. This message is meant to be sent by the relay-chain to a para.
616
	///
617
	/// Safety: The message should originate directly from the relay-chain.
618
	///
619
	/// Kind: *System Notification*
620
	///
621
	/// Errors:
622
	HrmpChannelAccepted {
623
		// NOTE: We keep this as a structured item to a) keep it consistent with the other Hrmp
624
		// items; and b) because the field's meaning is not obvious/mentioned from the item name.
625
21
		#[codec(compact)]
626
21
		recipient: u32,
627
3888
	},
628

            
629
1383
	/// A message to notify that the other party in an open channel decided to close it. In
630
	/// particular, `initiator` is going to close the channel opened from `sender` to the
631
	/// `recipient`. The close will be enacted at the next relay-chain session change. This message
632
	/// is meant to be sent by the relay-chain to a para.
633
	///
634
	/// Safety: The message should originate directly from the relay-chain.
635
	///
636
	/// Kind: *System Notification*
637
	///
638
	/// Errors:
639
	HrmpChannelClosing {
640
21
		#[codec(compact)]
641
21
		initiator: u32,
642
18
		#[codec(compact)]
643
18
		sender: u32,
644
9
		#[codec(compact)]
645
9
		recipient: u32,
646
1383
	},
647

            
648
5469
	/// Clear the origin.
649
5469
	///
650
5469
	/// This may be used by the XCM author to ensure that later instructions cannot command the
651
5469
	/// authority of the origin (e.g. if they are being relayed from an untrusted source, as often
652
5469
	/// the case with `ReserveAssetDeposited`).
653
5469
	///
654
5469
	/// Safety: No concerns.
655
5469
	///
656
5469
	/// Kind: *Command*.
657
5469
	///
658
5469
	/// Errors:
659
5469
	ClearOrigin,
660

            
661
399
	/// Mutate the origin to some interior location.
662
	///
663
	/// Kind: *Command*
664
	///
665
	/// Errors:
666
399
	DescendOrigin(InteriorMultiLocation),
667

            
668
1008
	/// Immediately report the contents of the Error Register to the given destination via XCM.
669
	///
670
	/// A `QueryResponse` message of type `ExecutionOutcome` is sent to `dest` with the given
671
	/// `query_id` and the outcome of the XCM.
672
	///
673
	/// - `query_id`: An identifier that will be replicated into the returned XCM message.
674
	/// - `dest`: A valid destination for the returned XCM message.
675
	/// - `max_response_weight`: The maximum amount of weight that the `QueryResponse` item which
676
	///   is sent as a reply may take to execute. NOTE: If this is unexpectedly large then the
677
	///   response may not execute at all.
678
	///
679
	/// Kind: *Command*
680
	///
681
	/// Errors:
682
	ReportError {
683
12
		#[codec(compact)]
684
12
		query_id: QueryId,
685
30
		dest: MultiLocation,
686
15
		#[codec(compact)]
687
15
		max_response_weight: u64,
688
1008
	},
689

            
690
1149
	/// Remove the asset(s) (`assets`) from the Holding Register and place equivalent assets under
691
	/// the ownership of `beneficiary` within this consensus system.
692
	///
693
	/// - `assets`: The asset(s) to remove from holding.
694
	/// - `max_assets`: The maximum number of unique assets/asset instances to remove from holding.
695
	///   Only the first `max_assets` assets/instances of those matched by `assets` will be
696
	///   removed, prioritized under standard asset ordering. Any others will remain in holding.
697
	/// - `beneficiary`: The new owner for the assets.
698
	///
699
	/// Kind: *Command*
700
	///
701
	/// Errors:
702
	DepositAsset {
703
12
		assets: MultiAssetFilter,
704
21
		#[codec(compact)]
705
21
		max_assets: u32,
706
30
		beneficiary: MultiLocation,
707
1149
	},
708

            
709
3984
	/// Remove the asset(s) (`assets`) from the Holding Register and place equivalent assets under
710
	/// the ownership of `dest` within this consensus system (i.e. deposit them into its sovereign
711
	/// account).
712
	///
713
	/// Send an onward XCM message to `dest` of `ReserveAssetDeposited` with the given `effects`.
714
	///
715
	/// - `assets`: The asset(s) to remove from holding.
716
	/// - `max_assets`: The maximum number of unique assets/asset instances to remove from holding.
717
	///   Only the first `max_assets` assets/instances of those matched by `assets` will be
718
	///   removed, prioritized under standard asset ordering. Any others will remain in holding.
719
	/// - `dest`: The location whose sovereign account will own the assets and thus the effective
720
	///   beneficiary for the assets and the notification target for the reserve asset deposit
721
	///   message.
722
	/// - `xcm`: The orders that should follow the `ReserveAssetDeposited` instruction which is
723
	///   sent onwards to `dest`.
724
	///
725
	/// Kind: *Command*
726
	///
727
	/// Errors:
728
	DepositReserveAsset {
729
24
		assets: MultiAssetFilter,
730
27
		#[codec(compact)]
731
27
		max_assets: u32,
732
45
		dest: MultiLocation,
733
315
		xcm: Xcm<()>,
734
3984
	},
735

            
736
990
	/// Remove the asset(s) (`give`) from the Holding Register and replace them with alternative
737
	/// assets.
738
	///
739
	/// The minimum amount of assets to be received into the Holding Register for the order not to
740
	/// fail may be stated.
741
	///
742
	/// - `give`: The asset(s) to remove from holding.
743
	/// - `receive`: The minimum amount of assets(s) which `give` should be exchanged for.
744
	///
745
	/// Kind: *Command*
746
	///
747
	/// Errors:
748
990
	ExchangeAsset { give: MultiAssetFilter, receive: MultiAssets },
749

            
750
5583
	/// Remove the asset(s) (`assets`) from holding and send a `WithdrawAsset` XCM message to a
751
	/// reserve location.
752
	///
753
	/// - `assets`: The asset(s) to remove from holding.
754
	/// - `reserve`: A valid location that acts as a reserve for all asset(s) in `assets`. The
755
	///   sovereign account of this consensus system *on the reserve location* will have
756
	///   appropriate assets withdrawn and `effects` will be executed on them. There will typically
757
	///   be only one valid location on any given asset/chain combination.
758
	/// - `xcm`: The instructions to execute on the assets once withdrawn *on the reserve
759
	///   location*.
760
	///
761
	/// Kind: *Command*
762
	///
763
	/// Errors:
764
5583
	InitiateReserveWithdraw { assets: MultiAssetFilter, reserve: MultiLocation, xcm: Xcm<()> },
765

            
766
3438
	/// Remove the asset(s) (`assets`) from holding and send a `ReceiveTeleportedAsset` XCM message
767
	/// to a `dest` location.
768
	///
769
	/// - `assets`: The asset(s) to remove from holding.
770
	/// - `dest`: A valid location that respects teleports coming from this location.
771
	/// - `xcm`: The instructions to execute on the assets once arrived *on the destination
772
	///   location*.
773
	///
774
	/// NOTE: The `dest` location *MUST* respect this origin as a valid teleportation origin for
775
	/// all `assets`. If it does not, then the assets may be lost.
776
	///
777
	/// Kind: *Command*
778
	///
779
	/// Errors:
780
3438
	InitiateTeleport { assets: MultiAssetFilter, dest: MultiLocation, xcm: Xcm<()> },
781

            
782
1830
	/// Send a `Balances` XCM message with the `assets` value equal to the holding contents, or a
783
	/// portion thereof.
784
	///
785
	/// - `query_id`: An identifier that will be replicated into the returned XCM message.
786
	/// - `dest`: A valid destination for the returned XCM message. This may be limited to the
787
	///   current origin.
788
	/// - `assets`: A filter for the assets that should be reported back. The assets reported back
789
	///   will be, asset-wise, *the lesser of this value and the holding register*. No wildcards
790
	///   will be used when reporting assets back.
791
	/// - `max_response_weight`: The maximum amount of weight that the `QueryResponse` item which
792
	///   is sent as a reply may take to execute. NOTE: If this is unexpectedly large then the
793
	///   response may not execute at all.
794
	///
795
	/// Kind: *Command*
796
	///
797
	/// Errors:
798
	QueryHolding {
799
15
		#[codec(compact)]
800
15
		query_id: QueryId,
801
24
		dest: MultiLocation,
802
18
		assets: MultiAssetFilter,
803
39
		#[codec(compact)]
804
39
		max_response_weight: u64,
805
1830
	},
806

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

            
820
7752
	/// Refund any surplus weight previously bought with `BuyExecution`.
821
7752
	///
822
7752
	/// Kind: *Command*
823
7752
	///
824
7752
	/// Errors: None.
825
7752
	RefundSurplus,
826

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

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

            
859
3564
	/// Clear the Error Register.
860
3564
	///
861
3564
	/// Kind: *Command*
862
3564
	///
863
3564
	/// Errors: None.
864
3564
	ClearError,
865

            
866
423
	/// Create some assets which are being held on behalf of the origin.
867
	///
868
	/// - `assets`: The assets which are to be claimed. This must match exactly with the assets
869
	///   claimable by the origin of the ticket.
870
	/// - `ticket`: The ticket of the asset; this is an abstract identifier to help locate the
871
	///   asset.
872
	///
873
	/// Kind: *Command*
874
	///
875
	/// Errors:
876
423
	ClaimAsset { assets: MultiAssets, ticket: MultiLocation },
877

            
878
2067
	/// Always throws an error of type `Trap`.
879
	///
880
	/// Kind: *Command*
881
	///
882
	/// Errors:
883
	/// - `Trap`: All circumstances, whose inner value is the same as this item's inner value.
884
2067
	Trap(#[codec(compact)] u64),
885

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

            
905
1557
	/// Cancel the effect of a previous `SubscribeVersion` instruction.
906
1557
	///
907
1557
	/// Kind: *Command*
908
1557
	///
909
1557
	/// Errors: *Fallible*
910
1557
	UnsubscribeVersion,
911
}
912

            
913
impl<RuntimeCall> Xcm<RuntimeCall> {
914
	pub fn into<C>(self) -> Xcm<C> {
915
		Xcm::from(self)
916
	}
917
	pub fn from<C>(xcm: Xcm<C>) -> Self {
918
		Self(xcm.0.into_iter().map(Instruction::<RuntimeCall>::from).collect())
919
	}
920
}
921

            
922
impl<RuntimeCall> Instruction<RuntimeCall> {
923
	pub fn into<C>(self) -> Instruction<C> {
924
		Instruction::from(self)
925
	}
926
	pub fn from<C>(xcm: Instruction<C>) -> Self {
927
		use Instruction::*;
928
		match xcm {
929
			WithdrawAsset(assets) => WithdrawAsset(assets),
930
			ReserveAssetDeposited(assets) => ReserveAssetDeposited(assets),
931
			ReceiveTeleportedAsset(assets) => ReceiveTeleportedAsset(assets),
932
			QueryResponse { query_id, response, max_weight } =>
933
				QueryResponse { query_id, response, max_weight },
934
			TransferAsset { assets, beneficiary } => TransferAsset { assets, beneficiary },
935
			TransferReserveAsset { assets, dest, xcm } =>
936
				TransferReserveAsset { assets, dest, xcm },
937
			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
938
				HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity },
939
			HrmpChannelAccepted { recipient } => HrmpChannelAccepted { recipient },
940
			HrmpChannelClosing { initiator, sender, recipient } =>
941
				HrmpChannelClosing { initiator, sender, recipient },
942
			Transact { origin_type, require_weight_at_most, call } =>
943
				Transact { origin_type, require_weight_at_most, call: call.into() },
944
			ReportError { query_id, dest, max_response_weight } =>
945
				ReportError { query_id, dest, max_response_weight },
946
			DepositAsset { assets, max_assets, beneficiary } =>
947
				DepositAsset { assets, max_assets, beneficiary },
948
			DepositReserveAsset { assets, max_assets, dest, xcm } =>
949
				DepositReserveAsset { assets, max_assets, dest, xcm },
950
			ExchangeAsset { give, receive } => ExchangeAsset { give, receive },
951
			InitiateReserveWithdraw { assets, reserve, xcm } =>
952
				InitiateReserveWithdraw { assets, reserve, xcm },
953
			InitiateTeleport { assets, dest, xcm } => InitiateTeleport { assets, dest, xcm },
954
			QueryHolding { query_id, dest, assets, max_response_weight } =>
955
				QueryHolding { query_id, dest, assets, max_response_weight },
956
			BuyExecution { fees, weight_limit } => BuyExecution { fees, weight_limit },
957
			ClearOrigin => ClearOrigin,
958
			DescendOrigin(who) => DescendOrigin(who),
959
			RefundSurplus => RefundSurplus,
960
			SetErrorHandler(xcm) => SetErrorHandler(xcm.into()),
961
			SetAppendix(xcm) => SetAppendix(xcm.into()),
962
			ClearError => ClearError,
963
			ClaimAsset { assets, ticket } => ClaimAsset { assets, ticket },
964
			Trap(code) => Trap(code),
965
			SubscribeVersion { query_id, max_response_weight } =>
966
				SubscribeVersion { query_id, max_response_weight },
967
			UnsubscribeVersion => UnsubscribeVersion,
968
		}
969
	}
970
}
971

            
972
// TODO: Automate Generation
973
impl<RuntimeCall, W: XcmWeightInfo<RuntimeCall>> GetWeight<W> for Instruction<RuntimeCall> {
974
	fn weight(&self) -> sp_weights::Weight {
975
		use Instruction::*;
976
		match self {
977
			WithdrawAsset(assets) => sp_weights::Weight::from_parts(W::withdraw_asset(assets), 0),
978
			ReserveAssetDeposited(assets) =>
979
				sp_weights::Weight::from_parts(W::reserve_asset_deposited(assets), 0),
980
			ReceiveTeleportedAsset(assets) =>
981
				sp_weights::Weight::from_parts(W::receive_teleported_asset(assets), 0),
982
			QueryResponse { query_id, response, max_weight } =>
983
				sp_weights::Weight::from_parts(W::query_response(query_id, response, max_weight), 0),
984
			TransferAsset { assets, beneficiary } =>
985
				sp_weights::Weight::from_parts(W::transfer_asset(assets, beneficiary), 0),
986
			TransferReserveAsset { assets, dest, xcm } =>
987
				sp_weights::Weight::from_parts(W::transfer_reserve_asset(&assets, dest, xcm), 0),
988
			Transact { origin_type, require_weight_at_most, call } =>
989
				sp_weights::Weight::from_parts(
990
					W::transact(origin_type, require_weight_at_most, call),
991
					0,
992
				),
993
			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
994
				sp_weights::Weight::from_parts(
995
					W::hrmp_new_channel_open_request(sender, max_message_size, max_capacity),
996
					0,
997
				),
998
			HrmpChannelAccepted { recipient } =>
999
				sp_weights::Weight::from_parts(W::hrmp_channel_accepted(recipient), 0),
			HrmpChannelClosing { initiator, sender, recipient } => sp_weights::Weight::from_parts(
				W::hrmp_channel_closing(initiator, sender, recipient),
				0,
			),
			ClearOrigin => sp_weights::Weight::from_parts(W::clear_origin(), 0),
			DescendOrigin(who) => sp_weights::Weight::from_parts(W::descend_origin(who), 0),
			ReportError { query_id, dest, max_response_weight } => sp_weights::Weight::from_parts(
				W::report_error(query_id, dest, max_response_weight),
				0,
			),
			DepositAsset { assets, max_assets, beneficiary } =>
				sp_weights::Weight::from_parts(W::deposit_asset(assets, max_assets, beneficiary), 0),
			DepositReserveAsset { assets, max_assets, dest, xcm } =>
				sp_weights::Weight::from_parts(
					W::deposit_reserve_asset(assets, max_assets, dest, xcm),
					0,
				),
			ExchangeAsset { give, receive } =>
				sp_weights::Weight::from_parts(W::exchange_asset(give, receive), 0),
			InitiateReserveWithdraw { assets, reserve, xcm } => sp_weights::Weight::from_parts(
				W::initiate_reserve_withdraw(assets, reserve, xcm),
				0,
			),
			InitiateTeleport { assets, dest, xcm } =>
				sp_weights::Weight::from_parts(W::initiate_teleport(assets, dest, xcm), 0),
			QueryHolding { query_id, dest, assets, max_response_weight } =>
				sp_weights::Weight::from_parts(
					W::query_holding(query_id, dest, assets, max_response_weight),
					0,
				),
			BuyExecution { fees, weight_limit } =>
				sp_weights::Weight::from_parts(W::buy_execution(fees, weight_limit), 0),
			RefundSurplus => sp_weights::Weight::from_parts(W::refund_surplus(), 0),
			SetErrorHandler(xcm) => sp_weights::Weight::from_parts(W::set_error_handler(xcm), 0),
			SetAppendix(xcm) => sp_weights::Weight::from_parts(W::set_appendix(xcm), 0),
			ClearError => sp_weights::Weight::from_parts(W::clear_error(), 0),
			ClaimAsset { assets, ticket } =>
				sp_weights::Weight::from_parts(W::claim_asset(assets, ticket), 0),
			Trap(code) => sp_weights::Weight::from_parts(W::trap(code), 0),
			SubscribeVersion { query_id, max_response_weight } => sp_weights::Weight::from_parts(
				W::subscribe_version(query_id, max_response_weight),
				0,
			),
			UnsubscribeVersion => sp_weights::Weight::from_parts(W::unsubscribe_version(), 0),
		}
	}
}
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 response to a v2 response
impl TryFrom<NewResponse> for Response {
	type Error = ();
	fn try_from(response: NewResponse) -> result::Result<Self, ()> {
		Ok(match response {
			NewResponse::Assets(assets) => Self::Assets(assets.try_into()?),
			NewResponse::Version(version) => Self::Version(version),
			NewResponse::ExecutionResult(error) => Self::ExecutionResult(match error {
				Some((i, e)) => Some((i, e.try_into()?)),
				None => None,
			}),
			NewResponse::Null => Self::Null,
			_ => return Err(()),
		})
	}
}
// Convert from a v3 XCM to a v2 XCM.
impl<RuntimeCall> TryFrom<NewXcm<RuntimeCall>> for Xcm<RuntimeCall> {
	type Error = ();
	fn try_from(new_xcm: NewXcm<RuntimeCall>) -> result::Result<Self, ()> {
		Ok(Xcm(new_xcm.0.into_iter().map(TryInto::try_into).collect::<result::Result<_, _>>()?))
	}
}
// Convert from a v3 instruction to a v2 instruction
impl<RuntimeCall> TryFrom<NewInstruction<RuntimeCall>> for Instruction<RuntimeCall> {
	type Error = ();
	fn try_from(instruction: NewInstruction<RuntimeCall>) -> result::Result<Self, ()> {
		use NewInstruction::*;
		Ok(match 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, .. } => Self::QueryResponse {
				query_id,
				response: response.try_into()?,
				max_weight: max_weight.ref_time(),
			},
			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_type: origin_kind.into(),
				require_weight_at_most: require_weight_at_most.ref_time(),
				call: call.into(),
			},
			ReportError(response_info) => Self::ReportError {
				query_id: response_info.query_id,
				dest: response_info.destination.try_into()?,
				max_response_weight: response_info.max_weight.ref_time(),
			},
			DepositAsset { assets, beneficiary } => {
				let max_assets = assets.count().ok_or(())?;
				let beneficiary = beneficiary.try_into()?;
				let assets = assets.try_into()?;
				Self::DepositAsset { assets, max_assets, beneficiary }
			},
			DepositReserveAsset { assets, dest, xcm } => {
				let max_assets = assets.count().ok_or(())?;
				let dest = dest.try_into()?;
				let xcm = xcm.try_into()?;
				let assets = assets.try_into()?;
				Self::DepositReserveAsset { assets, max_assets, dest, xcm }
			},
			ExchangeAsset { give, want, .. } => {
				let give = give.try_into()?;
				let receive = want.try_into()?;
				Self::ExchangeAsset { give, receive }
			},
			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 } => Self::QueryHolding {
				query_id: response_info.query_id,
				dest: response_info.destination.try_into()?,
				assets: assets.try_into()?,
				max_response_weight: response_info.max_weight.ref_time(),
			},
			BuyExecution { fees, weight_limit } => {
				let fees = fees.try_into()?;
				let weight_limit = weight_limit.try_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: max_response_weight.ref_time(),
			},
			UnsubscribeVersion => Self::UnsubscribeVersion,
			i => {
				log::debug!(target: "xcm::v3tov2", "`{i:?}` not supported by v2");
				return Err(());
			},
		})
	}
}
#[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_assets: 1,
			};
			(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(), 345730);
		// This should not decode since the limit is 100
		assert_eq!(MAX_INSTRUCTIONS_TO_DECODE, 100, "precondition");
		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
	}
}