diff --git a/polkadot/xcm/src/v3/multiasset.rs b/polkadot/xcm/src/v3/multiasset.rs index b078c9f456777..dc88eb60b7c12 100644 --- a/polkadot/xcm/src/v3/multiasset.rs +++ b/polkadot/xcm/src/v3/multiasset.rs @@ -587,10 +587,13 @@ impl MaxEncodedLen for MultiAssets { impl Decode for MultiAssets { fn decode(input: &mut I) -> Result { - let bounded_instructions = + let mut bounded_instructions = BoundedVec::>::decode(input)?; + + bounded_instructions.sort(); + Self::from_sorted_and_deduplicated(bounded_instructions.into_inner()) - .map_err(|()| "Out of order".into()) + .map_err(|()| "Duplicate items".into()) } } @@ -682,6 +685,7 @@ impl MultiAssets { pub fn from_sorted_and_deduplicated_skip_checks(r: Vec) -> Self { Self::from_sorted_and_deduplicated(r).expect("Invalid input r is not sorted/deduped") } + /// Create a new instance of `MultiAssets` from a `Vec` whose contents are sorted /// and which contain no duplicates. /// diff --git a/polkadot/xcm/src/v4/asset.rs b/polkadot/xcm/src/v4/asset.rs index ed2c8c8671d96..fe792e5748551 100644 --- a/polkadot/xcm/src/v4/asset.rs +++ b/polkadot/xcm/src/v4/asset.rs @@ -624,10 +624,13 @@ impl MaxEncodedLen for Assets { impl Decode for Assets { fn decode(input: &mut I) -> Result { - let bounded_instructions = + let mut bounded_instructions = BoundedVec::>::decode(input)?; + + bounded_instructions.sort(); + Self::from_sorted_and_deduplicated(bounded_instructions.into_inner()) - .map_err(|()| "Out of order".into()) + .map_err(|()| "Duplicate items".into()) } } diff --git a/polkadot/xcm/src/v5/asset.rs b/polkadot/xcm/src/v5/asset.rs index 9888e339bbce1..ef1a543ae7571 100644 --- a/polkadot/xcm/src/v5/asset.rs +++ b/polkadot/xcm/src/v5/asset.rs @@ -562,10 +562,13 @@ impl MaxEncodedLen for Assets { impl Decode for Assets { fn decode(input: &mut I) -> Result { - let bounded_instructions = + let mut bounded_instructions = BoundedVec::>::decode(input)?; + + bounded_instructions.sort(); + Self::from_sorted_and_deduplicated(bounded_instructions.into_inner()) - .map_err(|()| "Out of order".into()) + .map_err(|()| "Duplicate items".into()) } } diff --git a/prdoc/pr_9842.prdoc b/prdoc/pr_9842.prdoc new file mode 100644 index 0000000000000..890567c7957d6 --- /dev/null +++ b/prdoc/pr_9842.prdoc @@ -0,0 +1,8 @@ +title: 'xcm: Do not require `Asset` to be sorted on `decode`' +doc: +- audience: Runtime User + description: |- + `Asset` was requiring that all the assets are sorted at decoding. This is quite confusing for people writingg frontends, because this is not really documented anywhere. There are also only at max 20 assets available, we can just make everyones life easier and always sort the assets after decoding. +crates: +- name: staging-xcm + bump: patch