Skip to content

Commit

Permalink
XCM MultiAssets: sort after reanchoring (#2129)
Browse files Browse the repository at this point in the history
Fixes #2123
  • Loading branch information
serban300 authored and bkontur committed Nov 6, 2023
1 parent 78ef6b9 commit aa0ea96
Showing 1 changed file with 41 additions and 1 deletion.
42 changes: 41 additions & 1 deletion polkadot/xcm/src/v3/multiasset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,12 +689,16 @@ impl MultiAssets {

/// Mutate the location of the asset identifier if concrete, giving it the same location
/// relative to a `target` context. The local context is provided as `context`.
///
/// This will also re-sort the inner assets to preserve ordering guarantees.
pub fn reanchor(
&mut self,
target: &MultiLocation,
context: InteriorMultiLocation,
) -> Result<(), ()> {
self.0.iter_mut().try_for_each(|i| i.reanchor(target, context))
self.0.iter_mut().try_for_each(|i| i.reanchor(target, context))?;
self.0.sort();
Ok(())
}

/// Return a reference to an item at a specific index or `None` if it doesn't exist.
Expand Down Expand Up @@ -985,6 +989,42 @@ mod tests {
assert!(r.is_err());
}

#[test]
fn reanchor_preserves_sorting() {
use super::*;
use alloc::vec;

let reanchor_context = X1(Parachain(2000));
let dest = MultiLocation::new(1, Here);

let asset_1: MultiAsset =
(MultiLocation::new(0, X2(PalletInstance(50), GeneralIndex(1))), 10).into();
let mut asset_1_reanchored = asset_1.clone();
assert!(asset_1_reanchored.reanchor(&dest, reanchor_context).is_ok());
assert_eq!(
asset_1_reanchored,
(MultiLocation::new(0, X3(Parachain(2000), PalletInstance(50), GeneralIndex(1))), 10)
.into()
);

let asset_2: MultiAsset = (MultiLocation::new(1, Here), 10).into();
let mut asset_2_reanchored = asset_2.clone();
assert!(asset_2_reanchored.reanchor(&dest, reanchor_context).is_ok());
assert_eq!(asset_2_reanchored, (MultiLocation::new(0, Here), 10).into());

let asset_3: MultiAsset = (MultiLocation::new(1, X1(Parachain(1000))), 10).into();
let mut asset_3_reanchored = asset_3.clone();
assert!(asset_3_reanchored.reanchor(&dest, reanchor_context).is_ok());
assert_eq!(asset_3_reanchored, (MultiLocation::new(0, X1(Parachain(1000))), 10).into());

let mut assets: MultiAssets =
vec![asset_1.clone(), asset_2.clone(), asset_3.clone()].into();
assert_eq!(assets.clone(), vec![asset_1.clone(), asset_2.clone(), asset_3.clone()].into());

assert!(assets.reanchor(&dest, reanchor_context).is_ok());
assert_eq!(assets, vec![asset_2_reanchored, asset_3_reanchored, asset_1_reanchored].into());
}

#[test]
fn decoding_respects_limit() {
use super::*;
Expand Down

0 comments on commit aa0ea96

Please sign in to comment.