mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 20:21:03 +00:00
XCMv4 (#1230)
# Note for reviewer
Most changes are just syntax changes necessary for the new version.
Most important files should be the ones under the `xcm` folder.
# Description
Added XCMv4.
## Removed `Multi` prefix
The following types have been renamed:
- MultiLocation -> Location
- MultiAsset -> Asset
- MultiAssets -> Assets
- InteriorMultiLocation -> InteriorLocation
- MultiAssetFilter -> AssetFilter
- VersionedMultiAsset -> VersionedAsset
- WildMultiAsset -> WildAsset
- VersionedMultiLocation -> VersionedLocation
In order to fix a name conflict, the `Assets` in `xcm-executor` were
renamed to `HoldingAssets`, as they represent assets in holding.
## Removed `Abstract` asset id
It was not being used anywhere and this simplifies the code.
Now assets are just constructed as follows:
```rust
let asset: Asset = (AssetId(Location::new(1, Here)), 100u128).into();
```
No need for specifying `Concrete` anymore.
## Outcome is now a named fields struct
Instead of
```rust
pub enum Outcome {
Complete(Weight),
Incomplete(Weight, Error),
Error(Error),
}
```
we now have
```rust
pub enum Outcome {
Complete { used: Weight },
Incomplete { used: Weight, error: Error },
Error { error: Error },
}
```
## Added Reanchorable trait
Now both locations and assets implement this trait, making it easier to
reanchor both.
## New syntax for building locations and junctions
Now junctions are built using the following methods:
```rust
let location = Location {
parents: 1,
interior: [Parachain(1000), PalletInstance(50), GeneralIndex(1984)].into()
};
```
or
```rust
let location = Location::new(1, [Parachain(1000), PalletInstance(50), GeneralIndex(1984)]);
```
And they are matched like so:
```rust
match location.unpack() {
(1, [Parachain(id)]) => ...
(0, Here) => ...,
(1, [_]) => ...,
}
```
This syntax is mandatory in v4, and has been also implemented for v2 and
v3 for easier migration.
This was needed to make all sizes smaller.
# TODO
- [x] Scaffold v4
- [x] Port github.com/paritytech/polkadot/pull/7236
- [x] Remove `Multi` prefix
- [x] Remove `Abstract` asset id
---------
Co-authored-by: command-bot <>
Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
This commit is contained in:
committed by
GitHub
parent
ec7bfae00a
commit
8428f678fe
@@ -23,39 +23,42 @@ use xcm::latest::prelude::*;
|
||||
use xcm_executor::traits::{Error as MatchError, MatchesFungibles, MatchesNonFungibles};
|
||||
|
||||
/// Converter struct implementing `AssetIdConversion` converting a numeric asset ID (must be
|
||||
/// `TryFrom/TryInto<u128>`) into a `GeneralIndex` junction, prefixed by some `MultiLocation` value.
|
||||
/// The `MultiLocation` value will typically be a `PalletInstance` junction.
|
||||
pub struct AsPrefixedGeneralIndex<Prefix, AssetId, ConvertAssetId>(
|
||||
PhantomData<(Prefix, AssetId, ConvertAssetId)>,
|
||||
/// `TryFrom/TryInto<u128>`) into a `GeneralIndex` junction, prefixed by some `Location` value.
|
||||
/// The `Location` value will typically be a `PalletInstance` junction.
|
||||
pub struct AsPrefixedGeneralIndex<Prefix, AssetId, ConvertAssetId, L = Location>(
|
||||
PhantomData<(Prefix, AssetId, ConvertAssetId, L)>,
|
||||
);
|
||||
impl<
|
||||
Prefix: Get<MultiLocation>,
|
||||
Prefix: Get<L>,
|
||||
AssetId: Clone,
|
||||
ConvertAssetId: MaybeEquivalence<u128, AssetId>,
|
||||
> MaybeEquivalence<MultiLocation, AssetId>
|
||||
for AsPrefixedGeneralIndex<Prefix, AssetId, ConvertAssetId>
|
||||
L: TryInto<Location> + TryFrom<Location> + Clone,
|
||||
> MaybeEquivalence<L, AssetId> for AsPrefixedGeneralIndex<Prefix, AssetId, ConvertAssetId, L>
|
||||
{
|
||||
fn convert(id: &MultiLocation) -> Option<AssetId> {
|
||||
fn convert(id: &L) -> Option<AssetId> {
|
||||
let prefix = Prefix::get();
|
||||
if prefix.parent_count() != id.parent_count() ||
|
||||
prefix
|
||||
let latest_prefix: Location = prefix.try_into().ok()?;
|
||||
let latest_id: Location = (*id).clone().try_into().ok()?;
|
||||
if latest_prefix.parent_count() != latest_id.parent_count() ||
|
||||
latest_prefix
|
||||
.interior()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.any(|(index, junction)| id.interior().at(index) != Some(junction))
|
||||
.any(|(index, junction)| latest_id.interior().at(index) != Some(junction))
|
||||
{
|
||||
return None
|
||||
}
|
||||
match id.interior().at(prefix.interior().len()) {
|
||||
Some(Junction::GeneralIndex(id)) => ConvertAssetId::convert(id),
|
||||
match latest_id.interior().at(latest_prefix.interior().len()) {
|
||||
Some(Junction::GeneralIndex(id)) => ConvertAssetId::convert(&id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn convert_back(what: &AssetId) -> Option<MultiLocation> {
|
||||
let mut location = Prefix::get();
|
||||
fn convert_back(what: &AssetId) -> Option<L> {
|
||||
let location = Prefix::get();
|
||||
let mut latest_location: Location = location.try_into().ok()?;
|
||||
let id = ConvertAssetId::convert_back(what)?;
|
||||
location.push_interior(Junction::GeneralIndex(id)).ok()?;
|
||||
Some(location)
|
||||
latest_location.push_interior(Junction::GeneralIndex(id)).ok()?;
|
||||
latest_location.try_into().ok()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,14 +68,14 @@ pub struct ConvertedConcreteId<AssetId, Balance, ConvertAssetId, ConvertOther>(
|
||||
impl<
|
||||
AssetId: Clone,
|
||||
Balance: Clone,
|
||||
ConvertAssetId: MaybeEquivalence<MultiLocation, AssetId>,
|
||||
ConvertAssetId: MaybeEquivalence<Location, AssetId>,
|
||||
ConvertBalance: MaybeEquivalence<u128, Balance>,
|
||||
> MatchesFungibles<AssetId, Balance>
|
||||
for ConvertedConcreteId<AssetId, Balance, ConvertAssetId, ConvertBalance>
|
||||
{
|
||||
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), MatchError> {
|
||||
fn matches_fungibles(a: &Asset) -> result::Result<(AssetId, Balance), MatchError> {
|
||||
let (amount, id) = match (&a.fun, &a.id) {
|
||||
(Fungible(ref amount), Concrete(ref id)) => (amount, id),
|
||||
(Fungible(ref amount), AssetId(ref id)) => (amount, id),
|
||||
_ => return Err(MatchError::AssetNotHandled),
|
||||
};
|
||||
let what = ConvertAssetId::convert(id).ok_or(MatchError::AssetIdConversionFailed)?;
|
||||
@@ -84,56 +87,14 @@ impl<
|
||||
impl<
|
||||
ClassId: Clone,
|
||||
InstanceId: Clone,
|
||||
ConvertClassId: MaybeEquivalence<MultiLocation, ClassId>,
|
||||
ConvertClassId: MaybeEquivalence<Location, ClassId>,
|
||||
ConvertInstanceId: MaybeEquivalence<AssetInstance, InstanceId>,
|
||||
> MatchesNonFungibles<ClassId, InstanceId>
|
||||
for ConvertedConcreteId<ClassId, InstanceId, ConvertClassId, ConvertInstanceId>
|
||||
{
|
||||
fn matches_nonfungibles(a: &MultiAsset) -> result::Result<(ClassId, InstanceId), MatchError> {
|
||||
fn matches_nonfungibles(a: &Asset) -> result::Result<(ClassId, InstanceId), MatchError> {
|
||||
let (instance, class) = match (&a.fun, &a.id) {
|
||||
(NonFungible(ref instance), Concrete(ref class)) => (instance, class),
|
||||
_ => return Err(MatchError::AssetNotHandled),
|
||||
};
|
||||
let what = ConvertClassId::convert(class).ok_or(MatchError::AssetIdConversionFailed)?;
|
||||
let instance =
|
||||
ConvertInstanceId::convert(instance).ok_or(MatchError::InstanceConversionFailed)?;
|
||||
Ok((what, instance))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConvertedAbstractId<AssetId, Balance, ConvertAssetId, ConvertOther>(
|
||||
PhantomData<(AssetId, Balance, ConvertAssetId, ConvertOther)>,
|
||||
);
|
||||
impl<
|
||||
AssetId: Clone,
|
||||
Balance: Clone,
|
||||
ConvertAssetId: MaybeEquivalence<[u8; 32], AssetId>,
|
||||
ConvertBalance: MaybeEquivalence<u128, Balance>,
|
||||
> MatchesFungibles<AssetId, Balance>
|
||||
for ConvertedAbstractId<AssetId, Balance, ConvertAssetId, ConvertBalance>
|
||||
{
|
||||
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), MatchError> {
|
||||
let (amount, id) = match (&a.fun, &a.id) {
|
||||
(Fungible(ref amount), Abstract(ref id)) => (amount, id),
|
||||
_ => return Err(MatchError::AssetNotHandled),
|
||||
};
|
||||
let what = ConvertAssetId::convert(id).ok_or(MatchError::AssetIdConversionFailed)?;
|
||||
let amount =
|
||||
ConvertBalance::convert(amount).ok_or(MatchError::AmountToBalanceConversionFailed)?;
|
||||
Ok((what, amount))
|
||||
}
|
||||
}
|
||||
impl<
|
||||
ClassId: Clone,
|
||||
InstanceId: Clone,
|
||||
ConvertClassId: MaybeEquivalence<[u8; 32], ClassId>,
|
||||
ConvertInstanceId: MaybeEquivalence<AssetInstance, InstanceId>,
|
||||
> MatchesNonFungibles<ClassId, InstanceId>
|
||||
for ConvertedAbstractId<ClassId, InstanceId, ConvertClassId, ConvertInstanceId>
|
||||
{
|
||||
fn matches_nonfungibles(a: &MultiAsset) -> result::Result<(ClassId, InstanceId), MatchError> {
|
||||
let (instance, class) = match (&a.fun, &a.id) {
|
||||
(NonFungible(ref instance), Abstract(ref class)) => (instance, class),
|
||||
(NonFungible(ref instance), AssetId(ref class)) => (instance, class),
|
||||
_ => return Err(MatchError::AssetNotHandled),
|
||||
};
|
||||
let what = ConvertClassId::convert(class).ok_or(MatchError::AssetIdConversionFailed)?;
|
||||
@@ -145,8 +106,17 @@ impl<
|
||||
|
||||
#[deprecated = "Use `ConvertedConcreteId` instead"]
|
||||
pub type ConvertedConcreteAssetId<A, B, C, O> = ConvertedConcreteId<A, B, C, O>;
|
||||
#[deprecated = "Use `ConvertedAbstractId` instead"]
|
||||
pub type ConvertedAbstractAssetId<A, B, C, O> = ConvertedAbstractId<A, B, C, O>;
|
||||
|
||||
pub struct V4V3LocationConverter;
|
||||
impl MaybeEquivalence<xcm::v4::Location, xcm::v3::Location> for V4V3LocationConverter {
|
||||
fn convert(old: &xcm::v4::Location) -> Option<xcm::v3::Location> {
|
||||
(*old).clone().try_into().ok()
|
||||
}
|
||||
|
||||
fn convert_back(new: &xcm::v3::Location) -> Option<xcm::v4::Location> {
|
||||
(*new).try_into().ok()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MatchedConvertedConcreteId<AssetId, Balance, MatchAssetId, ConvertAssetId, ConvertOther>(
|
||||
PhantomData<(AssetId, Balance, MatchAssetId, ConvertAssetId, ConvertOther)>,
|
||||
@@ -154,15 +124,15 @@ pub struct MatchedConvertedConcreteId<AssetId, Balance, MatchAssetId, ConvertAss
|
||||
impl<
|
||||
AssetId: Clone,
|
||||
Balance: Clone,
|
||||
MatchAssetId: Contains<MultiLocation>,
|
||||
ConvertAssetId: MaybeEquivalence<MultiLocation, AssetId>,
|
||||
MatchAssetId: Contains<Location>,
|
||||
ConvertAssetId: MaybeEquivalence<Location, AssetId>,
|
||||
ConvertBalance: MaybeEquivalence<u128, Balance>,
|
||||
> MatchesFungibles<AssetId, Balance>
|
||||
for MatchedConvertedConcreteId<AssetId, Balance, MatchAssetId, ConvertAssetId, ConvertBalance>
|
||||
{
|
||||
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), MatchError> {
|
||||
fn matches_fungibles(a: &Asset) -> result::Result<(AssetId, Balance), MatchError> {
|
||||
let (amount, id) = match (&a.fun, &a.id) {
|
||||
(Fungible(ref amount), Concrete(ref id)) if MatchAssetId::contains(id) => (amount, id),
|
||||
(Fungible(ref amount), AssetId(ref id)) if MatchAssetId::contains(id) => (amount, id),
|
||||
_ => return Err(MatchError::AssetNotHandled),
|
||||
};
|
||||
let what = ConvertAssetId::convert(id).ok_or(MatchError::AssetIdConversionFailed)?;
|
||||
@@ -174,15 +144,15 @@ impl<
|
||||
impl<
|
||||
ClassId: Clone,
|
||||
InstanceId: Clone,
|
||||
MatchClassId: Contains<MultiLocation>,
|
||||
ConvertClassId: MaybeEquivalence<MultiLocation, ClassId>,
|
||||
MatchClassId: Contains<Location>,
|
||||
ConvertClassId: MaybeEquivalence<Location, ClassId>,
|
||||
ConvertInstanceId: MaybeEquivalence<AssetInstance, InstanceId>,
|
||||
> MatchesNonFungibles<ClassId, InstanceId>
|
||||
for MatchedConvertedConcreteId<ClassId, InstanceId, MatchClassId, ConvertClassId, ConvertInstanceId>
|
||||
{
|
||||
fn matches_nonfungibles(a: &MultiAsset) -> result::Result<(ClassId, InstanceId), MatchError> {
|
||||
fn matches_nonfungibles(a: &Asset) -> result::Result<(ClassId, InstanceId), MatchError> {
|
||||
let (instance, class) = match (&a.fun, &a.id) {
|
||||
(NonFungible(ref instance), Concrete(ref class)) if MatchClassId::contains(class) =>
|
||||
(NonFungible(ref instance), AssetId(ref class)) if MatchClassId::contains(class) =>
|
||||
(instance, class),
|
||||
_ => return Err(MatchError::AssetNotHandled),
|
||||
};
|
||||
@@ -200,10 +170,10 @@ mod tests {
|
||||
use xcm_executor::traits::JustTry;
|
||||
|
||||
struct OnlyParentZero;
|
||||
impl Contains<MultiLocation> for OnlyParentZero {
|
||||
fn contains(a: &MultiLocation) -> bool {
|
||||
impl Contains<Location> for OnlyParentZero {
|
||||
fn contains(a: &Location) -> bool {
|
||||
match a {
|
||||
MultiLocation { parents: 0, .. } => true,
|
||||
Location { parents: 0, .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -214,7 +184,7 @@ mod tests {
|
||||
type AssetIdForTrustBackedAssets = u32;
|
||||
type Balance = u128;
|
||||
frame_support::parameter_types! {
|
||||
pub TrustBackedAssetsPalletLocation: MultiLocation = PalletInstance(50).into();
|
||||
pub TrustBackedAssetsPalletLocation: Location = PalletInstance(50).into();
|
||||
}
|
||||
|
||||
// ConvertedConcreteId cfg
|
||||
@@ -231,13 +201,13 @@ mod tests {
|
||||
>;
|
||||
assert_eq!(
|
||||
TrustBackedAssetsPalletLocation::get(),
|
||||
MultiLocation { parents: 0, interior: X1(PalletInstance(50)) }
|
||||
Location { parents: 0, interior: [PalletInstance(50)].into() }
|
||||
);
|
||||
|
||||
// err - does not match
|
||||
assert_eq!(
|
||||
Converter::matches_fungibles(&MultiAsset {
|
||||
id: Concrete(MultiLocation::new(1, X2(PalletInstance(50), GeneralIndex(1)))),
|
||||
Converter::matches_fungibles(&Asset {
|
||||
id: AssetId(Location::new(1, [PalletInstance(50), GeneralIndex(1)])),
|
||||
fun: Fungible(12345),
|
||||
}),
|
||||
Err(MatchError::AssetNotHandled)
|
||||
@@ -245,10 +215,10 @@ mod tests {
|
||||
|
||||
// err - matches, but convert fails
|
||||
assert_eq!(
|
||||
Converter::matches_fungibles(&MultiAsset {
|
||||
id: Concrete(MultiLocation::new(
|
||||
Converter::matches_fungibles(&Asset {
|
||||
id: AssetId(Location::new(
|
||||
0,
|
||||
X2(PalletInstance(50), GeneralKey { length: 1, data: [1; 32] })
|
||||
[PalletInstance(50), GeneralKey { length: 1, data: [1; 32] }]
|
||||
)),
|
||||
fun: Fungible(12345),
|
||||
}),
|
||||
@@ -257,8 +227,8 @@ mod tests {
|
||||
|
||||
// err - matches, but NonFungible
|
||||
assert_eq!(
|
||||
Converter::matches_fungibles(&MultiAsset {
|
||||
id: Concrete(MultiLocation::new(0, X2(PalletInstance(50), GeneralIndex(1)))),
|
||||
Converter::matches_fungibles(&Asset {
|
||||
id: AssetId(Location::new(0, [PalletInstance(50), GeneralIndex(1)])),
|
||||
fun: NonFungible(Index(54321)),
|
||||
}),
|
||||
Err(MatchError::AssetNotHandled)
|
||||
@@ -266,8 +236,8 @@ mod tests {
|
||||
|
||||
// ok
|
||||
assert_eq!(
|
||||
Converter::matches_fungibles(&MultiAsset {
|
||||
id: Concrete(MultiLocation::new(0, X2(PalletInstance(50), GeneralIndex(1)))),
|
||||
Converter::matches_fungibles(&Asset {
|
||||
id: AssetId(Location::new(0, [PalletInstance(50), GeneralIndex(1)])),
|
||||
fun: Fungible(12345),
|
||||
}),
|
||||
Ok((1, 12345))
|
||||
@@ -279,7 +249,7 @@ mod tests {
|
||||
type ClassId = u32;
|
||||
type ClassInstanceId = u64;
|
||||
frame_support::parameter_types! {
|
||||
pub TrustBackedAssetsPalletLocation: MultiLocation = PalletInstance(50).into();
|
||||
pub TrustBackedAssetsPalletLocation: Location = PalletInstance(50).into();
|
||||
}
|
||||
|
||||
// ConvertedConcreteId cfg
|
||||
@@ -303,13 +273,13 @@ mod tests {
|
||||
>;
|
||||
assert_eq!(
|
||||
TrustBackedAssetsPalletLocation::get(),
|
||||
MultiLocation { parents: 0, interior: X1(PalletInstance(50)) }
|
||||
Location { parents: 0, interior: [PalletInstance(50)].into() }
|
||||
);
|
||||
|
||||
// err - does not match
|
||||
assert_eq!(
|
||||
Converter::matches_nonfungibles(&MultiAsset {
|
||||
id: Concrete(MultiLocation::new(1, X2(PalletInstance(50), GeneralIndex(1)))),
|
||||
Converter::matches_nonfungibles(&Asset {
|
||||
id: AssetId(Location::new(1, [PalletInstance(50), GeneralIndex(1)])),
|
||||
fun: NonFungible(Index(54321)),
|
||||
}),
|
||||
Err(MatchError::AssetNotHandled)
|
||||
@@ -317,10 +287,10 @@ mod tests {
|
||||
|
||||
// err - matches, but convert fails
|
||||
assert_eq!(
|
||||
Converter::matches_nonfungibles(&MultiAsset {
|
||||
id: Concrete(MultiLocation::new(
|
||||
Converter::matches_nonfungibles(&Asset {
|
||||
id: AssetId(Location::new(
|
||||
0,
|
||||
X2(PalletInstance(50), GeneralKey { length: 1, data: [1; 32] })
|
||||
[PalletInstance(50), GeneralKey { length: 1, data: [1; 32] }]
|
||||
)),
|
||||
fun: NonFungible(Index(54321)),
|
||||
}),
|
||||
@@ -329,8 +299,8 @@ mod tests {
|
||||
|
||||
// err - matches, but Fungible vs NonFungible
|
||||
assert_eq!(
|
||||
Converter::matches_nonfungibles(&MultiAsset {
|
||||
id: Concrete(MultiLocation::new(0, X2(PalletInstance(50), GeneralIndex(1)))),
|
||||
Converter::matches_nonfungibles(&Asset {
|
||||
id: AssetId(Location::new(0, [PalletInstance(50), GeneralIndex(1)])),
|
||||
fun: Fungible(12345),
|
||||
}),
|
||||
Err(MatchError::AssetNotHandled)
|
||||
@@ -338,8 +308,8 @@ mod tests {
|
||||
|
||||
// ok
|
||||
assert_eq!(
|
||||
Converter::matches_nonfungibles(&MultiAsset {
|
||||
id: Concrete(MultiLocation::new(0, X2(PalletInstance(50), GeneralIndex(1)))),
|
||||
Converter::matches_nonfungibles(&Asset {
|
||||
id: AssetId(Location::new(0, [PalletInstance(50), GeneralIndex(1)])),
|
||||
fun: NonFungible(Index(54321)),
|
||||
}),
|
||||
Ok((1, 54321))
|
||||
|
||||
@@ -34,7 +34,7 @@ use xcm_executor::traits::{CheckSuspension, OnResponse, Properties, ShouldExecut
|
||||
pub struct TakeWeightCredit;
|
||||
impl ShouldExecute for TakeWeightCredit {
|
||||
fn should_execute<RuntimeCall>(
|
||||
_origin: &MultiLocation,
|
||||
_origin: &Location,
|
||||
_instructions: &mut [Instruction<RuntimeCall>],
|
||||
max_weight: Weight,
|
||||
properties: &mut Properties,
|
||||
@@ -60,9 +60,9 @@ const MAX_ASSETS_FOR_BUY_EXECUTION: usize = 2;
|
||||
/// Only allows for `TeleportAsset`, `WithdrawAsset`, `ClaimAsset` and `ReserveAssetDeposit` XCMs
|
||||
/// because they are the only ones that place assets in the Holding Register to pay for execution.
|
||||
pub struct AllowTopLevelPaidExecutionFrom<T>(PhantomData<T>);
|
||||
impl<T: Contains<MultiLocation>> ShouldExecute for AllowTopLevelPaidExecutionFrom<T> {
|
||||
impl<T: Contains<Location>> ShouldExecute for AllowTopLevelPaidExecutionFrom<T> {
|
||||
fn should_execute<RuntimeCall>(
|
||||
origin: &MultiLocation,
|
||||
origin: &Location,
|
||||
instructions: &mut [Instruction<RuntimeCall>],
|
||||
max_weight: Weight,
|
||||
_properties: &mut Properties,
|
||||
@@ -158,14 +158,11 @@ impl<T: Contains<MultiLocation>> ShouldExecute for AllowTopLevelPaidExecutionFro
|
||||
pub struct WithComputedOrigin<InnerBarrier, LocalUniversal, MaxPrefixes>(
|
||||
PhantomData<(InnerBarrier, LocalUniversal, MaxPrefixes)>,
|
||||
);
|
||||
impl<
|
||||
InnerBarrier: ShouldExecute,
|
||||
LocalUniversal: Get<InteriorMultiLocation>,
|
||||
MaxPrefixes: Get<u32>,
|
||||
> ShouldExecute for WithComputedOrigin<InnerBarrier, LocalUniversal, MaxPrefixes>
|
||||
impl<InnerBarrier: ShouldExecute, LocalUniversal: Get<InteriorLocation>, MaxPrefixes: Get<u32>>
|
||||
ShouldExecute for WithComputedOrigin<InnerBarrier, LocalUniversal, MaxPrefixes>
|
||||
{
|
||||
fn should_execute<Call>(
|
||||
origin: &MultiLocation,
|
||||
origin: &Location,
|
||||
instructions: &mut [Instruction<Call>],
|
||||
max_weight: Weight,
|
||||
properties: &mut Properties,
|
||||
@@ -175,7 +172,7 @@ impl<
|
||||
"WithComputedOrigin origin: {:?}, instructions: {:?}, max_weight: {:?}, properties: {:?}",
|
||||
origin, instructions, max_weight, properties,
|
||||
);
|
||||
let mut actual_origin = *origin;
|
||||
let mut actual_origin = origin.clone();
|
||||
let skipped = Cell::new(0usize);
|
||||
// NOTE: We do not check the validity of `UniversalOrigin` here, meaning that a malicious
|
||||
// origin could place a `UniversalOrigin` in order to spoof some location which gets free
|
||||
@@ -190,10 +187,11 @@ impl<
|
||||
// Note the origin is *relative to local consensus*! So we need to escape
|
||||
// local consensus with the `parents` before diving in into the
|
||||
// `universal_location`.
|
||||
actual_origin = X1(*new_global).relative_to(&LocalUniversal::get());
|
||||
actual_origin =
|
||||
Junctions::from([*new_global]).relative_to(&LocalUniversal::get());
|
||||
},
|
||||
DescendOrigin(j) => {
|
||||
let Ok(_) = actual_origin.append_with(*j) else {
|
||||
let Ok(_) = actual_origin.append_with(j.clone()) else {
|
||||
return Err(ProcessMessageError::Unsupported)
|
||||
};
|
||||
},
|
||||
@@ -221,7 +219,7 @@ impl<
|
||||
pub struct TrailingSetTopicAsId<InnerBarrier>(PhantomData<InnerBarrier>);
|
||||
impl<InnerBarrier: ShouldExecute> ShouldExecute for TrailingSetTopicAsId<InnerBarrier> {
|
||||
fn should_execute<Call>(
|
||||
origin: &MultiLocation,
|
||||
origin: &Location,
|
||||
instructions: &mut [Instruction<Call>],
|
||||
max_weight: Weight,
|
||||
properties: &mut Properties,
|
||||
@@ -250,7 +248,7 @@ where
|
||||
SuspensionChecker: CheckSuspension,
|
||||
{
|
||||
fn should_execute<Call>(
|
||||
origin: &MultiLocation,
|
||||
origin: &Location,
|
||||
instructions: &mut [Instruction<Call>],
|
||||
max_weight: Weight,
|
||||
properties: &mut Properties,
|
||||
@@ -268,9 +266,9 @@ where
|
||||
/// Use only for executions from completely trusted origins, from which no permissionless messages
|
||||
/// can be sent.
|
||||
pub struct AllowUnpaidExecutionFrom<T>(PhantomData<T>);
|
||||
impl<T: Contains<MultiLocation>> ShouldExecute for AllowUnpaidExecutionFrom<T> {
|
||||
impl<T: Contains<Location>> ShouldExecute for AllowUnpaidExecutionFrom<T> {
|
||||
fn should_execute<RuntimeCall>(
|
||||
origin: &MultiLocation,
|
||||
origin: &Location,
|
||||
instructions: &mut [Instruction<RuntimeCall>],
|
||||
_max_weight: Weight,
|
||||
_properties: &mut Properties,
|
||||
@@ -290,9 +288,9 @@ impl<T: Contains<MultiLocation>> ShouldExecute for AllowUnpaidExecutionFrom<T> {
|
||||
///
|
||||
/// Use only for executions from trusted origin groups.
|
||||
pub struct AllowExplicitUnpaidExecutionFrom<T>(PhantomData<T>);
|
||||
impl<T: Contains<MultiLocation>> ShouldExecute for AllowExplicitUnpaidExecutionFrom<T> {
|
||||
impl<T: Contains<Location>> ShouldExecute for AllowExplicitUnpaidExecutionFrom<T> {
|
||||
fn should_execute<Call>(
|
||||
origin: &MultiLocation,
|
||||
origin: &Location,
|
||||
instructions: &mut [Instruction<Call>],
|
||||
max_weight: Weight,
|
||||
_properties: &mut Properties,
|
||||
@@ -314,11 +312,11 @@ impl<T: Contains<MultiLocation>> ShouldExecute for AllowExplicitUnpaidExecutionF
|
||||
|
||||
/// Allows a message only if it is from a system-level child parachain.
|
||||
pub struct IsChildSystemParachain<ParaId>(PhantomData<ParaId>);
|
||||
impl<ParaId: IsSystem + From<u32>> Contains<MultiLocation> for IsChildSystemParachain<ParaId> {
|
||||
fn contains(l: &MultiLocation) -> bool {
|
||||
impl<ParaId: IsSystem + From<u32>> Contains<Location> for IsChildSystemParachain<ParaId> {
|
||||
fn contains(l: &Location) -> bool {
|
||||
matches!(
|
||||
l.interior(),
|
||||
Junctions::X1(Junction::Parachain(id))
|
||||
l.interior().as_slice(),
|
||||
[Junction::Parachain(id)]
|
||||
if ParaId::from(*id).is_system() && l.parent_count() == 0,
|
||||
)
|
||||
}
|
||||
@@ -328,7 +326,7 @@ impl<ParaId: IsSystem + From<u32>> Contains<MultiLocation> for IsChildSystemPara
|
||||
pub struct AllowKnownQueryResponses<ResponseHandler>(PhantomData<ResponseHandler>);
|
||||
impl<ResponseHandler: OnResponse> ShouldExecute for AllowKnownQueryResponses<ResponseHandler> {
|
||||
fn should_execute<RuntimeCall>(
|
||||
origin: &MultiLocation,
|
||||
origin: &Location,
|
||||
instructions: &mut [Instruction<RuntimeCall>],
|
||||
_max_weight: Weight,
|
||||
_properties: &mut Properties,
|
||||
@@ -354,9 +352,9 @@ impl<ResponseHandler: OnResponse> ShouldExecute for AllowKnownQueryResponses<Res
|
||||
/// Allows execution from `origin` if it is just a straight `SubscribeVersion` or
|
||||
/// `UnsubscribeVersion` instruction.
|
||||
pub struct AllowSubscriptionsFrom<T>(PhantomData<T>);
|
||||
impl<T: Contains<MultiLocation>> ShouldExecute for AllowSubscriptionsFrom<T> {
|
||||
impl<T: Contains<Location>> ShouldExecute for AllowSubscriptionsFrom<T> {
|
||||
fn should_execute<RuntimeCall>(
|
||||
origin: &MultiLocation,
|
||||
origin: &Location,
|
||||
instructions: &mut [Instruction<RuntimeCall>],
|
||||
_max_weight: Weight,
|
||||
_properties: &mut Properties,
|
||||
@@ -391,7 +389,7 @@ where
|
||||
Allow: ShouldExecute,
|
||||
{
|
||||
fn should_execute<RuntimeCall>(
|
||||
origin: &MultiLocation,
|
||||
origin: &Location,
|
||||
message: &mut [Instruction<RuntimeCall>],
|
||||
max_weight: Weight,
|
||||
properties: &mut Properties,
|
||||
@@ -405,7 +403,7 @@ where
|
||||
pub struct DenyReserveTransferToRelayChain;
|
||||
impl ShouldExecute for DenyReserveTransferToRelayChain {
|
||||
fn should_execute<RuntimeCall>(
|
||||
origin: &MultiLocation,
|
||||
origin: &Location,
|
||||
message: &mut [Instruction<RuntimeCall>],
|
||||
_max_weight: Weight,
|
||||
_properties: &mut Properties,
|
||||
@@ -414,22 +412,18 @@ impl ShouldExecute for DenyReserveTransferToRelayChain {
|
||||
|_| true,
|
||||
|inst| match inst {
|
||||
InitiateReserveWithdraw {
|
||||
reserve: MultiLocation { parents: 1, interior: Here },
|
||||
reserve: Location { parents: 1, interior: Here },
|
||||
..
|
||||
} |
|
||||
DepositReserveAsset {
|
||||
dest: MultiLocation { parents: 1, interior: Here }, ..
|
||||
} |
|
||||
TransferReserveAsset {
|
||||
dest: MultiLocation { parents: 1, interior: Here }, ..
|
||||
} => {
|
||||
DepositReserveAsset { dest: Location { parents: 1, interior: Here }, .. } |
|
||||
TransferReserveAsset { dest: Location { parents: 1, interior: Here }, .. } => {
|
||||
Err(ProcessMessageError::Unsupported) // Deny
|
||||
},
|
||||
|
||||
// An unexpected reserve transfer has arrived from the Relay Chain. Generally,
|
||||
// `IsReserve` should not allow this, but we just log it here.
|
||||
ReserveAssetDeposited { .. }
|
||||
if matches!(origin, MultiLocation { parents: 1, interior: Here }) =>
|
||||
if matches!(origin, Location { parents: 1, interior: Here }) =>
|
||||
{
|
||||
log::warn!(
|
||||
target: "xcm::barrier",
|
||||
|
||||
@@ -45,7 +45,7 @@ pub trait ExecuteControllerWeightInfo {
|
||||
/// Execute an XCM locally, for a given origin.
|
||||
///
|
||||
/// An implementation of that trait will handle the low-level details of the execution, such as:
|
||||
/// - Validating and Converting the origin to a MultiLocation.
|
||||
/// - Validating and Converting the origin to a Location.
|
||||
/// - Handling versioning.
|
||||
/// - Calling the internal executor, which implements [`ExecuteXcm`].
|
||||
pub trait ExecuteController<Origin, RuntimeCall> {
|
||||
@@ -92,7 +92,7 @@ pub trait SendController<Origin> {
|
||||
/// - `msg`: the XCM to be sent.
|
||||
fn send(
|
||||
origin: Origin,
|
||||
dest: Box<VersionedMultiLocation>,
|
||||
dest: Box<VersionedLocation>,
|
||||
message: Box<VersionedXcm<()>>,
|
||||
) -> Result<XcmHash, DispatchError>;
|
||||
}
|
||||
@@ -127,7 +127,7 @@ pub trait QueryController<Origin, Timeout>: QueryHandler {
|
||||
fn query(
|
||||
origin: Origin,
|
||||
timeout: Timeout,
|
||||
match_querier: VersionedMultiLocation,
|
||||
match_querier: VersionedLocation,
|
||||
) -> Result<Self::QueryId, DispatchError>;
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ impl<Origin, RuntimeCall> ExecuteController<Origin, RuntimeCall> for () {
|
||||
_message: Box<VersionedXcm<RuntimeCall>>,
|
||||
_max_weight: Weight,
|
||||
) -> Result<Outcome, DispatchError> {
|
||||
Ok(Outcome::Error(XcmError::Unimplemented))
|
||||
Ok(Outcome::Error { error: XcmError::Unimplemented })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ impl<Origin> SendController<Origin> for () {
|
||||
type WeightInfo = ();
|
||||
fn send(
|
||||
_origin: Origin,
|
||||
_dest: Box<VersionedMultiLocation>,
|
||||
_dest: Box<VersionedLocation>,
|
||||
_message: Box<VersionedXcm<()>>,
|
||||
) -> Result<XcmHash, DispatchError> {
|
||||
Ok(Default::default())
|
||||
@@ -180,7 +180,7 @@ impl<Origin, Timeout> QueryController<Origin, Timeout> for () {
|
||||
fn query(
|
||||
_origin: Origin,
|
||||
_timeout: Timeout,
|
||||
_match_querier: VersionedMultiLocation,
|
||||
_match_querier: VersionedLocation,
|
||||
) -> Result<Self::QueryId, DispatchError> {
|
||||
Ok(Default::default())
|
||||
}
|
||||
|
||||
@@ -22,17 +22,17 @@ use super::MintLocation;
|
||||
use frame_support::traits::{ExistenceRequirement::AllowDeath, Get, WithdrawReasons};
|
||||
use sp_runtime::traits::CheckedSub;
|
||||
use sp_std::{marker::PhantomData, result};
|
||||
use xcm::latest::{Error as XcmError, MultiAsset, MultiLocation, Result, XcmContext};
|
||||
use xcm::latest::{Asset, Error as XcmError, Location, Result, XcmContext};
|
||||
use xcm_executor::{
|
||||
traits::{ConvertLocation, MatchesFungible, TransactAsset},
|
||||
Assets,
|
||||
AssetsInHolding,
|
||||
};
|
||||
|
||||
/// Asset transaction errors.
|
||||
enum Error {
|
||||
/// The given asset is not handled. (According to [`XcmError::AssetNotFound`])
|
||||
AssetNotHandled,
|
||||
/// `MultiLocation` to `AccountId` conversion failed.
|
||||
/// `Location` to `AccountId` conversion failed.
|
||||
AccountIdConversionFailed,
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ impl From<Error> for XcmError {
|
||||
///
|
||||
/// /// Our relay chain's location.
|
||||
/// parameter_types! {
|
||||
/// pub RelayChain: MultiLocation = Parent.into();
|
||||
/// pub RelayChain: Location = Parent.into();
|
||||
/// pub CheckingAccount: AccountId = PalletId(*b"checking").into_account_truncating();
|
||||
/// }
|
||||
///
|
||||
@@ -142,7 +142,7 @@ impl<
|
||||
> TransactAsset
|
||||
for CurrencyAdapter<Currency, Matcher, AccountIdConverter, AccountId, CheckedAccount>
|
||||
{
|
||||
fn can_check_in(_origin: &MultiLocation, what: &MultiAsset, _context: &XcmContext) -> Result {
|
||||
fn can_check_in(_origin: &Location, what: &Asset, _context: &XcmContext) -> Result {
|
||||
log::trace!(target: "xcm::currency_adapter", "can_check_in origin: {:?}, what: {:?}", _origin, what);
|
||||
// Check we handle this asset.
|
||||
let amount: Currency::Balance =
|
||||
@@ -156,7 +156,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn check_in(_origin: &MultiLocation, what: &MultiAsset, _context: &XcmContext) {
|
||||
fn check_in(_origin: &Location, what: &Asset, _context: &XcmContext) {
|
||||
log::trace!(target: "xcm::currency_adapter", "check_in origin: {:?}, what: {:?}", _origin, what);
|
||||
if let Some(amount) = Matcher::matches_fungible(what) {
|
||||
match CheckedAccount::get() {
|
||||
@@ -169,7 +169,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn can_check_out(_dest: &MultiLocation, what: &MultiAsset, _context: &XcmContext) -> Result {
|
||||
fn can_check_out(_dest: &Location, what: &Asset, _context: &XcmContext) -> Result {
|
||||
log::trace!(target: "xcm::currency_adapter", "check_out dest: {:?}, what: {:?}", _dest, what);
|
||||
let amount = Matcher::matches_fungible(what).ok_or(Error::AssetNotHandled)?;
|
||||
match CheckedAccount::get() {
|
||||
@@ -181,7 +181,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn check_out(_dest: &MultiLocation, what: &MultiAsset, _context: &XcmContext) {
|
||||
fn check_out(_dest: &Location, what: &Asset, _context: &XcmContext) {
|
||||
log::trace!(target: "xcm::currency_adapter", "check_out dest: {:?}, what: {:?}", _dest, what);
|
||||
if let Some(amount) = Matcher::matches_fungible(what) {
|
||||
match CheckedAccount::get() {
|
||||
@@ -194,11 +194,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn deposit_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
_context: Option<&XcmContext>,
|
||||
) -> Result {
|
||||
fn deposit_asset(what: &Asset, who: &Location, _context: Option<&XcmContext>) -> Result {
|
||||
log::trace!(target: "xcm::currency_adapter", "deposit_asset what: {:?}, who: {:?}", what, who);
|
||||
// Check we handle this asset.
|
||||
let amount = Matcher::matches_fungible(&what).ok_or(Error::AssetNotHandled)?;
|
||||
@@ -209,10 +205,10 @@ impl<
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
what: &Asset,
|
||||
who: &Location,
|
||||
_maybe_context: Option<&XcmContext>,
|
||||
) -> result::Result<Assets, XcmError> {
|
||||
) -> result::Result<AssetsInHolding, XcmError> {
|
||||
log::trace!(target: "xcm::currency_adapter", "withdraw_asset what: {:?}, who: {:?}", what, who);
|
||||
// Check we handle this asset.
|
||||
let amount = Matcher::matches_fungible(what).ok_or(Error::AssetNotHandled)?;
|
||||
@@ -224,11 +220,11 @@ impl<
|
||||
}
|
||||
|
||||
fn internal_transfer_asset(
|
||||
asset: &MultiAsset,
|
||||
from: &MultiLocation,
|
||||
to: &MultiLocation,
|
||||
asset: &Asset,
|
||||
from: &Location,
|
||||
to: &Location,
|
||||
_context: &XcmContext,
|
||||
) -> result::Result<Assets, XcmError> {
|
||||
) -> result::Result<AssetsInHolding, XcmError> {
|
||||
log::trace!(target: "xcm::currency_adapter", "internal_transfer_asset asset: {:?}, from: {:?}, to: {:?}", asset, from, to);
|
||||
let amount = Matcher::matches_fungible(asset).ok_or(Error::AssetNotHandled)?;
|
||||
let from =
|
||||
|
||||
@@ -25,27 +25,22 @@ pub trait HandleFee {
|
||||
/// fees.
|
||||
///
|
||||
/// Returns any part of the fee that wasn't consumed.
|
||||
fn handle_fee(fee: MultiAssets, context: Option<&XcmContext>, reason: FeeReason)
|
||||
-> MultiAssets;
|
||||
fn handle_fee(fee: Assets, context: Option<&XcmContext>, reason: FeeReason) -> Assets;
|
||||
}
|
||||
|
||||
// Default `HandleFee` implementation that just burns the fee.
|
||||
impl HandleFee for () {
|
||||
fn handle_fee(_: MultiAssets, _: Option<&XcmContext>, _: FeeReason) -> MultiAssets {
|
||||
MultiAssets::new()
|
||||
fn handle_fee(_: Assets, _: Option<&XcmContext>, _: FeeReason) -> Assets {
|
||||
Assets::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
|
||||
impl HandleFee for Tuple {
|
||||
fn handle_fee(
|
||||
fee: MultiAssets,
|
||||
context: Option<&XcmContext>,
|
||||
reason: FeeReason,
|
||||
) -> MultiAssets {
|
||||
fn handle_fee(fee: Assets, context: Option<&XcmContext>, reason: FeeReason) -> Assets {
|
||||
let mut unconsumed_fee = fee;
|
||||
for_tuples!( #(
|
||||
unconsumed_fee = Tuple::handle_fee(unconsumed_fee, context, reason);
|
||||
unconsumed_fee = Tuple::handle_fee(unconsumed_fee, context, reason.clone());
|
||||
if unconsumed_fee.is_none() {
|
||||
return unconsumed_fee;
|
||||
}
|
||||
@@ -60,15 +55,15 @@ impl HandleFee for Tuple {
|
||||
pub struct XcmFeeManagerFromComponents<WaivedLocations, HandleFee>(
|
||||
PhantomData<(WaivedLocations, HandleFee)>,
|
||||
);
|
||||
impl<WaivedLocations: Contains<MultiLocation>, FeeHandler: HandleFee> FeeManager
|
||||
impl<WaivedLocations: Contains<Location>, FeeHandler: HandleFee> FeeManager
|
||||
for XcmFeeManagerFromComponents<WaivedLocations, FeeHandler>
|
||||
{
|
||||
fn is_waived(origin: Option<&MultiLocation>, _: FeeReason) -> bool {
|
||||
fn is_waived(origin: Option<&Location>, _: FeeReason) -> bool {
|
||||
let Some(loc) = origin else { return false };
|
||||
WaivedLocations::contains(loc)
|
||||
}
|
||||
|
||||
fn handle_fee(fee: MultiAssets, context: Option<&XcmContext>, reason: FeeReason) {
|
||||
fn handle_fee(fee: Assets, context: Option<&XcmContext>, reason: FeeReason) {
|
||||
FeeHandler::handle_fee(fee, context, reason);
|
||||
}
|
||||
}
|
||||
@@ -76,7 +71,7 @@ impl<WaivedLocations: Contains<MultiLocation>, FeeHandler: HandleFee> FeeManager
|
||||
/// Try to deposit the given fee in the specified account.
|
||||
/// Burns the fee in case of a failure.
|
||||
pub fn deposit_or_burn_fee<AssetTransactor: TransactAsset, AccountId: Clone + Into<[u8; 32]>>(
|
||||
fee: MultiAssets,
|
||||
fee: Assets,
|
||||
context: Option<&XcmContext>,
|
||||
receiver: AccountId,
|
||||
) {
|
||||
@@ -109,13 +104,9 @@ impl<
|
||||
ReceiverAccount: Get<AccountId>,
|
||||
> HandleFee for XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount>
|
||||
{
|
||||
fn handle_fee(
|
||||
fee: MultiAssets,
|
||||
context: Option<&XcmContext>,
|
||||
_reason: FeeReason,
|
||||
) -> MultiAssets {
|
||||
fn handle_fee(fee: Assets, context: Option<&XcmContext>, _reason: FeeReason) -> Assets {
|
||||
deposit_or_burn_fee::<AssetTransactor, _>(fee, context, ReceiverAccount::get());
|
||||
|
||||
MultiAssets::new()
|
||||
Assets::new()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,28 +14,26 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Various implementations of `ContainsPair<MultiAsset, MultiLocation>` or
|
||||
//! `Contains<(MultiLocation, Vec<MultiAsset>)>`.
|
||||
//! Various implementations of `ContainsPair<Asset, Location>` or
|
||||
//! `Contains<(Location, Vec<Asset>)>`.
|
||||
|
||||
use frame_support::traits::{Contains, ContainsPair, Get};
|
||||
use sp_std::{marker::PhantomData, vec::Vec};
|
||||
use xcm::latest::{AssetId::Concrete, MultiAsset, MultiAssetFilter, MultiLocation, WildMultiAsset};
|
||||
use xcm::latest::{Asset, AssetFilter, AssetId, Location, WildAsset};
|
||||
|
||||
/// Accepts an asset iff it is a native asset.
|
||||
pub struct NativeAsset;
|
||||
impl ContainsPair<MultiAsset, MultiLocation> for NativeAsset {
|
||||
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
|
||||
impl ContainsPair<Asset, Location> for NativeAsset {
|
||||
fn contains(asset: &Asset, origin: &Location) -> bool {
|
||||
log::trace!(target: "xcm::contains", "NativeAsset asset: {:?}, origin: {:?}", asset, origin);
|
||||
matches!(asset.id, Concrete(ref id) if id == origin)
|
||||
matches!(asset.id, AssetId(ref id) if id == origin)
|
||||
}
|
||||
}
|
||||
|
||||
/// Accepts an asset if it is contained in the given `T`'s `Get` implementation.
|
||||
pub struct Case<T>(PhantomData<T>);
|
||||
impl<T: Get<(MultiAssetFilter, MultiLocation)>> ContainsPair<MultiAsset, MultiLocation>
|
||||
for Case<T>
|
||||
{
|
||||
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
|
||||
impl<T: Get<(AssetFilter, Location)>> ContainsPair<Asset, Location> for Case<T> {
|
||||
fn contains(asset: &Asset, origin: &Location) -> bool {
|
||||
log::trace!(target: "xcm::contains", "Case asset: {:?}, origin: {:?}", asset, origin);
|
||||
let (a, o) = T::get();
|
||||
a.matches(asset) && &o == origin
|
||||
@@ -44,18 +42,18 @@ impl<T: Get<(MultiAssetFilter, MultiLocation)>> ContainsPair<MultiAsset, MultiLo
|
||||
|
||||
/// Accepts a tuple `(location, assets)` if the `location` is contained in the `Contains`
|
||||
/// implementation of the given `Location` and if every asset from `assets` matches at least one of
|
||||
/// the `MultiAssetFilter` instances provided by the `Get` implementation of `AssetFilters`.
|
||||
pub struct LocationWithAssetFilters<Location, AssetFilters>(
|
||||
sp_std::marker::PhantomData<(Location, AssetFilters)>,
|
||||
/// the `AssetFilter` instances provided by the `Get` implementation of `AssetFilters`.
|
||||
pub struct LocationWithAssetFilters<LocationFilter, AssetFilters>(
|
||||
sp_std::marker::PhantomData<(LocationFilter, AssetFilters)>,
|
||||
);
|
||||
impl<Location: Contains<MultiLocation>, AssetFilters: Get<Vec<MultiAssetFilter>>>
|
||||
Contains<(MultiLocation, Vec<MultiAsset>)> for LocationWithAssetFilters<Location, AssetFilters>
|
||||
impl<LocationFilter: Contains<Location>, AssetFilters: Get<Vec<AssetFilter>>>
|
||||
Contains<(Location, Vec<Asset>)> for LocationWithAssetFilters<LocationFilter, AssetFilters>
|
||||
{
|
||||
fn contains((location, assets): &(MultiLocation, Vec<MultiAsset>)) -> bool {
|
||||
fn contains((location, assets): &(Location, Vec<Asset>)) -> bool {
|
||||
log::trace!(target: "xcm::contains", "LocationWithAssetFilters location: {:?}, assets: {:?}", location, assets);
|
||||
|
||||
// `location` must match the `Location` filter.
|
||||
if !Location::contains(location) {
|
||||
if !LocationFilter::contains(location) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -72,12 +70,12 @@ impl<Location: Contains<MultiLocation>, AssetFilters: Get<Vec<MultiAssetFilter>>
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `Get<Vec<MultiAssetFilter>>` which accepts every asset.
|
||||
/// Implementation of `Get<Vec<AssetFilter>>` which accepts every asset.
|
||||
/// (For example, it can be used with `LocationWithAssetFilters`).
|
||||
pub struct AllAssets;
|
||||
impl Get<Vec<MultiAssetFilter>> for AllAssets {
|
||||
fn get() -> Vec<MultiAssetFilter> {
|
||||
sp_std::vec![MultiAssetFilter::Wild(WildMultiAsset::All)]
|
||||
impl Get<Vec<AssetFilter>> for AllAssets {
|
||||
fn get() -> Vec<AssetFilter> {
|
||||
sp_std::vec![AssetFilter::Wild(WildAsset::All)]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,24 +88,24 @@ mod tests {
|
||||
#[test]
|
||||
fn location_with_asset_filters_works() {
|
||||
frame_support::parameter_types! {
|
||||
pub ParaA: MultiLocation = MultiLocation::new(1, X1(Parachain(1001)));
|
||||
pub ParaB: MultiLocation = MultiLocation::new(1, X1(Parachain(1002)));
|
||||
pub ParaC: MultiLocation = MultiLocation::new(1, X1(Parachain(1003)));
|
||||
pub ParaA: Location = Location::new(1, [Parachain(1001)]);
|
||||
pub ParaB: Location = Location::new(1, [Parachain(1002)]);
|
||||
pub ParaC: Location = Location::new(1, [Parachain(1003)]);
|
||||
|
||||
pub AssetXLocation: MultiLocation = MultiLocation::new(1, X1(GeneralIndex(1111)));
|
||||
pub AssetYLocation: MultiLocation = MultiLocation::new(1, X1(GeneralIndex(2222)));
|
||||
pub AssetZLocation: MultiLocation = MultiLocation::new(1, X1(GeneralIndex(3333)));
|
||||
pub AssetXLocation: Location = Location::new(1, [GeneralIndex(1111)]);
|
||||
pub AssetYLocation: Location = Location::new(1, [GeneralIndex(2222)]);
|
||||
pub AssetZLocation: Location = Location::new(1, [GeneralIndex(3333)]);
|
||||
|
||||
pub OnlyAssetXOrAssetY: sp_std::vec::Vec<MultiAssetFilter> = sp_std::vec![
|
||||
Wild(AllOf { fun: WildFungible, id: Concrete(AssetXLocation::get()) }),
|
||||
Wild(AllOf { fun: WildFungible, id: Concrete(AssetYLocation::get()) }),
|
||||
pub OnlyAssetXOrAssetY: sp_std::vec::Vec<AssetFilter> = sp_std::vec![
|
||||
Wild(AllOf { fun: WildFungible, id: AssetId(AssetXLocation::get()) }),
|
||||
Wild(AllOf { fun: WildFungible, id: AssetId(AssetYLocation::get()) }),
|
||||
];
|
||||
pub OnlyAssetZ: sp_std::vec::Vec<MultiAssetFilter> = sp_std::vec![
|
||||
Wild(AllOf { fun: WildFungible, id: Concrete(AssetZLocation::get()) })
|
||||
pub OnlyAssetZ: sp_std::vec::Vec<AssetFilter> = sp_std::vec![
|
||||
Wild(AllOf { fun: WildFungible, id: AssetId(AssetZLocation::get()) })
|
||||
];
|
||||
}
|
||||
|
||||
let test_data: Vec<(MultiLocation, Vec<MultiAsset>, bool)> = vec![
|
||||
let test_data: Vec<(Location, Vec<Asset>, bool)> = vec![
|
||||
(ParaA::get(), vec![(AssetXLocation::get(), 1).into()], true),
|
||||
(ParaA::get(), vec![(AssetYLocation::get(), 1).into()], true),
|
||||
(ParaA::get(), vec![(AssetZLocation::get(), 1).into()], false),
|
||||
@@ -202,7 +200,7 @@ mod tests {
|
||||
|
||||
for (location, assets, expected_result) in test_data {
|
||||
assert_eq!(
|
||||
Filter::contains(&(location, assets.clone())),
|
||||
Filter::contains(&(location.clone(), assets.clone())),
|
||||
expected_result,
|
||||
"expected_result: {expected_result} not matched for (location, assets): ({:?}, {:?})!", location, assets,
|
||||
)
|
||||
|
||||
@@ -25,7 +25,10 @@ use frame_support::traits::{
|
||||
};
|
||||
use sp_std::{marker::PhantomData, prelude::*, result};
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_executor::traits::{ConvertLocation, Error as MatchError, MatchesFungible, TransactAsset};
|
||||
use xcm_executor::{
|
||||
traits::{ConvertLocation, Error as MatchError, MatchesFungible, TransactAsset},
|
||||
AssetsInHolding,
|
||||
};
|
||||
|
||||
/// [`TransactAsset`] implementation that allows the use of a [`fungible`] implementation for
|
||||
/// handling an asset in the XCM executor.
|
||||
@@ -41,11 +44,11 @@ impl<
|
||||
> TransactAsset for FungibleTransferAdapter<Fungible, Matcher, AccountIdConverter, AccountId>
|
||||
{
|
||||
fn internal_transfer_asset(
|
||||
what: &MultiAsset,
|
||||
from: &MultiLocation,
|
||||
to: &MultiLocation,
|
||||
what: &Asset,
|
||||
from: &Location,
|
||||
to: &Location,
|
||||
_context: &XcmContext,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<AssetsInHolding, XcmError> {
|
||||
log::trace!(
|
||||
target: "xcm::fungible_adapter",
|
||||
"internal_transfer_asset what: {:?}, from: {:?}, to: {:?}",
|
||||
@@ -111,11 +114,7 @@ impl<
|
||||
> TransactAsset
|
||||
for FungibleMutateAdapter<Fungible, Matcher, AccountIdConverter, AccountId, CheckingAccount>
|
||||
{
|
||||
fn can_check_in(
|
||||
_origin: &MultiLocation,
|
||||
what: &MultiAsset,
|
||||
_context: &XcmContext,
|
||||
) -> XcmResult {
|
||||
fn can_check_in(_origin: &Location, what: &Asset, _context: &XcmContext) -> XcmResult {
|
||||
log::trace!(
|
||||
target: "xcm::fungible_adapter",
|
||||
"can_check_in origin: {:?}, what: {:?}",
|
||||
@@ -132,7 +131,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn check_in(_origin: &MultiLocation, what: &MultiAsset, _context: &XcmContext) {
|
||||
fn check_in(_origin: &Location, what: &Asset, _context: &XcmContext) {
|
||||
log::trace!(
|
||||
target: "xcm::fungible_adapter",
|
||||
"check_in origin: {:?}, what: {:?}",
|
||||
@@ -149,7 +148,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn can_check_out(_dest: &MultiLocation, what: &MultiAsset, _context: &XcmContext) -> XcmResult {
|
||||
fn can_check_out(_dest: &Location, what: &Asset, _context: &XcmContext) -> XcmResult {
|
||||
log::trace!(
|
||||
target: "xcm::fungible_adapter",
|
||||
"check_out dest: {:?}, what: {:?}",
|
||||
@@ -166,7 +165,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn check_out(_dest: &MultiLocation, what: &MultiAsset, _context: &XcmContext) {
|
||||
fn check_out(_dest: &Location, what: &Asset, _context: &XcmContext) {
|
||||
log::trace!(
|
||||
target: "xcm::fungible_adapter",
|
||||
"check_out dest: {:?}, what: {:?}",
|
||||
@@ -184,11 +183,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn deposit_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
_context: Option<&XcmContext>,
|
||||
) -> XcmResult {
|
||||
fn deposit_asset(what: &Asset, who: &Location, _context: Option<&XcmContext>) -> XcmResult {
|
||||
log::trace!(
|
||||
target: "xcm::fungible_adapter",
|
||||
"deposit_asset what: {:?}, who: {:?}",
|
||||
@@ -203,10 +198,10 @@ impl<
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
what: &Asset,
|
||||
who: &Location,
|
||||
_context: Option<&XcmContext>,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<AssetsInHolding, XcmError> {
|
||||
log::trace!(
|
||||
target: "xcm::fungible_adapter",
|
||||
"deposit_asset what: {:?}, who: {:?}",
|
||||
@@ -236,7 +231,7 @@ impl<
|
||||
> TransactAsset
|
||||
for FungibleAdapter<Fungible, Matcher, AccountIdConverter, AccountId, CheckingAccount>
|
||||
{
|
||||
fn can_check_in(origin: &MultiLocation, what: &MultiAsset, context: &XcmContext) -> XcmResult {
|
||||
fn can_check_in(origin: &Location, what: &Asset, context: &XcmContext) -> XcmResult {
|
||||
FungibleMutateAdapter::<
|
||||
Fungible,
|
||||
Matcher,
|
||||
@@ -246,7 +241,7 @@ impl<
|
||||
>::can_check_in(origin, what, context)
|
||||
}
|
||||
|
||||
fn check_in(origin: &MultiLocation, what: &MultiAsset, context: &XcmContext) {
|
||||
fn check_in(origin: &Location, what: &Asset, context: &XcmContext) {
|
||||
FungibleMutateAdapter::<
|
||||
Fungible,
|
||||
Matcher,
|
||||
@@ -256,7 +251,7 @@ impl<
|
||||
>::check_in(origin, what, context)
|
||||
}
|
||||
|
||||
fn can_check_out(dest: &MultiLocation, what: &MultiAsset, context: &XcmContext) -> XcmResult {
|
||||
fn can_check_out(dest: &Location, what: &Asset, context: &XcmContext) -> XcmResult {
|
||||
FungibleMutateAdapter::<
|
||||
Fungible,
|
||||
Matcher,
|
||||
@@ -266,7 +261,7 @@ impl<
|
||||
>::can_check_out(dest, what, context)
|
||||
}
|
||||
|
||||
fn check_out(dest: &MultiLocation, what: &MultiAsset, context: &XcmContext) {
|
||||
fn check_out(dest: &Location, what: &Asset, context: &XcmContext) {
|
||||
FungibleMutateAdapter::<
|
||||
Fungible,
|
||||
Matcher,
|
||||
@@ -276,11 +271,7 @@ impl<
|
||||
>::check_out(dest, what, context)
|
||||
}
|
||||
|
||||
fn deposit_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
context: Option<&XcmContext>,
|
||||
) -> XcmResult {
|
||||
fn deposit_asset(what: &Asset, who: &Location, context: Option<&XcmContext>) -> XcmResult {
|
||||
FungibleMutateAdapter::<
|
||||
Fungible,
|
||||
Matcher,
|
||||
@@ -291,10 +282,10 @@ impl<
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
what: &Asset,
|
||||
who: &Location,
|
||||
maybe_context: Option<&XcmContext>,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<AssetsInHolding, XcmError> {
|
||||
FungibleMutateAdapter::<
|
||||
Fungible,
|
||||
Matcher,
|
||||
@@ -305,11 +296,11 @@ impl<
|
||||
}
|
||||
|
||||
fn internal_transfer_asset(
|
||||
what: &MultiAsset,
|
||||
from: &MultiLocation,
|
||||
to: &MultiLocation,
|
||||
what: &Asset,
|
||||
from: &Location,
|
||||
to: &Location,
|
||||
context: &XcmContext,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<AssetsInHolding, XcmError> {
|
||||
FungibleTransferAdapter::<Fungible, Matcher, AccountIdConverter, AccountId>::internal_transfer_asset(
|
||||
what, from, to, context
|
||||
)
|
||||
|
||||
@@ -38,11 +38,11 @@ impl<
|
||||
> TransactAsset for FungiblesTransferAdapter<Assets, Matcher, AccountIdConverter, AccountId>
|
||||
{
|
||||
fn internal_transfer_asset(
|
||||
what: &MultiAsset,
|
||||
from: &MultiLocation,
|
||||
to: &MultiLocation,
|
||||
what: &Asset,
|
||||
from: &Location,
|
||||
to: &Location,
|
||||
_context: &XcmContext,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<xcm_executor::AssetsInHolding, XcmError> {
|
||||
log::trace!(
|
||||
target: "xcm::fungibles_adapter",
|
||||
"internal_transfer_asset what: {:?}, from: {:?}, to: {:?}",
|
||||
@@ -198,11 +198,7 @@ impl<
|
||||
CheckingAccount,
|
||||
>
|
||||
{
|
||||
fn can_check_in(
|
||||
_origin: &MultiLocation,
|
||||
what: &MultiAsset,
|
||||
_context: &XcmContext,
|
||||
) -> XcmResult {
|
||||
fn can_check_in(_origin: &Location, what: &Asset, _context: &XcmContext) -> XcmResult {
|
||||
log::trace!(
|
||||
target: "xcm::fungibles_adapter",
|
||||
"can_check_in origin: {:?}, what: {:?}",
|
||||
@@ -219,7 +215,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn check_in(_origin: &MultiLocation, what: &MultiAsset, _context: &XcmContext) {
|
||||
fn check_in(_origin: &Location, what: &Asset, _context: &XcmContext) {
|
||||
log::trace!(
|
||||
target: "xcm::fungibles_adapter",
|
||||
"check_in origin: {:?}, what: {:?}",
|
||||
@@ -236,11 +232,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn can_check_out(
|
||||
_origin: &MultiLocation,
|
||||
what: &MultiAsset,
|
||||
_context: &XcmContext,
|
||||
) -> XcmResult {
|
||||
fn can_check_out(_origin: &Location, what: &Asset, _context: &XcmContext) -> XcmResult {
|
||||
log::trace!(
|
||||
target: "xcm::fungibles_adapter",
|
||||
"can_check_in origin: {:?}, what: {:?}",
|
||||
@@ -257,7 +249,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn check_out(_dest: &MultiLocation, what: &MultiAsset, _context: &XcmContext) {
|
||||
fn check_out(_dest: &Location, what: &Asset, _context: &XcmContext) {
|
||||
log::trace!(
|
||||
target: "xcm::fungibles_adapter",
|
||||
"check_out dest: {:?}, what: {:?}",
|
||||
@@ -274,11 +266,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn deposit_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
_context: Option<&XcmContext>,
|
||||
) -> XcmResult {
|
||||
fn deposit_asset(what: &Asset, who: &Location, _context: Option<&XcmContext>) -> XcmResult {
|
||||
log::trace!(
|
||||
target: "xcm::fungibles_adapter",
|
||||
"deposit_asset what: {:?}, who: {:?}",
|
||||
@@ -294,10 +282,10 @@ impl<
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
what: &Asset,
|
||||
who: &Location,
|
||||
_maybe_context: Option<&XcmContext>,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<xcm_executor::AssetsInHolding, XcmError> {
|
||||
log::trace!(
|
||||
target: "xcm::fungibles_adapter",
|
||||
"withdraw_asset what: {:?}, who: {:?}",
|
||||
@@ -331,7 +319,7 @@ impl<
|
||||
> TransactAsset
|
||||
for FungiblesAdapter<Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount>
|
||||
{
|
||||
fn can_check_in(origin: &MultiLocation, what: &MultiAsset, context: &XcmContext) -> XcmResult {
|
||||
fn can_check_in(origin: &Location, what: &Asset, context: &XcmContext) -> XcmResult {
|
||||
FungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -342,7 +330,7 @@ impl<
|
||||
>::can_check_in(origin, what, context)
|
||||
}
|
||||
|
||||
fn check_in(origin: &MultiLocation, what: &MultiAsset, context: &XcmContext) {
|
||||
fn check_in(origin: &Location, what: &Asset, context: &XcmContext) {
|
||||
FungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -353,7 +341,7 @@ impl<
|
||||
>::check_in(origin, what, context)
|
||||
}
|
||||
|
||||
fn can_check_out(dest: &MultiLocation, what: &MultiAsset, context: &XcmContext) -> XcmResult {
|
||||
fn can_check_out(dest: &Location, what: &Asset, context: &XcmContext) -> XcmResult {
|
||||
FungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -364,7 +352,7 @@ impl<
|
||||
>::can_check_out(dest, what, context)
|
||||
}
|
||||
|
||||
fn check_out(dest: &MultiLocation, what: &MultiAsset, context: &XcmContext) {
|
||||
fn check_out(dest: &Location, what: &Asset, context: &XcmContext) {
|
||||
FungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -375,11 +363,7 @@ impl<
|
||||
>::check_out(dest, what, context)
|
||||
}
|
||||
|
||||
fn deposit_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
context: Option<&XcmContext>,
|
||||
) -> XcmResult {
|
||||
fn deposit_asset(what: &Asset, who: &Location, context: Option<&XcmContext>) -> XcmResult {
|
||||
FungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -391,10 +375,10 @@ impl<
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
what: &Asset,
|
||||
who: &Location,
|
||||
maybe_context: Option<&XcmContext>,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<xcm_executor::AssetsInHolding, XcmError> {
|
||||
FungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -406,11 +390,11 @@ impl<
|
||||
}
|
||||
|
||||
fn internal_transfer_asset(
|
||||
what: &MultiAsset,
|
||||
from: &MultiLocation,
|
||||
to: &MultiLocation,
|
||||
what: &Asset,
|
||||
from: &Location,
|
||||
to: &Location,
|
||||
context: &XcmContext,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<xcm_executor::AssetsInHolding, XcmError> {
|
||||
FungiblesTransferAdapter::<Assets, Matcher, AccountIdConverter, AccountId>::internal_transfer_asset(
|
||||
what, from, to, context
|
||||
)
|
||||
|
||||
@@ -47,11 +47,11 @@ pub use origin_conversion::{
|
||||
};
|
||||
|
||||
mod asset_conversion;
|
||||
pub use asset_conversion::{
|
||||
AsPrefixedGeneralIndex, ConvertedAbstractId, ConvertedConcreteId, MatchedConvertedConcreteId,
|
||||
};
|
||||
#[allow(deprecated)]
|
||||
pub use asset_conversion::{ConvertedAbstractAssetId, ConvertedConcreteAssetId};
|
||||
pub use asset_conversion::ConvertedConcreteAssetId;
|
||||
pub use asset_conversion::{
|
||||
AsPrefixedGeneralIndex, ConvertedConcreteId, MatchedConvertedConcreteId, V4V3LocationConverter,
|
||||
};
|
||||
|
||||
mod barriers;
|
||||
pub use barriers::{
|
||||
@@ -96,7 +96,7 @@ mod matches_location;
|
||||
pub use matches_location::{StartsWith, StartsWithExplicitGlobalConsensus};
|
||||
|
||||
mod matches_token;
|
||||
pub use matches_token::{IsAbstract, IsConcrete};
|
||||
pub use matches_token::IsConcrete;
|
||||
|
||||
mod matcher;
|
||||
pub use matcher::{CreateMatcher, MatchXcm, Matcher};
|
||||
|
||||
@@ -27,12 +27,12 @@ use xcm_executor::traits::ConvertLocation;
|
||||
pub trait DescribeLocation {
|
||||
/// Create a description of the given `location` if possible. No two locations should have the
|
||||
/// same descriptor.
|
||||
fn describe_location(location: &MultiLocation) -> Option<Vec<u8>>;
|
||||
fn describe_location(location: &Location) -> Option<Vec<u8>>;
|
||||
}
|
||||
|
||||
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||
impl DescribeLocation for Tuple {
|
||||
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
|
||||
fn describe_location(l: &Location) -> Option<Vec<u8>> {
|
||||
for_tuples!( #(
|
||||
match Tuple::describe_location(l) {
|
||||
Some(result) => return Some(result),
|
||||
@@ -45,9 +45,9 @@ impl DescribeLocation for Tuple {
|
||||
|
||||
pub struct DescribeTerminus;
|
||||
impl DescribeLocation for DescribeTerminus {
|
||||
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
|
||||
match (l.parents, &l.interior) {
|
||||
(0, Here) => Some(Vec::new()),
|
||||
fn describe_location(l: &Location) -> Option<Vec<u8>> {
|
||||
match l.unpack() {
|
||||
(0, []) => Some(Vec::new()),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
@@ -55,10 +55,9 @@ impl DescribeLocation for DescribeTerminus {
|
||||
|
||||
pub struct DescribePalletTerminal;
|
||||
impl DescribeLocation for DescribePalletTerminal {
|
||||
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
|
||||
match (l.parents, &l.interior) {
|
||||
(0, X1(PalletInstance(i))) =>
|
||||
Some((b"Pallet", Compact::<u32>::from(*i as u32)).encode()),
|
||||
fn describe_location(l: &Location) -> Option<Vec<u8>> {
|
||||
match l.unpack() {
|
||||
(0, [PalletInstance(i)]) => Some((b"Pallet", Compact::<u32>::from(*i as u32)).encode()),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
@@ -66,9 +65,9 @@ impl DescribeLocation for DescribePalletTerminal {
|
||||
|
||||
pub struct DescribeAccountId32Terminal;
|
||||
impl DescribeLocation for DescribeAccountId32Terminal {
|
||||
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
|
||||
match (l.parents, &l.interior) {
|
||||
(0, X1(AccountId32 { id, .. })) => Some((b"AccountId32", id).encode()),
|
||||
fn describe_location(l: &Location) -> Option<Vec<u8>> {
|
||||
match l.unpack() {
|
||||
(0, [AccountId32 { id, .. }]) => Some((b"AccountId32", id).encode()),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
@@ -76,9 +75,9 @@ impl DescribeLocation for DescribeAccountId32Terminal {
|
||||
|
||||
pub struct DescribeAccountKey20Terminal;
|
||||
impl DescribeLocation for DescribeAccountKey20Terminal {
|
||||
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
|
||||
match (l.parents, &l.interior) {
|
||||
(0, X1(AccountKey20 { key, .. })) => Some((b"AccountKey20", key).encode()),
|
||||
fn describe_location(l: &Location) -> Option<Vec<u8>> {
|
||||
match l.unpack() {
|
||||
(0, [AccountKey20 { key, .. }]) => Some((b"AccountKey20", key).encode()),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
@@ -89,9 +88,9 @@ impl DescribeLocation for DescribeAccountKey20Terminal {
|
||||
pub struct DescribeTreasuryVoiceTerminal;
|
||||
|
||||
impl DescribeLocation for DescribeTreasuryVoiceTerminal {
|
||||
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
|
||||
match (l.parents, &l.interior) {
|
||||
(0, X1(Plurality { id: BodyId::Treasury, part: BodyPart::Voice })) =>
|
||||
fn describe_location(location: &Location) -> Option<Vec<u8>> {
|
||||
match location.unpack() {
|
||||
(0, [Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]) =>
|
||||
Some((b"Treasury", b"Voice").encode()),
|
||||
_ => None,
|
||||
}
|
||||
@@ -102,9 +101,9 @@ pub type DescribeAccountIdTerminal = (DescribeAccountId32Terminal, DescribeAccou
|
||||
|
||||
pub struct DescribeBodyTerminal;
|
||||
impl DescribeLocation for DescribeBodyTerminal {
|
||||
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
|
||||
match (l.parents, &l.interior) {
|
||||
(0, X1(Plurality { id, part })) => Some((b"Body", id, part).encode()),
|
||||
fn describe_location(l: &Location) -> Option<Vec<u8>> {
|
||||
match l.unpack() {
|
||||
(0, [Plurality { id, part }]) => Some((b"Body", id, part).encode()),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
@@ -121,20 +120,21 @@ pub type DescribeAllTerminal = (
|
||||
|
||||
pub struct DescribeFamily<DescribeInterior>(PhantomData<DescribeInterior>);
|
||||
impl<Suffix: DescribeLocation> DescribeLocation for DescribeFamily<Suffix> {
|
||||
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
|
||||
match (l.parents, l.interior.first()) {
|
||||
fn describe_location(l: &Location) -> Option<Vec<u8>> {
|
||||
match (l.parent_count(), l.first_interior()) {
|
||||
(0, Some(Parachain(index))) => {
|
||||
let tail = l.interior.split_first().0;
|
||||
let tail = l.clone().split_first_interior().0;
|
||||
let interior = Suffix::describe_location(&tail.into())?;
|
||||
Some((b"ChildChain", Compact::<u32>::from(*index), interior).encode())
|
||||
},
|
||||
(1, Some(Parachain(index))) => {
|
||||
let tail = l.interior.split_first().0;
|
||||
let interior = Suffix::describe_location(&tail.into())?;
|
||||
let tail_junctions = l.interior().clone().split_first().0;
|
||||
let tail = Location::new(0, tail_junctions);
|
||||
let interior = Suffix::describe_location(&tail)?;
|
||||
Some((b"SiblingChain", Compact::<u32>::from(*index), interior).encode())
|
||||
},
|
||||
(1, _) => {
|
||||
let tail = l.interior.into();
|
||||
let tail = l.interior().clone().into();
|
||||
let interior = Suffix::describe_location(&tail)?;
|
||||
Some((b"ParentChain", interior).encode())
|
||||
},
|
||||
@@ -147,7 +147,7 @@ pub struct HashedDescription<AccountId, Describe>(PhantomData<(AccountId, Descri
|
||||
impl<AccountId: From<[u8; 32]> + Clone, Describe: DescribeLocation> ConvertLocation<AccountId>
|
||||
for HashedDescription<AccountId, Describe>
|
||||
{
|
||||
fn convert_location(value: &MultiLocation) -> Option<AccountId> {
|
||||
fn convert_location(value: &Location) -> Option<AccountId> {
|
||||
Some(blake2_256(&Describe::describe_location(value)?).into())
|
||||
}
|
||||
}
|
||||
@@ -156,34 +156,26 @@ impl<AccountId: From<[u8; 32]> + Clone, Describe: DescribeLocation> ConvertLocat
|
||||
/// are recommended to use the more extensible `HashedDescription` type.
|
||||
pub struct LegacyDescribeForeignChainAccount;
|
||||
impl DescribeLocation for LegacyDescribeForeignChainAccount {
|
||||
fn describe_location(location: &MultiLocation) -> Option<Vec<u8>> {
|
||||
Some(match location {
|
||||
fn describe_location(location: &Location) -> Option<Vec<u8>> {
|
||||
Some(match location.unpack() {
|
||||
// Used on the relay chain for sending paras that use 32 byte accounts
|
||||
MultiLocation {
|
||||
parents: 0,
|
||||
interior: X2(Parachain(para_id), AccountId32 { id, .. }),
|
||||
} => LegacyDescribeForeignChainAccount::from_para_32(para_id, id, 0),
|
||||
(0, [Parachain(para_id), AccountId32 { id, .. }]) =>
|
||||
LegacyDescribeForeignChainAccount::from_para_32(para_id, id, 0),
|
||||
|
||||
// Used on the relay chain for sending paras that use 20 byte accounts
|
||||
MultiLocation {
|
||||
parents: 0,
|
||||
interior: X2(Parachain(para_id), AccountKey20 { key, .. }),
|
||||
} => LegacyDescribeForeignChainAccount::from_para_20(para_id, key, 0),
|
||||
(0, [Parachain(para_id), AccountKey20 { key, .. }]) =>
|
||||
LegacyDescribeForeignChainAccount::from_para_20(para_id, key, 0),
|
||||
|
||||
// Used on para-chain for sending paras that use 32 byte accounts
|
||||
MultiLocation {
|
||||
parents: 1,
|
||||
interior: X2(Parachain(para_id), AccountId32 { id, .. }),
|
||||
} => LegacyDescribeForeignChainAccount::from_para_32(para_id, id, 1),
|
||||
(1, [Parachain(para_id), AccountId32 { id, .. }]) =>
|
||||
LegacyDescribeForeignChainAccount::from_para_32(para_id, id, 1),
|
||||
|
||||
// Used on para-chain for sending paras that use 20 byte accounts
|
||||
MultiLocation {
|
||||
parents: 1,
|
||||
interior: X2(Parachain(para_id), AccountKey20 { key, .. }),
|
||||
} => LegacyDescribeForeignChainAccount::from_para_20(para_id, key, 1),
|
||||
(1, [Parachain(para_id), AccountKey20 { key, .. }]) =>
|
||||
LegacyDescribeForeignChainAccount::from_para_20(para_id, key, 1),
|
||||
|
||||
// Used on para-chain for sending from the relay chain
|
||||
MultiLocation { parents: 1, interior: X1(AccountId32 { id, .. }) } =>
|
||||
(1, [AccountId32 { id, .. }]) =>
|
||||
LegacyDescribeForeignChainAccount::from_relay_32(id, 1),
|
||||
|
||||
// No other conversions provided
|
||||
@@ -278,16 +270,16 @@ pub struct Account32Hash<Network, AccountId>(PhantomData<(Network, AccountId)>);
|
||||
impl<Network: Get<Option<NetworkId>>, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone>
|
||||
ConvertLocation<AccountId> for Account32Hash<Network, AccountId>
|
||||
{
|
||||
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
|
||||
fn convert_location(location: &Location) -> Option<AccountId> {
|
||||
Some(("multiloc", location).using_encoded(blake2_256).into())
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`MultiLocation`] consisting of a single `Parent` [`Junction`] will be converted to the
|
||||
/// A [`Location`] consisting of a single `Parent` [`Junction`] will be converted to the
|
||||
/// parent `AccountId`.
|
||||
pub struct ParentIsPreset<AccountId>(PhantomData<AccountId>);
|
||||
impl<AccountId: Decode + Eq + Clone> ConvertLocation<AccountId> for ParentIsPreset<AccountId> {
|
||||
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
|
||||
fn convert_location(location: &Location) -> Option<AccountId> {
|
||||
if location.contains_parents_only(1) {
|
||||
Some(
|
||||
b"Parent"
|
||||
@@ -304,10 +296,9 @@ pub struct ChildParachainConvertsVia<ParaId, AccountId>(PhantomData<(ParaId, Acc
|
||||
impl<ParaId: From<u32> + Into<u32> + AccountIdConversion<AccountId>, AccountId: Clone>
|
||||
ConvertLocation<AccountId> for ChildParachainConvertsVia<ParaId, AccountId>
|
||||
{
|
||||
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
|
||||
match location {
|
||||
MultiLocation { parents: 0, interior: X1(Parachain(id)) } =>
|
||||
Some(ParaId::from(*id).into_account_truncating()),
|
||||
fn convert_location(location: &Location) -> Option<AccountId> {
|
||||
match location.unpack() {
|
||||
(0, [Parachain(id)]) => Some(ParaId::from(*id).into_account_truncating()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -317,10 +308,9 @@ pub struct SiblingParachainConvertsVia<ParaId, AccountId>(PhantomData<(ParaId, A
|
||||
impl<ParaId: From<u32> + Into<u32> + AccountIdConversion<AccountId>, AccountId: Clone>
|
||||
ConvertLocation<AccountId> for SiblingParachainConvertsVia<ParaId, AccountId>
|
||||
{
|
||||
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
|
||||
match location {
|
||||
MultiLocation { parents: 1, interior: X1(Parachain(id)) } =>
|
||||
Some(ParaId::from(*id).into_account_truncating()),
|
||||
fn convert_location(location: &Location) -> Option<AccountId> {
|
||||
match location.unpack() {
|
||||
(1, [Parachain(id)]) => Some(ParaId::from(*id).into_account_truncating()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -331,15 +321,13 @@ pub struct AccountId32Aliases<Network, AccountId>(PhantomData<(Network, AccountI
|
||||
impl<Network: Get<Option<NetworkId>>, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone>
|
||||
ConvertLocation<AccountId> for AccountId32Aliases<Network, AccountId>
|
||||
{
|
||||
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
|
||||
let id = match *location {
|
||||
MultiLocation { parents: 0, interior: X1(AccountId32 { id, network: None }) } => id,
|
||||
MultiLocation { parents: 0, interior: X1(AccountId32 { id, network }) }
|
||||
if network == Network::get() =>
|
||||
id,
|
||||
fn convert_location(location: &Location) -> Option<AccountId> {
|
||||
let id = match location.unpack() {
|
||||
(0, [AccountId32 { id, network: None }]) => id,
|
||||
(0, [AccountId32 { id, network }]) if *network == Network::get() => id,
|
||||
_ => return None,
|
||||
};
|
||||
Some(id.into())
|
||||
Some((*id).into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,25 +339,23 @@ pub struct LocalTreasuryVoiceConvertsVia<TreasuryAccount, AccountId>(
|
||||
impl<TreasuryAccount: Get<AccountId>, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone>
|
||||
ConvertLocation<AccountId> for LocalTreasuryVoiceConvertsVia<TreasuryAccount, AccountId>
|
||||
{
|
||||
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
|
||||
match *location {
|
||||
MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(Plurality { id: BodyId::Treasury, part: BodyPart::Voice }),
|
||||
} => Some((TreasuryAccount::get().into() as [u8; 32]).into()),
|
||||
fn convert_location(location: &Location) -> Option<AccountId> {
|
||||
match location.unpack() {
|
||||
(0, [Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]) =>
|
||||
Some((TreasuryAccount::get().into() as [u8; 32]).into()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Conversion implementation which converts from a `[u8; 32]`-based `AccountId` into a
|
||||
/// `MultiLocation` consisting solely of a `AccountId32` junction with a fixed value for its
|
||||
/// `Location` consisting solely of a `AccountId32` junction with a fixed value for its
|
||||
/// network (provided by `Network`) and the `AccountId`'s `[u8; 32]` datum for the `id`.
|
||||
pub struct AliasesIntoAccountId32<Network, AccountId>(PhantomData<(Network, AccountId)>);
|
||||
impl<'a, Network: Get<Option<NetworkId>>, AccountId: Clone + Into<[u8; 32]> + Clone>
|
||||
TryConvert<&'a AccountId, MultiLocation> for AliasesIntoAccountId32<Network, AccountId>
|
||||
TryConvert<&'a AccountId, Location> for AliasesIntoAccountId32<Network, AccountId>
|
||||
{
|
||||
fn try_convert(who: &AccountId) -> Result<MultiLocation, &AccountId> {
|
||||
fn try_convert(who: &AccountId) -> Result<Location, &AccountId> {
|
||||
Ok(AccountId32 { network: Network::get(), id: who.clone().into() }.into())
|
||||
}
|
||||
}
|
||||
@@ -378,15 +364,13 @@ pub struct AccountKey20Aliases<Network, AccountId>(PhantomData<(Network, Account
|
||||
impl<Network: Get<Option<NetworkId>>, AccountId: From<[u8; 20]> + Into<[u8; 20]> + Clone>
|
||||
ConvertLocation<AccountId> for AccountKey20Aliases<Network, AccountId>
|
||||
{
|
||||
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
|
||||
let key = match *location {
|
||||
MultiLocation { parents: 0, interior: X1(AccountKey20 { key, network: None }) } => key,
|
||||
MultiLocation { parents: 0, interior: X1(AccountKey20 { key, network }) }
|
||||
if network == Network::get() =>
|
||||
key,
|
||||
fn convert_location(location: &Location) -> Option<AccountId> {
|
||||
let key = match location.unpack() {
|
||||
(0, [AccountKey20 { key, network: None }]) => key,
|
||||
(0, [AccountKey20 { key, network }]) if *network == Network::get() => key,
|
||||
_ => return None,
|
||||
};
|
||||
Some(key.into())
|
||||
Some((*key).into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,10 +386,10 @@ impl<Network: Get<Option<NetworkId>>, AccountId: From<[u8; 20]> + Into<[u8; 20]>
|
||||
pub struct GlobalConsensusConvertsFor<UniversalLocation, AccountId>(
|
||||
PhantomData<(UniversalLocation, AccountId)>,
|
||||
);
|
||||
impl<UniversalLocation: Get<InteriorMultiLocation>, AccountId: From<[u8; 32]> + Clone>
|
||||
impl<UniversalLocation: Get<InteriorLocation>, AccountId: From<[u8; 32]> + Clone>
|
||||
ConvertLocation<AccountId> for GlobalConsensusConvertsFor<UniversalLocation, AccountId>
|
||||
{
|
||||
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
|
||||
fn convert_location(location: &Location) -> Option<AccountId> {
|
||||
let universal_source = UniversalLocation::get();
|
||||
log::trace!(
|
||||
target: "xcm::location_conversion",
|
||||
@@ -413,7 +397,7 @@ impl<UniversalLocation: Get<InteriorMultiLocation>, AccountId: From<[u8; 32]> +
|
||||
universal_source, location,
|
||||
);
|
||||
let (remote_network, remote_location) =
|
||||
ensure_is_remote(universal_source, *location).ok()?;
|
||||
ensure_is_remote(universal_source, location.clone()).ok()?;
|
||||
|
||||
match remote_location {
|
||||
Here => Some(AccountId::from(Self::from_params(&remote_network))),
|
||||
@@ -445,21 +429,21 @@ impl<UniversalLocation, AccountId> GlobalConsensusConvertsFor<UniversalLocation,
|
||||
pub struct GlobalConsensusParachainConvertsFor<UniversalLocation, AccountId>(
|
||||
PhantomData<(UniversalLocation, AccountId)>,
|
||||
);
|
||||
impl<UniversalLocation: Get<InteriorMultiLocation>, AccountId: From<[u8; 32]> + Clone>
|
||||
impl<UniversalLocation: Get<InteriorLocation>, AccountId: From<[u8; 32]> + Clone>
|
||||
ConvertLocation<AccountId> for GlobalConsensusParachainConvertsFor<UniversalLocation, AccountId>
|
||||
{
|
||||
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
|
||||
fn convert_location(location: &Location) -> Option<AccountId> {
|
||||
let universal_source = UniversalLocation::get();
|
||||
log::trace!(
|
||||
target: "xcm::location_conversion",
|
||||
"GlobalConsensusParachainConvertsFor universal_source: {:?}, location: {:?}",
|
||||
universal_source, location,
|
||||
);
|
||||
let devolved = ensure_is_remote(universal_source, *location).ok()?;
|
||||
let devolved = ensure_is_remote(universal_source, location.clone()).ok()?;
|
||||
let (remote_network, remote_location) = devolved;
|
||||
|
||||
match remote_location {
|
||||
X1(Parachain(remote_network_para_id)) =>
|
||||
match remote_location.as_slice() {
|
||||
[Parachain(remote_network_para_id)] =>
|
||||
Some(AccountId::from(Self::from_params(&remote_network, &remote_network_para_id))),
|
||||
_ => None,
|
||||
}
|
||||
@@ -509,12 +493,12 @@ mod tests {
|
||||
#[test]
|
||||
fn inverter_works_in_tree() {
|
||||
parameter_types! {
|
||||
pub UniversalLocation: InteriorMultiLocation = X3(Parachain(1), account20(), account20());
|
||||
pub UniversalLocation: InteriorLocation = [Parachain(1), account20(), account20()].into();
|
||||
}
|
||||
|
||||
let input = MultiLocation::new(3, X2(Parachain(2), account32()));
|
||||
let input = Location::new(3, [Parachain(2), account32()]);
|
||||
let inverted = UniversalLocation::get().invert_target(&input).unwrap();
|
||||
assert_eq!(inverted, MultiLocation::new(2, X3(Parachain(1), account20(), account20())));
|
||||
assert_eq!(inverted, Location::new(2, [Parachain(1), account20(), account20()]));
|
||||
}
|
||||
|
||||
// Network Topology
|
||||
@@ -524,12 +508,12 @@ mod tests {
|
||||
#[test]
|
||||
fn inverter_uses_context_as_inverted_location() {
|
||||
parameter_types! {
|
||||
pub UniversalLocation: InteriorMultiLocation = X2(account20(), account20());
|
||||
pub UniversalLocation: InteriorLocation = [account20(), account20()].into();
|
||||
}
|
||||
|
||||
let input = MultiLocation::grandparent();
|
||||
let input = Location::new(2, Here);
|
||||
let inverted = UniversalLocation::get().invert_target(&input).unwrap();
|
||||
assert_eq!(inverted, X2(account20(), account20()).into());
|
||||
assert_eq!(inverted, [account20(), account20()].into());
|
||||
}
|
||||
|
||||
// Network Topology
|
||||
@@ -539,10 +523,10 @@ mod tests {
|
||||
#[test]
|
||||
fn inverter_uses_only_child_on_missing_context() {
|
||||
parameter_types! {
|
||||
pub UniversalLocation: InteriorMultiLocation = PalletInstance(5).into();
|
||||
pub UniversalLocation: InteriorLocation = PalletInstance(5).into();
|
||||
}
|
||||
|
||||
let input = MultiLocation::grandparent();
|
||||
let input = Location::new(2, Here);
|
||||
let inverted = UniversalLocation::get().invert_target(&input).unwrap();
|
||||
assert_eq!(inverted, (OnlyChild, PalletInstance(5)).into());
|
||||
}
|
||||
@@ -550,10 +534,10 @@ mod tests {
|
||||
#[test]
|
||||
fn inverter_errors_when_location_is_too_large() {
|
||||
parameter_types! {
|
||||
pub UniversalLocation: InteriorMultiLocation = Here;
|
||||
pub UniversalLocation: InteriorLocation = Here;
|
||||
}
|
||||
|
||||
let input = MultiLocation { parents: 99, interior: X1(Parachain(88)) };
|
||||
let input = Location { parents: 99, interior: [Parachain(88)].into() };
|
||||
let inverted = UniversalLocation::get().invert_target(&input);
|
||||
assert_eq!(inverted, Err(()));
|
||||
}
|
||||
@@ -561,8 +545,8 @@ mod tests {
|
||||
#[test]
|
||||
fn global_consensus_converts_for_works() {
|
||||
parameter_types! {
|
||||
pub UniversalLocationInNetwork1: InteriorMultiLocation = X2(GlobalConsensus(ByGenesis([1; 32])), Parachain(1234));
|
||||
pub UniversalLocationInNetwork2: InteriorMultiLocation = X2(GlobalConsensus(ByGenesis([2; 32])), Parachain(1234));
|
||||
pub UniversalLocationInNetwork1: InteriorLocation = [GlobalConsensus(ByGenesis([1; 32])), Parachain(1234)].into();
|
||||
pub UniversalLocationInNetwork2: InteriorLocation = [GlobalConsensus(ByGenesis([2; 32])), Parachain(1234)].into();
|
||||
}
|
||||
let network_1 = UniversalLocationInNetwork1::get().global_consensus().expect("NetworkId");
|
||||
let network_2 = UniversalLocationInNetwork2::get().global_consensus().expect("NetworkId");
|
||||
@@ -571,17 +555,17 @@ mod tests {
|
||||
let network_5 = ByGenesis([5; 32]);
|
||||
|
||||
let test_data = vec![
|
||||
(MultiLocation::parent(), false),
|
||||
(MultiLocation::new(0, Here), false),
|
||||
(MultiLocation::new(0, X1(GlobalConsensus(network_1))), false),
|
||||
(MultiLocation::new(1, X1(GlobalConsensus(network_1))), false),
|
||||
(MultiLocation::new(2, X1(GlobalConsensus(network_1))), false),
|
||||
(MultiLocation::new(0, X1(GlobalConsensus(network_2))), false),
|
||||
(MultiLocation::new(1, X1(GlobalConsensus(network_2))), false),
|
||||
(MultiLocation::new(2, X1(GlobalConsensus(network_2))), true),
|
||||
(MultiLocation::new(0, X2(GlobalConsensus(network_2), Parachain(1000))), false),
|
||||
(MultiLocation::new(1, X2(GlobalConsensus(network_2), Parachain(1000))), false),
|
||||
(MultiLocation::new(2, X2(GlobalConsensus(network_2), Parachain(1000))), false),
|
||||
(Location::parent(), false),
|
||||
(Location::new(0, Here), false),
|
||||
(Location::new(0, [GlobalConsensus(network_1)]), false),
|
||||
(Location::new(1, [GlobalConsensus(network_1)]), false),
|
||||
(Location::new(2, [GlobalConsensus(network_1)]), false),
|
||||
(Location::new(0, [GlobalConsensus(network_2)]), false),
|
||||
(Location::new(1, [GlobalConsensus(network_2)]), false),
|
||||
(Location::new(2, [GlobalConsensus(network_2)]), true),
|
||||
(Location::new(0, [GlobalConsensus(network_2), Parachain(1000)]), false),
|
||||
(Location::new(1, [GlobalConsensus(network_2), Parachain(1000)]), false),
|
||||
(Location::new(2, [GlobalConsensus(network_2), Parachain(1000)]), false),
|
||||
];
|
||||
|
||||
for (location, expected_result) in test_data {
|
||||
@@ -596,14 +580,14 @@ mod tests {
|
||||
"expected_result: {}, but conversion passed: {:?}, location: {:?}",
|
||||
expected_result, account, location
|
||||
);
|
||||
match &location {
|
||||
MultiLocation { interior: X1(GlobalConsensus(network)), .. } =>
|
||||
match location.unpack() {
|
||||
(_, [GlobalConsensus(network)]) =>
|
||||
assert_eq!(
|
||||
account,
|
||||
GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::from_params(network),
|
||||
"expected_result: {}, but conversion passed: {:?}, location: {:?}", expected_result, account, location
|
||||
),
|
||||
_ => panic!("expected_result: {}, conversion passed: {:?}, but MultiLocation does not match expected pattern, location: {:?}", expected_result, account, location)
|
||||
_ => panic!("expected_result: {}, conversion passed: {:?}, but Location does not match expected pattern, location: {:?}", expected_result, account, location)
|
||||
}
|
||||
},
|
||||
None => {
|
||||
@@ -619,32 +603,32 @@ mod tests {
|
||||
// all success
|
||||
let res_1_gc_network_3 =
|
||||
GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::convert_location(
|
||||
&MultiLocation::new(2, X1(GlobalConsensus(network_3))),
|
||||
&Location::new(2, [GlobalConsensus(network_3)]),
|
||||
)
|
||||
.expect("conversion is ok");
|
||||
let res_2_gc_network_3 =
|
||||
GlobalConsensusConvertsFor::<UniversalLocationInNetwork2, [u8; 32]>::convert_location(
|
||||
&MultiLocation::new(2, X1(GlobalConsensus(network_3))),
|
||||
&Location::new(2, [GlobalConsensus(network_3)]),
|
||||
)
|
||||
.expect("conversion is ok");
|
||||
let res_1_gc_network_4 =
|
||||
GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::convert_location(
|
||||
&MultiLocation::new(2, X1(GlobalConsensus(network_4))),
|
||||
&Location::new(2, [GlobalConsensus(network_4)]),
|
||||
)
|
||||
.expect("conversion is ok");
|
||||
let res_2_gc_network_4 =
|
||||
GlobalConsensusConvertsFor::<UniversalLocationInNetwork2, [u8; 32]>::convert_location(
|
||||
&MultiLocation::new(2, X1(GlobalConsensus(network_4))),
|
||||
&Location::new(2, [GlobalConsensus(network_4)]),
|
||||
)
|
||||
.expect("conversion is ok");
|
||||
let res_1_gc_network_5 =
|
||||
GlobalConsensusConvertsFor::<UniversalLocationInNetwork1, [u8; 32]>::convert_location(
|
||||
&MultiLocation::new(2, X1(GlobalConsensus(network_5))),
|
||||
&Location::new(2, [GlobalConsensus(network_5)]),
|
||||
)
|
||||
.expect("conversion is ok");
|
||||
let res_2_gc_network_5 =
|
||||
GlobalConsensusConvertsFor::<UniversalLocationInNetwork2, [u8; 32]>::convert_location(
|
||||
&MultiLocation::new(2, X1(GlobalConsensus(network_5))),
|
||||
&Location::new(2, [GlobalConsensus(network_5)]),
|
||||
)
|
||||
.expect("conversion is ok");
|
||||
|
||||
@@ -660,42 +644,30 @@ mod tests {
|
||||
#[test]
|
||||
fn global_consensus_parachain_converts_for_works() {
|
||||
parameter_types! {
|
||||
pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(ByGenesis([9; 32])), Parachain(1234));
|
||||
pub UniversalLocation: InteriorLocation = [GlobalConsensus(ByGenesis([9; 32])), Parachain(1234)].into();
|
||||
}
|
||||
|
||||
let test_data = vec![
|
||||
(MultiLocation::parent(), false),
|
||||
(MultiLocation::new(0, X1(Parachain(1000))), false),
|
||||
(MultiLocation::new(1, X1(Parachain(1000))), false),
|
||||
(Location::parent(), false),
|
||||
(Location::new(0, [Parachain(1000)]), false),
|
||||
(Location::new(1, [Parachain(1000)]), false),
|
||||
(
|
||||
MultiLocation::new(
|
||||
Location::new(
|
||||
2,
|
||||
X3(
|
||||
[
|
||||
GlobalConsensus(ByGenesis([0; 32])),
|
||||
Parachain(1000),
|
||||
AccountId32 { network: None, id: [1; 32].into() },
|
||||
),
|
||||
],
|
||||
),
|
||||
false,
|
||||
),
|
||||
(MultiLocation::new(2, X1(GlobalConsensus(ByGenesis([0; 32])))), false),
|
||||
(
|
||||
MultiLocation::new(0, X2(GlobalConsensus(ByGenesis([0; 32])), Parachain(1000))),
|
||||
false,
|
||||
),
|
||||
(
|
||||
MultiLocation::new(1, X2(GlobalConsensus(ByGenesis([0; 32])), Parachain(1000))),
|
||||
false,
|
||||
),
|
||||
(MultiLocation::new(2, X2(GlobalConsensus(ByGenesis([0; 32])), Parachain(1000))), true),
|
||||
(
|
||||
MultiLocation::new(3, X2(GlobalConsensus(ByGenesis([0; 32])), Parachain(1000))),
|
||||
false,
|
||||
),
|
||||
(
|
||||
MultiLocation::new(9, X2(GlobalConsensus(ByGenesis([0; 32])), Parachain(1000))),
|
||||
false,
|
||||
),
|
||||
(Location::new(2, [GlobalConsensus(ByGenesis([0; 32]))]), false),
|
||||
(Location::new(0, [GlobalConsensus(ByGenesis([0; 32])), Parachain(1000)]), false),
|
||||
(Location::new(1, [GlobalConsensus(ByGenesis([0; 32])), Parachain(1000)]), false),
|
||||
(Location::new(2, [GlobalConsensus(ByGenesis([0; 32])), Parachain(1000)]), true),
|
||||
(Location::new(3, [GlobalConsensus(ByGenesis([0; 32])), Parachain(1000)]), false),
|
||||
(Location::new(9, [GlobalConsensus(ByGenesis([0; 32])), Parachain(1000)]), false),
|
||||
];
|
||||
|
||||
for (location, expected_result) in test_data {
|
||||
@@ -710,8 +682,8 @@ mod tests {
|
||||
"expected_result: {}, but conversion passed: {:?}, location: {:?}",
|
||||
expected_result, account, location
|
||||
);
|
||||
match &location {
|
||||
MultiLocation { interior: X2(GlobalConsensus(network), Parachain(para_id)), .. } =>
|
||||
match location.unpack() {
|
||||
(_, [GlobalConsensus(network), Parachain(para_id)]) =>
|
||||
assert_eq!(
|
||||
account,
|
||||
GlobalConsensusParachainConvertsFor::<UniversalLocation, [u8; 32]>::from_params(network, para_id),
|
||||
@@ -720,7 +692,7 @@ mod tests {
|
||||
_ => assert_eq!(
|
||||
true,
|
||||
expected_result,
|
||||
"expected_result: {}, conversion passed: {:?}, but MultiLocation does not match expected pattern, location: {:?}", expected_result, account, location
|
||||
"expected_result: {}, conversion passed: {:?}, but Location does not match expected pattern, location: {:?}", expected_result, account, location
|
||||
)
|
||||
}
|
||||
},
|
||||
@@ -737,22 +709,22 @@ mod tests {
|
||||
// all success
|
||||
let res_gc_a_p1000 =
|
||||
GlobalConsensusParachainConvertsFor::<UniversalLocation, [u8; 32]>::convert_location(
|
||||
&MultiLocation::new(2, X2(GlobalConsensus(ByGenesis([3; 32])), Parachain(1000))),
|
||||
&Location::new(2, [GlobalConsensus(ByGenesis([3; 32])), Parachain(1000)]),
|
||||
)
|
||||
.expect("conversion is ok");
|
||||
let res_gc_a_p1001 =
|
||||
GlobalConsensusParachainConvertsFor::<UniversalLocation, [u8; 32]>::convert_location(
|
||||
&MultiLocation::new(2, X2(GlobalConsensus(ByGenesis([3; 32])), Parachain(1001))),
|
||||
&Location::new(2, [GlobalConsensus(ByGenesis([3; 32])), Parachain(1001)]),
|
||||
)
|
||||
.expect("conversion is ok");
|
||||
let res_gc_b_p1000 =
|
||||
GlobalConsensusParachainConvertsFor::<UniversalLocation, [u8; 32]>::convert_location(
|
||||
&MultiLocation::new(2, X2(GlobalConsensus(ByGenesis([4; 32])), Parachain(1000))),
|
||||
&Location::new(2, [GlobalConsensus(ByGenesis([4; 32])), Parachain(1000)]),
|
||||
)
|
||||
.expect("conversion is ok");
|
||||
let res_gc_b_p1001 =
|
||||
GlobalConsensusParachainConvertsFor::<UniversalLocation, [u8; 32]>::convert_location(
|
||||
&MultiLocation::new(2, X2(GlobalConsensus(ByGenesis([4; 32])), Parachain(1001))),
|
||||
&Location::new(2, [GlobalConsensus(ByGenesis([4; 32])), Parachain(1001)]),
|
||||
)
|
||||
.expect("conversion is ok");
|
||||
assert_ne!(res_gc_a_p1000, res_gc_a_p1001);
|
||||
@@ -765,9 +737,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn remote_account_convert_on_para_sending_para_32() {
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 1,
|
||||
interior: X2(Parachain(1), AccountId32 { network: None, id: [0u8; 32] }),
|
||||
interior: [Parachain(1), AccountId32 { network: None, id: [0u8; 32] }].into(),
|
||||
};
|
||||
let rem_1 = ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap();
|
||||
|
||||
@@ -779,19 +751,20 @@ mod tests {
|
||||
rem_1
|
||||
);
|
||||
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 1,
|
||||
interior: X2(
|
||||
interior: [
|
||||
Parachain(1),
|
||||
AccountId32 { network: Some(NetworkId::Polkadot), id: [0u8; 32] },
|
||||
),
|
||||
]
|
||||
.into(),
|
||||
};
|
||||
|
||||
assert_eq!(ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap(), rem_1);
|
||||
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 1,
|
||||
interior: X2(Parachain(2), AccountId32 { network: None, id: [0u8; 32] }),
|
||||
interior: [Parachain(2), AccountId32 { network: None, id: [0u8; 32] }].into(),
|
||||
};
|
||||
let rem_2 = ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap();
|
||||
|
||||
@@ -808,9 +781,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn remote_account_convert_on_para_sending_para_20() {
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 1,
|
||||
interior: X2(Parachain(1), AccountKey20 { network: None, key: [0u8; 20] }),
|
||||
interior: [Parachain(1), AccountKey20 { network: None, key: [0u8; 20] }].into(),
|
||||
};
|
||||
let rem_1 = ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap();
|
||||
|
||||
@@ -822,19 +795,20 @@ mod tests {
|
||||
rem_1
|
||||
);
|
||||
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 1,
|
||||
interior: X2(
|
||||
interior: [
|
||||
Parachain(1),
|
||||
AccountKey20 { network: Some(NetworkId::Polkadot), key: [0u8; 20] },
|
||||
),
|
||||
]
|
||||
.into(),
|
||||
};
|
||||
|
||||
assert_eq!(ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap(), rem_1);
|
||||
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 1,
|
||||
interior: X2(Parachain(2), AccountKey20 { network: None, key: [0u8; 20] }),
|
||||
interior: [Parachain(2), AccountKey20 { network: None, key: [0u8; 20] }].into(),
|
||||
};
|
||||
let rem_2 = ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap();
|
||||
|
||||
@@ -851,9 +825,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn remote_account_convert_on_para_sending_relay() {
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 1,
|
||||
interior: X1(AccountId32 { network: None, id: [0u8; 32] }),
|
||||
interior: [AccountId32 { network: None, id: [0u8; 32] }].into(),
|
||||
};
|
||||
let rem_1 = ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap();
|
||||
|
||||
@@ -865,16 +839,16 @@ mod tests {
|
||||
rem_1
|
||||
);
|
||||
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 1,
|
||||
interior: X1(AccountId32 { network: Some(NetworkId::Polkadot), id: [0u8; 32] }),
|
||||
interior: [AccountId32 { network: Some(NetworkId::Polkadot), id: [0u8; 32] }].into(),
|
||||
};
|
||||
|
||||
assert_eq!(ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap(), rem_1);
|
||||
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 1,
|
||||
interior: X1(AccountId32 { network: None, id: [1u8; 32] }),
|
||||
interior: [AccountId32 { network: None, id: [1u8; 32] }].into(),
|
||||
};
|
||||
let rem_2 = ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap();
|
||||
|
||||
@@ -891,9 +865,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn remote_account_convert_on_relay_sending_para_20() {
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 0,
|
||||
interior: X2(Parachain(1), AccountKey20 { network: None, key: [0u8; 20] }),
|
||||
interior: [Parachain(1), AccountKey20 { network: None, key: [0u8; 20] }].into(),
|
||||
};
|
||||
let rem_1 = ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap();
|
||||
|
||||
@@ -905,9 +879,9 @@ mod tests {
|
||||
rem_1
|
||||
);
|
||||
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 0,
|
||||
interior: X2(Parachain(2), AccountKey20 { network: None, key: [0u8; 20] }),
|
||||
interior: [Parachain(2), AccountKey20 { network: None, key: [0u8; 20] }].into(),
|
||||
};
|
||||
let rem_2 = ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap();
|
||||
|
||||
@@ -924,9 +898,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn remote_account_convert_on_relay_sending_para_32() {
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 0,
|
||||
interior: X2(Parachain(1), AccountId32 { network: None, id: [0u8; 32] }),
|
||||
interior: [Parachain(1), AccountId32 { network: None, id: [0u8; 32] }].into(),
|
||||
};
|
||||
let rem_1 = ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap();
|
||||
|
||||
@@ -938,19 +912,20 @@ mod tests {
|
||||
rem_1
|
||||
);
|
||||
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 0,
|
||||
interior: X2(
|
||||
interior: [
|
||||
Parachain(1),
|
||||
AccountId32 { network: Some(NetworkId::Polkadot), id: [0u8; 32] },
|
||||
),
|
||||
]
|
||||
.into(),
|
||||
};
|
||||
|
||||
assert_eq!(ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap(), rem_1);
|
||||
|
||||
let mul = MultiLocation {
|
||||
let mul = Location {
|
||||
parents: 0,
|
||||
interior: X2(Parachain(2), AccountId32 { network: None, id: [0u8; 32] }),
|
||||
interior: [Parachain(2), AccountId32 { network: None, id: [0u8; 32] }].into(),
|
||||
};
|
||||
let rem_2 = ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).unwrap();
|
||||
|
||||
@@ -966,20 +941,18 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remote_account_fails_with_bad_multilocation() {
|
||||
let mul = MultiLocation {
|
||||
fn remote_account_fails_with_bad_location() {
|
||||
let mul = Location {
|
||||
parents: 1,
|
||||
interior: X1(AccountKey20 { network: None, key: [0u8; 20] }),
|
||||
interior: [AccountKey20 { network: None, key: [0u8; 20] }].into(),
|
||||
};
|
||||
assert!(ForeignChainAliasAccount::<[u8; 32]>::convert_location(&mul).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remote_account_convert_on_para_sending_from_remote_para_treasury() {
|
||||
let relay_treasury_to_para_location = MultiLocation {
|
||||
parents: 1,
|
||||
interior: X1(Plurality { id: BodyId::Treasury, part: BodyPart::Voice }),
|
||||
};
|
||||
let relay_treasury_to_para_location =
|
||||
Location::new(1, [Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]);
|
||||
let actual_description = ForeignChainAliasTreasuryAccount::<[u8; 32]>::convert_location(
|
||||
&relay_treasury_to_para_location,
|
||||
)
|
||||
@@ -993,13 +966,10 @@ mod tests {
|
||||
actual_description
|
||||
);
|
||||
|
||||
let para_to_para_treasury_location = MultiLocation {
|
||||
parents: 1,
|
||||
interior: X2(
|
||||
Parachain(1001),
|
||||
Plurality { id: BodyId::Treasury, part: BodyPart::Voice },
|
||||
),
|
||||
};
|
||||
let para_to_para_treasury_location = Location::new(
|
||||
1,
|
||||
[Parachain(1001), Plurality { id: BodyId::Treasury, part: BodyPart::Voice }],
|
||||
);
|
||||
let actual_description = ForeignChainAliasTreasuryAccount::<[u8; 32]>::convert_location(
|
||||
¶_to_para_treasury_location,
|
||||
)
|
||||
@@ -1016,10 +986,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn local_account_convert_on_para_from_relay_treasury() {
|
||||
let location = MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(Plurality { id: BodyId::Treasury, part: BodyPart::Voice }),
|
||||
};
|
||||
let location =
|
||||
Location::new(0, [Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]);
|
||||
|
||||
parameter_types! {
|
||||
pub TreasuryAccountId: AccountId = AccountId::new([42u8; 32]);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use core::ops::ControlFlow;
|
||||
use frame_support::traits::ProcessMessageError;
|
||||
use xcm::latest::{Instruction, MultiLocation};
|
||||
use xcm::latest::{Instruction, Location};
|
||||
|
||||
/// Creates an instruction matcher from an XCM. Since XCM versions differ, we need to make a trait
|
||||
/// here to unify the interfaces among them.
|
||||
@@ -67,7 +67,7 @@ impl<'a, Call> CreateMatcher for &'a mut [Instruction<Call>] {
|
||||
pub trait MatchXcm {
|
||||
/// The concrete instruction type. Necessary to specify as it changes between XCM versions.
|
||||
type Inst;
|
||||
/// The `MultiLocation` type. Necessary to specify as it changes between XCM versions.
|
||||
/// The `Location` type. Necessary to specify as it changes between XCM versions.
|
||||
type Loc;
|
||||
/// The error type to throw when errors happen during matching.
|
||||
type Error;
|
||||
@@ -125,7 +125,7 @@ pub struct Matcher<'a, Call> {
|
||||
impl<'a, Call> MatchXcm for Matcher<'a, Call> {
|
||||
type Error = ProcessMessageError;
|
||||
type Inst = Instruction<Call>;
|
||||
type Loc = MultiLocation;
|
||||
type Loc = Location;
|
||||
|
||||
fn assert_remaining_insts(self, n: usize) -> Result<Self, Self::Error>
|
||||
where
|
||||
|
||||
@@ -14,37 +14,47 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Various implementations and utilities for matching and filtering `MultiLocation` and
|
||||
//! `InteriorMultiLocation` types.
|
||||
//! Various implementations and utilities for matching and filtering `Location` and
|
||||
//! `InteriorLocation` types.
|
||||
|
||||
use frame_support::traits::{Contains, Get};
|
||||
use xcm::latest::{InteriorMultiLocation, MultiLocation, NetworkId};
|
||||
use xcm::latest::{InteriorLocation, Location, NetworkId};
|
||||
|
||||
/// An implementation of `Contains` that checks for `MultiLocation` or
|
||||
/// `InteriorMultiLocation` if starts with the provided type `T`.
|
||||
pub struct StartsWith<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Get<MultiLocation>> Contains<MultiLocation> for StartsWith<T> {
|
||||
fn contains(t: &MultiLocation) -> bool {
|
||||
t.starts_with(&T::get())
|
||||
/// An implementation of `Contains` that checks for `Location` or
|
||||
/// `InteriorLocation` if starts with the provided type `T`.
|
||||
pub struct StartsWith<T, L = Location>(sp_std::marker::PhantomData<(T, L)>);
|
||||
impl<T: Get<L>, L: TryInto<Location> + Clone> Contains<L> for StartsWith<T, L> {
|
||||
fn contains(location: &L) -> bool {
|
||||
let latest_location: Location = if let Ok(location) = (*location).clone().try_into() {
|
||||
location
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
let latest_t = if let Ok(location) = T::get().try_into() {
|
||||
location
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
latest_location.starts_with(&latest_t)
|
||||
}
|
||||
}
|
||||
impl<T: Get<InteriorMultiLocation>> Contains<InteriorMultiLocation> for StartsWith<T> {
|
||||
fn contains(t: &InteriorMultiLocation) -> bool {
|
||||
impl<T: Get<InteriorLocation>> Contains<InteriorLocation> for StartsWith<T> {
|
||||
fn contains(t: &InteriorLocation) -> bool {
|
||||
t.starts_with(&T::get())
|
||||
}
|
||||
}
|
||||
|
||||
/// An implementation of `Contains` that checks for `MultiLocation` or
|
||||
/// `InteriorMultiLocation` if starts with expected `GlobalConsensus(NetworkId)` provided as type
|
||||
/// An implementation of `Contains` that checks for `Location` or
|
||||
/// `InteriorLocation` if starts with expected `GlobalConsensus(NetworkId)` provided as type
|
||||
/// `T`.
|
||||
pub struct StartsWithExplicitGlobalConsensus<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Get<NetworkId>> Contains<MultiLocation> for StartsWithExplicitGlobalConsensus<T> {
|
||||
fn contains(location: &MultiLocation) -> bool {
|
||||
matches!(location.interior.global_consensus(), Ok(requested_network) if requested_network.eq(&T::get()))
|
||||
impl<T: Get<NetworkId>> Contains<Location> for StartsWithExplicitGlobalConsensus<T> {
|
||||
fn contains(location: &Location) -> bool {
|
||||
matches!(location.interior().global_consensus(), Ok(requested_network) if requested_network.eq(&T::get()))
|
||||
}
|
||||
}
|
||||
impl<T: Get<NetworkId>> Contains<InteriorMultiLocation> for StartsWithExplicitGlobalConsensus<T> {
|
||||
fn contains(location: &InteriorMultiLocation) -> bool {
|
||||
impl<T: Get<NetworkId>> Contains<InteriorLocation> for StartsWithExplicitGlobalConsensus<T> {
|
||||
fn contains(location: &InteriorLocation) -> bool {
|
||||
matches!(location.global_consensus(), Ok(requested_network) if requested_network.eq(&T::get()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,25 +19,24 @@
|
||||
use frame_support::traits::Get;
|
||||
use sp_std::marker::PhantomData;
|
||||
use xcm::latest::{
|
||||
AssetId::{Abstract, Concrete},
|
||||
AssetInstance,
|
||||
Asset, AssetId, AssetInstance,
|
||||
Fungibility::{Fungible, NonFungible},
|
||||
MultiAsset, MultiLocation,
|
||||
Location,
|
||||
};
|
||||
use xcm_executor::traits::{MatchesFungible, MatchesNonFungible};
|
||||
|
||||
/// Converts a `MultiAsset` into balance `B` if it is a concrete fungible with an id equal to that
|
||||
/// Converts a `Asset` into balance `B` if its id is equal to that
|
||||
/// given by `T`'s `Get`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use xcm::latest::{MultiLocation, Parent};
|
||||
/// use xcm::latest::{Location, Parent};
|
||||
/// use staging_xcm_builder::IsConcrete;
|
||||
/// use xcm_executor::traits::MatchesFungible;
|
||||
///
|
||||
/// frame_support::parameter_types! {
|
||||
/// pub TargetLocation: MultiLocation = Parent.into();
|
||||
/// pub TargetLocation: Location = Parent.into();
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {
|
||||
@@ -47,62 +46,18 @@ use xcm_executor::traits::{MatchesFungible, MatchesNonFungible};
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct IsConcrete<T>(PhantomData<T>);
|
||||
impl<T: Get<MultiLocation>, B: TryFrom<u128>> MatchesFungible<B> for IsConcrete<T> {
|
||||
fn matches_fungible(a: &MultiAsset) -> Option<B> {
|
||||
impl<T: Get<Location>, B: TryFrom<u128>> MatchesFungible<B> for IsConcrete<T> {
|
||||
fn matches_fungible(a: &Asset) -> Option<B> {
|
||||
match (&a.id, &a.fun) {
|
||||
(Concrete(ref id), Fungible(ref amount)) if id == &T::get() =>
|
||||
(*amount).try_into().ok(),
|
||||
(AssetId(ref id), Fungible(ref amount)) if id == &T::get() => (*amount).try_into().ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T: Get<MultiLocation>, I: TryFrom<AssetInstance>> MatchesNonFungible<I> for IsConcrete<T> {
|
||||
fn matches_nonfungible(a: &MultiAsset) -> Option<I> {
|
||||
impl<T: Get<Location>, I: TryFrom<AssetInstance>> MatchesNonFungible<I> for IsConcrete<T> {
|
||||
fn matches_nonfungible(a: &Asset) -> Option<I> {
|
||||
match (&a.id, &a.fun) {
|
||||
(Concrete(id), NonFungible(instance)) if id == &T::get() => (*instance).try_into().ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Same as [`IsConcrete`] but for a fungible with abstract location.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use xcm::latest::prelude::*;
|
||||
/// use staging_xcm_builder::IsAbstract;
|
||||
/// use xcm_executor::traits::{MatchesFungible, MatchesNonFungible};
|
||||
///
|
||||
/// frame_support::parameter_types! {
|
||||
/// pub TargetLocation: [u8; 32] = [7u8; 32];
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let asset = ([7u8; 32], 999u128).into();
|
||||
/// // match `asset` if it is an abstract asset in `TargetLocation`.
|
||||
/// assert_eq!(<IsAbstract<TargetLocation> as MatchesFungible<u128>>::matches_fungible(&asset), Some(999));
|
||||
/// let nft = ([7u8; 32], [42u8; 4]).into();
|
||||
/// assert_eq!(
|
||||
/// <IsAbstract<TargetLocation> as MatchesNonFungible<[u8; 4]>>::matches_nonfungible(&nft),
|
||||
/// Some([42u8; 4])
|
||||
/// );
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct IsAbstract<T>(PhantomData<T>);
|
||||
impl<T: Get<[u8; 32]>, B: TryFrom<u128>> MatchesFungible<B> for IsAbstract<T> {
|
||||
fn matches_fungible(a: &MultiAsset) -> Option<B> {
|
||||
match (&a.id, &a.fun) {
|
||||
(Abstract(ref id), Fungible(ref amount)) if id == &T::get() =>
|
||||
(*amount).try_into().ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T: Get<[u8; 32]>, B: TryFrom<AssetInstance>> MatchesNonFungible<B> for IsAbstract<T> {
|
||||
fn matches_nonfungible(a: &MultiAsset) -> Option<B> {
|
||||
match (&a.id, &a.fun) {
|
||||
(Abstract(id), NonFungible(instance)) if id == &T::get() => (*instance).try_into().ok(),
|
||||
(AssetId(id), NonFungible(instance)) if id == &T::get() => (*instance).try_into().ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,11 +40,11 @@ impl<
|
||||
> TransactAsset for NonFungiblesTransferAdapter<Assets, Matcher, AccountIdConverter, AccountId>
|
||||
{
|
||||
fn transfer_asset(
|
||||
what: &MultiAsset,
|
||||
from: &MultiLocation,
|
||||
to: &MultiLocation,
|
||||
what: &Asset,
|
||||
from: &Location,
|
||||
to: &Location,
|
||||
context: &XcmContext,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<xcm_executor::AssetsInHolding, XcmError> {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"transfer_asset what: {:?}, from: {:?}, to: {:?}, context: {:?}",
|
||||
@@ -131,7 +131,7 @@ impl<
|
||||
CheckingAccount,
|
||||
>
|
||||
{
|
||||
fn can_check_in(_origin: &MultiLocation, what: &MultiAsset, context: &XcmContext) -> XcmResult {
|
||||
fn can_check_in(_origin: &Location, what: &Asset, context: &XcmContext) -> XcmResult {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"can_check_in origin: {:?}, what: {:?}, context: {:?}",
|
||||
@@ -150,7 +150,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn check_in(_origin: &MultiLocation, what: &MultiAsset, context: &XcmContext) {
|
||||
fn check_in(_origin: &Location, what: &Asset, context: &XcmContext) {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"check_in origin: {:?}, what: {:?}, context: {:?}",
|
||||
@@ -169,7 +169,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn can_check_out(_dest: &MultiLocation, what: &MultiAsset, context: &XcmContext) -> XcmResult {
|
||||
fn can_check_out(_dest: &Location, what: &Asset, context: &XcmContext) -> XcmResult {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"can_check_out dest: {:?}, what: {:?}, context: {:?}",
|
||||
@@ -188,7 +188,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn check_out(_dest: &MultiLocation, what: &MultiAsset, context: &XcmContext) {
|
||||
fn check_out(_dest: &Location, what: &Asset, context: &XcmContext) {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"check_out dest: {:?}, what: {:?}, context: {:?}",
|
||||
@@ -207,11 +207,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
fn deposit_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
context: Option<&XcmContext>,
|
||||
) -> XcmResult {
|
||||
fn deposit_asset(what: &Asset, who: &Location, context: Option<&XcmContext>) -> XcmResult {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"deposit_asset what: {:?}, who: {:?}, context: {:?}",
|
||||
@@ -228,10 +224,10 @@ impl<
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
what: &Asset,
|
||||
who: &Location,
|
||||
maybe_context: Option<&XcmContext>,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<xcm_executor::AssetsInHolding, XcmError> {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"withdraw_asset what: {:?}, who: {:?}, maybe_context: {:?}",
|
||||
@@ -267,7 +263,7 @@ impl<
|
||||
> TransactAsset
|
||||
for NonFungiblesAdapter<Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount>
|
||||
{
|
||||
fn can_check_in(origin: &MultiLocation, what: &MultiAsset, context: &XcmContext) -> XcmResult {
|
||||
fn can_check_in(origin: &Location, what: &Asset, context: &XcmContext) -> XcmResult {
|
||||
NonFungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -278,7 +274,7 @@ impl<
|
||||
>::can_check_in(origin, what, context)
|
||||
}
|
||||
|
||||
fn check_in(origin: &MultiLocation, what: &MultiAsset, context: &XcmContext) {
|
||||
fn check_in(origin: &Location, what: &Asset, context: &XcmContext) {
|
||||
NonFungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -289,7 +285,7 @@ impl<
|
||||
>::check_in(origin, what, context)
|
||||
}
|
||||
|
||||
fn can_check_out(dest: &MultiLocation, what: &MultiAsset, context: &XcmContext) -> XcmResult {
|
||||
fn can_check_out(dest: &Location, what: &Asset, context: &XcmContext) -> XcmResult {
|
||||
NonFungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -300,7 +296,7 @@ impl<
|
||||
>::can_check_out(dest, what, context)
|
||||
}
|
||||
|
||||
fn check_out(dest: &MultiLocation, what: &MultiAsset, context: &XcmContext) {
|
||||
fn check_out(dest: &Location, what: &Asset, context: &XcmContext) {
|
||||
NonFungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -311,11 +307,7 @@ impl<
|
||||
>::check_out(dest, what, context)
|
||||
}
|
||||
|
||||
fn deposit_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
context: Option<&XcmContext>,
|
||||
) -> XcmResult {
|
||||
fn deposit_asset(what: &Asset, who: &Location, context: Option<&XcmContext>) -> XcmResult {
|
||||
NonFungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -327,10 +319,10 @@ impl<
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
what: &Asset,
|
||||
who: &Location,
|
||||
maybe_context: Option<&XcmContext>,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<xcm_executor::AssetsInHolding, XcmError> {
|
||||
NonFungiblesMutateAdapter::<
|
||||
Assets,
|
||||
Matcher,
|
||||
@@ -342,11 +334,11 @@ impl<
|
||||
}
|
||||
|
||||
fn transfer_asset(
|
||||
what: &MultiAsset,
|
||||
from: &MultiLocation,
|
||||
to: &MultiLocation,
|
||||
what: &Asset,
|
||||
from: &Location,
|
||||
to: &Location,
|
||||
context: &XcmContext,
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
) -> result::Result<xcm_executor::AssetsInHolding, XcmError> {
|
||||
NonFungiblesTransferAdapter::<Assets, Matcher, AccountIdConverter, AccountId>::transfer_asset(
|
||||
what, from, to, context,
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Implementation for `ContainsPair<MultiLocation, MultiLocation>`.
|
||||
//! Implementation for `ContainsPair<Location, Location>`.
|
||||
|
||||
use frame_support::traits::{Contains, ContainsPair};
|
||||
use sp_std::marker::PhantomData;
|
||||
@@ -25,13 +25,15 @@ use xcm::latest::prelude::*;
|
||||
///
|
||||
/// Requires that the prefixed origin `AccountId32` matches the target `AccountId32`.
|
||||
pub struct AliasForeignAccountId32<Prefix>(PhantomData<Prefix>);
|
||||
impl<Prefix: Contains<MultiLocation>> ContainsPair<MultiLocation, MultiLocation>
|
||||
impl<Prefix: Contains<Location>> ContainsPair<Location, Location>
|
||||
for AliasForeignAccountId32<Prefix>
|
||||
{
|
||||
fn contains(origin: &MultiLocation, target: &MultiLocation) -> bool {
|
||||
if let (prefix, Some(account_id @ AccountId32 { .. })) = origin.split_last_interior() {
|
||||
fn contains(origin: &Location, target: &Location) -> bool {
|
||||
if let (prefix, Some(account_id @ AccountId32 { .. })) =
|
||||
origin.clone().split_last_interior()
|
||||
{
|
||||
return Prefix::contains(&prefix) &&
|
||||
*target == MultiLocation { parents: 0, interior: X1(account_id) }
|
||||
*target == Location { parents: 0, interior: [account_id].into() }
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ use frame_system::RawOrigin as SystemRawOrigin;
|
||||
use polkadot_parachain_primitives::primitives::IsSystem;
|
||||
use sp_runtime::traits::TryConvert;
|
||||
use sp_std::marker::PhantomData;
|
||||
use xcm::latest::{BodyId, BodyPart, Junction, Junctions::*, MultiLocation, NetworkId, OriginKind};
|
||||
use xcm::latest::{BodyId, BodyPart, Junction, Junctions::*, Location, NetworkId, OriginKind};
|
||||
use xcm_executor::traits::{ConvertLocation, ConvertOrigin};
|
||||
|
||||
/// Sovereign accounts use the system's `Signed` origin with an account ID derived from the
|
||||
@@ -35,9 +35,9 @@ where
|
||||
RuntimeOrigin::AccountId: Clone,
|
||||
{
|
||||
fn convert_origin(
|
||||
origin: impl Into<MultiLocation>,
|
||||
origin: impl Into<Location>,
|
||||
kind: OriginKind,
|
||||
) -> Result<RuntimeOrigin, MultiLocation> {
|
||||
) -> Result<RuntimeOrigin, Location> {
|
||||
let origin = origin.into();
|
||||
log::trace!(
|
||||
target: "xcm::origin_conversion",
|
||||
@@ -56,9 +56,9 @@ where
|
||||
pub struct ParentAsSuperuser<RuntimeOrigin>(PhantomData<RuntimeOrigin>);
|
||||
impl<RuntimeOrigin: OriginTrait> ConvertOrigin<RuntimeOrigin> for ParentAsSuperuser<RuntimeOrigin> {
|
||||
fn convert_origin(
|
||||
origin: impl Into<MultiLocation>,
|
||||
origin: impl Into<Location>,
|
||||
kind: OriginKind,
|
||||
) -> Result<RuntimeOrigin, MultiLocation> {
|
||||
) -> Result<RuntimeOrigin, Location> {
|
||||
let origin = origin.into();
|
||||
log::trace!(target: "xcm::origin_conversion", "ParentAsSuperuser origin: {:?}, kind: {:?}", origin, kind);
|
||||
if kind == OriginKind::Superuser && origin.contains_parents_only(1) {
|
||||
@@ -76,17 +76,16 @@ impl<ParaId: IsSystem + From<u32>, RuntimeOrigin: OriginTrait> ConvertOrigin<Run
|
||||
for ChildSystemParachainAsSuperuser<ParaId, RuntimeOrigin>
|
||||
{
|
||||
fn convert_origin(
|
||||
origin: impl Into<MultiLocation>,
|
||||
origin: impl Into<Location>,
|
||||
kind: OriginKind,
|
||||
) -> Result<RuntimeOrigin, MultiLocation> {
|
||||
) -> Result<RuntimeOrigin, Location> {
|
||||
let origin = origin.into();
|
||||
log::trace!(target: "xcm::origin_conversion", "ChildSystemParachainAsSuperuser origin: {:?}, kind: {:?}", origin, kind);
|
||||
match (kind, origin) {
|
||||
(
|
||||
OriginKind::Superuser,
|
||||
MultiLocation { parents: 0, interior: X1(Junction::Parachain(id)) },
|
||||
) if ParaId::from(id).is_system() => Ok(RuntimeOrigin::root()),
|
||||
(_, origin) => Err(origin),
|
||||
match (kind, origin.unpack()) {
|
||||
(OriginKind::Superuser, (0, [Junction::Parachain(id)]))
|
||||
if ParaId::from(*id).is_system() =>
|
||||
Ok(RuntimeOrigin::root()),
|
||||
_ => Err(origin),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,21 +97,20 @@ impl<ParaId: IsSystem + From<u32>, RuntimeOrigin: OriginTrait> ConvertOrigin<Run
|
||||
for SiblingSystemParachainAsSuperuser<ParaId, RuntimeOrigin>
|
||||
{
|
||||
fn convert_origin(
|
||||
origin: impl Into<MultiLocation>,
|
||||
origin: impl Into<Location>,
|
||||
kind: OriginKind,
|
||||
) -> Result<RuntimeOrigin, MultiLocation> {
|
||||
) -> Result<RuntimeOrigin, Location> {
|
||||
let origin = origin.into();
|
||||
log::trace!(
|
||||
target: "xcm::origin_conversion",
|
||||
"SiblingSystemParachainAsSuperuser origin: {:?}, kind: {:?}",
|
||||
origin, kind,
|
||||
);
|
||||
match (kind, origin) {
|
||||
(
|
||||
OriginKind::Superuser,
|
||||
MultiLocation { parents: 1, interior: X1(Junction::Parachain(id)) },
|
||||
) if ParaId::from(id).is_system() => Ok(RuntimeOrigin::root()),
|
||||
(_, origin) => Err(origin),
|
||||
match (kind, origin.unpack()) {
|
||||
(OriginKind::Superuser, (1, [Junction::Parachain(id)]))
|
||||
if ParaId::from(*id).is_system() =>
|
||||
Ok(RuntimeOrigin::root()),
|
||||
_ => Err(origin),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,17 +122,15 @@ impl<ParachainOrigin: From<u32>, RuntimeOrigin: From<ParachainOrigin>> ConvertOr
|
||||
for ChildParachainAsNative<ParachainOrigin, RuntimeOrigin>
|
||||
{
|
||||
fn convert_origin(
|
||||
origin: impl Into<MultiLocation>,
|
||||
origin: impl Into<Location>,
|
||||
kind: OriginKind,
|
||||
) -> Result<RuntimeOrigin, MultiLocation> {
|
||||
) -> Result<RuntimeOrigin, Location> {
|
||||
let origin = origin.into();
|
||||
log::trace!(target: "xcm::origin_conversion", "ChildParachainAsNative origin: {:?}, kind: {:?}", origin, kind);
|
||||
match (kind, origin) {
|
||||
(
|
||||
OriginKind::Native,
|
||||
MultiLocation { parents: 0, interior: X1(Junction::Parachain(id)) },
|
||||
) => Ok(RuntimeOrigin::from(ParachainOrigin::from(id))),
|
||||
(_, origin) => Err(origin),
|
||||
match (kind, origin.unpack()) {
|
||||
(OriginKind::Native, (0, [Junction::Parachain(id)])) =>
|
||||
Ok(RuntimeOrigin::from(ParachainOrigin::from(*id))),
|
||||
_ => Err(origin),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,21 +142,19 @@ impl<ParachainOrigin: From<u32>, RuntimeOrigin: From<ParachainOrigin>> ConvertOr
|
||||
for SiblingParachainAsNative<ParachainOrigin, RuntimeOrigin>
|
||||
{
|
||||
fn convert_origin(
|
||||
origin: impl Into<MultiLocation>,
|
||||
origin: impl Into<Location>,
|
||||
kind: OriginKind,
|
||||
) -> Result<RuntimeOrigin, MultiLocation> {
|
||||
) -> Result<RuntimeOrigin, Location> {
|
||||
let origin = origin.into();
|
||||
log::trace!(
|
||||
target: "xcm::origin_conversion",
|
||||
"SiblingParachainAsNative origin: {:?}, kind: {:?}",
|
||||
origin, kind,
|
||||
);
|
||||
match (kind, origin) {
|
||||
(
|
||||
OriginKind::Native,
|
||||
MultiLocation { parents: 1, interior: X1(Junction::Parachain(id)) },
|
||||
) => Ok(RuntimeOrigin::from(ParachainOrigin::from(id))),
|
||||
(_, origin) => Err(origin),
|
||||
match (kind, origin.unpack()) {
|
||||
(OriginKind::Native, (1, [Junction::Parachain(id)])) =>
|
||||
Ok(RuntimeOrigin::from(ParachainOrigin::from(*id))),
|
||||
_ => Err(origin),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,9 +167,9 @@ impl<RelayOrigin: Get<RuntimeOrigin>, RuntimeOrigin> ConvertOrigin<RuntimeOrigin
|
||||
for RelayChainAsNative<RelayOrigin, RuntimeOrigin>
|
||||
{
|
||||
fn convert_origin(
|
||||
origin: impl Into<MultiLocation>,
|
||||
origin: impl Into<Location>,
|
||||
kind: OriginKind,
|
||||
) -> Result<RuntimeOrigin, MultiLocation> {
|
||||
) -> Result<RuntimeOrigin, Location> {
|
||||
let origin = origin.into();
|
||||
log::trace!(target: "xcm::origin_conversion", "RelayChainAsNative origin: {:?}, kind: {:?}", origin, kind);
|
||||
if kind == OriginKind::Native && origin.contains_parents_only(1) {
|
||||
@@ -193,22 +187,20 @@ where
|
||||
RuntimeOrigin::AccountId: From<[u8; 32]>,
|
||||
{
|
||||
fn convert_origin(
|
||||
origin: impl Into<MultiLocation>,
|
||||
origin: impl Into<Location>,
|
||||
kind: OriginKind,
|
||||
) -> Result<RuntimeOrigin, MultiLocation> {
|
||||
) -> Result<RuntimeOrigin, Location> {
|
||||
let origin = origin.into();
|
||||
log::trace!(
|
||||
target: "xcm::origin_conversion",
|
||||
"SignedAccountId32AsNative origin: {:?}, kind: {:?}",
|
||||
origin, kind,
|
||||
);
|
||||
match (kind, origin) {
|
||||
(
|
||||
OriginKind::Native,
|
||||
MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { id, network }) },
|
||||
) if matches!(network, None) || network == Network::get() =>
|
||||
Ok(RuntimeOrigin::signed(id.into())),
|
||||
(_, origin) => Err(origin),
|
||||
match (kind, origin.unpack()) {
|
||||
(OriginKind::Native, (0, [Junction::AccountId32 { id, network }]))
|
||||
if matches!(network, None) || *network == Network::get() =>
|
||||
Ok(RuntimeOrigin::signed((*id).into())),
|
||||
_ => Err(origin),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,34 +214,32 @@ where
|
||||
RuntimeOrigin::AccountId: From<[u8; 20]>,
|
||||
{
|
||||
fn convert_origin(
|
||||
origin: impl Into<MultiLocation>,
|
||||
origin: impl Into<Location>,
|
||||
kind: OriginKind,
|
||||
) -> Result<RuntimeOrigin, MultiLocation> {
|
||||
) -> Result<RuntimeOrigin, Location> {
|
||||
let origin = origin.into();
|
||||
log::trace!(
|
||||
target: "xcm::origin_conversion",
|
||||
"SignedAccountKey20AsNative origin: {:?}, kind: {:?}",
|
||||
origin, kind,
|
||||
);
|
||||
match (kind, origin) {
|
||||
(
|
||||
OriginKind::Native,
|
||||
MultiLocation { parents: 0, interior: X1(Junction::AccountKey20 { key, network }) },
|
||||
) if (matches!(network, None) || network == Network::get()) =>
|
||||
Ok(RuntimeOrigin::signed(key.into())),
|
||||
(_, origin) => Err(origin),
|
||||
match (kind, origin.unpack()) {
|
||||
(OriginKind::Native, (0, [Junction::AccountKey20 { key, network }]))
|
||||
if (matches!(network, None) || *network == Network::get()) =>
|
||||
Ok(RuntimeOrigin::signed((*key).into())),
|
||||
_ => Err(origin),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `EnsureOrigin` barrier to convert from dispatch origin to XCM origin, if one exists.
|
||||
pub struct EnsureXcmOrigin<RuntimeOrigin, Conversion>(PhantomData<(RuntimeOrigin, Conversion)>);
|
||||
impl<RuntimeOrigin: OriginTrait + Clone, Conversion: TryConvert<RuntimeOrigin, MultiLocation>>
|
||||
impl<RuntimeOrigin: OriginTrait + Clone, Conversion: TryConvert<RuntimeOrigin, Location>>
|
||||
EnsureOrigin<RuntimeOrigin> for EnsureXcmOrigin<RuntimeOrigin, Conversion>
|
||||
where
|
||||
RuntimeOrigin::PalletsOrigin: PartialEq,
|
||||
{
|
||||
type Success = MultiLocation;
|
||||
type Success = Location;
|
||||
fn try_origin(o: RuntimeOrigin) -> Result<Self::Success, RuntimeOrigin> {
|
||||
let o = match Conversion::try_convert(o) {
|
||||
Ok(location) => return Ok(location),
|
||||
@@ -282,13 +272,12 @@ impl<
|
||||
RuntimeOrigin: OriginTrait + Clone,
|
||||
AccountId: Into<[u8; 32]>,
|
||||
Network: Get<Option<NetworkId>>,
|
||||
> TryConvert<RuntimeOrigin, MultiLocation>
|
||||
for SignedToAccountId32<RuntimeOrigin, AccountId, Network>
|
||||
> TryConvert<RuntimeOrigin, Location> for SignedToAccountId32<RuntimeOrigin, AccountId, Network>
|
||||
where
|
||||
RuntimeOrigin::PalletsOrigin: From<SystemRawOrigin<AccountId>>
|
||||
+ TryInto<SystemRawOrigin<AccountId>, Error = RuntimeOrigin::PalletsOrigin>,
|
||||
{
|
||||
fn try_convert(o: RuntimeOrigin) -> Result<MultiLocation, RuntimeOrigin> {
|
||||
fn try_convert(o: RuntimeOrigin) -> Result<Location, RuntimeOrigin> {
|
||||
o.try_with_caller(|caller| match caller.try_into() {
|
||||
Ok(SystemRawOrigin::Signed(who)) =>
|
||||
Ok(Junction::AccountId32 { network: Network::get(), id: who.into() }.into()),
|
||||
@@ -299,7 +288,7 @@ where
|
||||
}
|
||||
|
||||
/// `Convert` implementation to convert from some an origin which implements `Backing` into a
|
||||
/// corresponding `Plurality` `MultiLocation`.
|
||||
/// corresponding `Plurality` `Location`.
|
||||
///
|
||||
/// Typically used when configuring `pallet-xcm` for allowing a collective's Origin to dispatch an
|
||||
/// XCM from a `Plurality` origin.
|
||||
@@ -307,12 +296,12 @@ pub struct BackingToPlurality<RuntimeOrigin, COrigin, Body>(
|
||||
PhantomData<(RuntimeOrigin, COrigin, Body)>,
|
||||
);
|
||||
impl<RuntimeOrigin: OriginTrait + Clone, COrigin: GetBacking, Body: Get<BodyId>>
|
||||
TryConvert<RuntimeOrigin, MultiLocation> for BackingToPlurality<RuntimeOrigin, COrigin, Body>
|
||||
TryConvert<RuntimeOrigin, Location> for BackingToPlurality<RuntimeOrigin, COrigin, Body>
|
||||
where
|
||||
RuntimeOrigin::PalletsOrigin:
|
||||
From<COrigin> + TryInto<COrigin, Error = RuntimeOrigin::PalletsOrigin>,
|
||||
{
|
||||
fn try_convert(o: RuntimeOrigin) -> Result<MultiLocation, RuntimeOrigin> {
|
||||
fn try_convert(o: RuntimeOrigin) -> Result<Location, RuntimeOrigin> {
|
||||
o.try_with_caller(|caller| match caller.try_into() {
|
||||
Ok(co) => match co.get_backing() {
|
||||
Some(backing) => Ok(Junction::Plurality {
|
||||
@@ -333,10 +322,10 @@ pub struct OriginToPluralityVoice<RuntimeOrigin, EnsureBodyOrigin, Body>(
|
||||
PhantomData<(RuntimeOrigin, EnsureBodyOrigin, Body)>,
|
||||
);
|
||||
impl<RuntimeOrigin: Clone, EnsureBodyOrigin: EnsureOrigin<RuntimeOrigin>, Body: Get<BodyId>>
|
||||
TryConvert<RuntimeOrigin, MultiLocation>
|
||||
TryConvert<RuntimeOrigin, Location>
|
||||
for OriginToPluralityVoice<RuntimeOrigin, EnsureBodyOrigin, Body>
|
||||
{
|
||||
fn try_convert(o: RuntimeOrigin) -> Result<MultiLocation, RuntimeOrigin> {
|
||||
fn try_convert(o: RuntimeOrigin) -> Result<Location, RuntimeOrigin> {
|
||||
match EnsureBodyOrigin::try_origin(o) {
|
||||
Ok(_) => Ok(Junction::Plurality { id: Body::get(), part: BodyPart::Voice }.into()),
|
||||
Err(o) => Err(o),
|
||||
|
||||
@@ -30,7 +30,7 @@ use xcm_executor::traits::{QueryHandler, QueryResponseStatus};
|
||||
/// ownership of some `Interior` location of the local chain to a particular `Beneficiary`. The
|
||||
/// `AssetKind` value is not itself bounded (to avoid the issue of needing to wrap some preexisting
|
||||
/// datatype), however a converter type `AssetKindToLocatableAsset` must be provided in order to
|
||||
/// translate it into a `LocatableAsset`, which comprises both an XCM `MultiLocation` describing
|
||||
/// translate it into a `LocatableAsset`, which comprises both an XCM `Location` describing
|
||||
/// the XCM endpoint on which the asset to be paid resides and an XCM `AssetId` to identify the
|
||||
/// specific asset at that endpoint.
|
||||
///
|
||||
@@ -65,14 +65,14 @@ pub struct PayOverXcm<
|
||||
)>,
|
||||
);
|
||||
impl<
|
||||
Interior: Get<InteriorMultiLocation>,
|
||||
Interior: Get<InteriorLocation>,
|
||||
Router: SendXcm,
|
||||
Querier: QueryHandler,
|
||||
Timeout: Get<Querier::BlockNumber>,
|
||||
Beneficiary: Clone,
|
||||
AssetKind,
|
||||
AssetKindToLocatableAsset: TryConvert<AssetKind, LocatableAssetId>,
|
||||
BeneficiaryRefToLocation: for<'a> TryConvert<&'a Beneficiary, MultiLocation>,
|
||||
BeneficiaryRefToLocation: for<'a> TryConvert<&'a Beneficiary, Location>,
|
||||
> Pay
|
||||
for PayOverXcm<
|
||||
Interior,
|
||||
@@ -105,7 +105,7 @@ impl<
|
||||
let beneficiary = BeneficiaryRefToLocation::try_convert(&who)
|
||||
.map_err(|_| xcm::latest::Error::InvalidLocation)?;
|
||||
|
||||
let query_id = Querier::new_query(asset_location, Timeout::get(), Interior::get());
|
||||
let query_id = Querier::new_query(asset_location.clone(), Timeout::get(), Interior::get());
|
||||
|
||||
let message = Xcm(vec![
|
||||
DescendOrigin(Interior::get()),
|
||||
@@ -120,8 +120,7 @@ impl<
|
||||
])),
|
||||
TransferAsset {
|
||||
beneficiary,
|
||||
assets: vec![MultiAsset { id: asset_id, fun: Fungibility::Fungible(amount) }]
|
||||
.into(),
|
||||
assets: vec![Asset { id: asset_id, fun: Fungibility::Fungible(amount) }].into(),
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -195,16 +194,16 @@ pub struct LocatableAssetId {
|
||||
/// The asset's ID.
|
||||
pub asset_id: AssetId,
|
||||
/// The (relative) location in which the asset ID is meaningful.
|
||||
pub location: MultiLocation,
|
||||
pub location: Location,
|
||||
}
|
||||
|
||||
/// Adapter `struct` which implements a conversion from any `AssetKind` into a [`LocatableAssetId`]
|
||||
/// value using a fixed `Location` for the `location` field.
|
||||
pub struct FixedLocation<Location>(sp_std::marker::PhantomData<Location>);
|
||||
impl<Location: Get<MultiLocation>, AssetKind: Into<AssetId>> TryConvert<AssetKind, LocatableAssetId>
|
||||
for FixedLocation<Location>
|
||||
pub struct FixedLocation<FixedLocationValue>(sp_std::marker::PhantomData<FixedLocationValue>);
|
||||
impl<FixedLocationValue: Get<Location>, AssetKind: Into<AssetId>>
|
||||
TryConvert<AssetKind, LocatableAssetId> for FixedLocation<FixedLocationValue>
|
||||
{
|
||||
fn try_convert(value: AssetKind) -> Result<LocatableAssetId, AssetKind> {
|
||||
Ok(LocatableAssetId { asset_id: value.into(), location: Location::get() })
|
||||
Ok(LocatableAssetId { asset_id: value.into(), location: FixedLocationValue::get() })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ pub struct ProcessXcmMessage<MessageOrigin, XcmExecutor, Call>(
|
||||
PhantomData<(MessageOrigin, XcmExecutor, Call)>,
|
||||
);
|
||||
impl<
|
||||
MessageOrigin: Into<MultiLocation> + FullCodec + MaxEncodedLen + Clone + Eq + PartialEq + TypeInfo + Debug,
|
||||
MessageOrigin: Into<Location> + FullCodec + MaxEncodedLen + Clone + Eq + PartialEq + TypeInfo + Debug,
|
||||
XcmExecutor: ExecuteXcm<Call>,
|
||||
Call,
|
||||
> ProcessMessage for ProcessXcmMessage<MessageOrigin, XcmExecutor, Call>
|
||||
@@ -82,28 +82,26 @@ impl<
|
||||
|
||||
let (consumed, result) = match XcmExecutor::execute(origin.into(), pre, id, Weight::zero())
|
||||
{
|
||||
Outcome::Complete(w) => {
|
||||
Outcome::Complete { used } => {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"XCM message execution complete, used weight: {w}",
|
||||
"XCM message execution complete, used weight: {used}",
|
||||
);
|
||||
(w, Ok(true))
|
||||
(used, Ok(true))
|
||||
},
|
||||
Outcome::Incomplete(w, e) => {
|
||||
Outcome::Incomplete { used, error } => {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"XCM message execution incomplete, used weight: {w}, error: {e:?}",
|
||||
"XCM message execution incomplete, used weight: {used}, error: {error:?}",
|
||||
);
|
||||
|
||||
(w, Ok(false))
|
||||
(used, Ok(false))
|
||||
},
|
||||
// In the error-case we assume the worst case and consume all possible weight.
|
||||
Outcome::Error(e) => {
|
||||
Outcome::Error { error } => {
|
||||
log::trace!(
|
||||
target: LOG_TARGET,
|
||||
"XCM message execution error: {e:?}",
|
||||
"XCM message execution error: {error:?}",
|
||||
);
|
||||
|
||||
(required, Err(ProcessMessageError::Unsupported))
|
||||
},
|
||||
};
|
||||
|
||||
@@ -38,7 +38,7 @@ impl<Inner: SendXcm> SendXcm for WithUniqueTopic<Inner> {
|
||||
type Ticket = (Inner::Ticket, [u8; 32]);
|
||||
|
||||
fn validate(
|
||||
destination: &mut Option<MultiLocation>,
|
||||
destination: &mut Option<Location>,
|
||||
message: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Self::Ticket> {
|
||||
let mut message = message.take().ok_or(SendError::MissingArgument)?;
|
||||
@@ -82,7 +82,7 @@ impl<Inner: SendXcm, TopicSource: SourceTopic> SendXcm for WithTopicSource<Inner
|
||||
type Ticket = (Inner::Ticket, [u8; 32]);
|
||||
|
||||
fn validate(
|
||||
destination: &mut Option<MultiLocation>,
|
||||
destination: &mut Option<Location>,
|
||||
message: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Self::Ticket> {
|
||||
let mut message = message.take().ok_or(SendError::MissingArgument)?;
|
||||
|
||||
@@ -27,11 +27,11 @@ pub use xcm_executor::{
|
||||
traits::{
|
||||
AssetExchange, AssetLock, ConvertOrigin, Enact, LockError, OnResponse, TransactAsset,
|
||||
},
|
||||
Assets, Config,
|
||||
AssetsInHolding, Config,
|
||||
};
|
||||
|
||||
parameter_types! {
|
||||
pub static SubscriptionRequests: Vec<(MultiLocation, Option<(QueryId, Weight)>)> = vec![];
|
||||
pub static SubscriptionRequests: Vec<(Location, Option<(QueryId, Weight)>)> = vec![];
|
||||
pub static MaxAssetsIntoHolding: u32 = 4;
|
||||
}
|
||||
|
||||
@@ -39,39 +39,39 @@ pub struct TestSubscriptionService;
|
||||
|
||||
impl VersionChangeNotifier for TestSubscriptionService {
|
||||
fn start(
|
||||
location: &MultiLocation,
|
||||
location: &Location,
|
||||
query_id: QueryId,
|
||||
max_weight: Weight,
|
||||
_context: &XcmContext,
|
||||
) -> XcmResult {
|
||||
let mut r = SubscriptionRequests::get();
|
||||
r.push((*location, Some((query_id, max_weight))));
|
||||
r.push((location.clone(), Some((query_id, max_weight))));
|
||||
SubscriptionRequests::set(r);
|
||||
Ok(())
|
||||
}
|
||||
fn stop(location: &MultiLocation, _context: &XcmContext) -> XcmResult {
|
||||
fn stop(location: &Location, _context: &XcmContext) -> XcmResult {
|
||||
let mut r = SubscriptionRequests::get();
|
||||
r.retain(|(l, _q)| l != location);
|
||||
r.push((*location, None));
|
||||
r.push((location.clone(), None));
|
||||
SubscriptionRequests::set(r);
|
||||
Ok(())
|
||||
}
|
||||
fn is_subscribed(location: &MultiLocation) -> bool {
|
||||
fn is_subscribed(location: &Location) -> bool {
|
||||
let r = SubscriptionRequests::get();
|
||||
r.iter().any(|(l, q)| l == location && q.is_some())
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub static TrappedAssets: Vec<(MultiLocation, MultiAssets)> = vec![];
|
||||
pub static TrappedAssets: Vec<(Location, Assets)> = vec![];
|
||||
}
|
||||
|
||||
pub struct TestAssetTrap;
|
||||
|
||||
impl DropAssets for TestAssetTrap {
|
||||
fn drop_assets(origin: &MultiLocation, assets: Assets, _context: &XcmContext) -> Weight {
|
||||
let mut t: Vec<(MultiLocation, MultiAssets)> = TrappedAssets::get();
|
||||
t.push((*origin, assets.into()));
|
||||
fn drop_assets(origin: &Location, assets: AssetsInHolding, _context: &XcmContext) -> Weight {
|
||||
let mut t: Vec<(Location, Assets)> = TrappedAssets::get();
|
||||
t.push((origin.clone(), assets.into()));
|
||||
TrappedAssets::set(t);
|
||||
Weight::from_parts(5, 5)
|
||||
}
|
||||
@@ -79,13 +79,13 @@ impl DropAssets for TestAssetTrap {
|
||||
|
||||
impl ClaimAssets for TestAssetTrap {
|
||||
fn claim_assets(
|
||||
origin: &MultiLocation,
|
||||
ticket: &MultiLocation,
|
||||
what: &MultiAssets,
|
||||
origin: &Location,
|
||||
ticket: &Location,
|
||||
what: &Assets,
|
||||
_context: &XcmContext,
|
||||
) -> bool {
|
||||
let mut t: Vec<(MultiLocation, MultiAssets)> = TrappedAssets::get();
|
||||
if let (0, X1(GeneralIndex(i))) = (ticket.parents, &ticket.interior) {
|
||||
let mut t: Vec<(Location, Assets)> = TrappedAssets::get();
|
||||
if let (0, [GeneralIndex(i)]) = ticket.unpack() {
|
||||
if let Some((l, a)) = t.get(*i as usize) {
|
||||
if l == origin && a == what {
|
||||
t.swap_remove(*i as usize);
|
||||
@@ -102,11 +102,11 @@ pub struct TestAssetExchanger;
|
||||
|
||||
impl AssetExchange for TestAssetExchanger {
|
||||
fn exchange_asset(
|
||||
_origin: Option<&MultiLocation>,
|
||||
_give: Assets,
|
||||
want: &MultiAssets,
|
||||
_origin: Option<&Location>,
|
||||
_give: AssetsInHolding,
|
||||
want: &Assets,
|
||||
_maximal: bool,
|
||||
) -> Result<Assets, Assets> {
|
||||
) -> Result<AssetsInHolding, AssetsInHolding> {
|
||||
Ok(want.clone().into())
|
||||
}
|
||||
}
|
||||
@@ -135,17 +135,17 @@ impl PalletsInfoAccess for TestPalletsInfo {
|
||||
}
|
||||
|
||||
pub struct TestUniversalAliases;
|
||||
impl Contains<(MultiLocation, Junction)> for TestUniversalAliases {
|
||||
fn contains(aliases: &(MultiLocation, Junction)) -> bool {
|
||||
impl Contains<(Location, Junction)> for TestUniversalAliases {
|
||||
fn contains(aliases: &(Location, Junction)) -> bool {
|
||||
&aliases.0 == &Here.into_location() && &aliases.1 == &GlobalConsensus(ByGenesis([0; 32]))
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub static LockedAssets: Vec<(MultiLocation, MultiAsset)> = vec![];
|
||||
pub static LockedAssets: Vec<(Location, Asset)> = vec![];
|
||||
}
|
||||
|
||||
pub struct TestLockTicket(MultiLocation, MultiAsset);
|
||||
pub struct TestLockTicket(Location, Asset);
|
||||
impl Enact for TestLockTicket {
|
||||
fn enact(self) -> Result<(), LockError> {
|
||||
let mut locked_assets = LockedAssets::get();
|
||||
@@ -154,7 +154,7 @@ impl Enact for TestLockTicket {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
pub struct TestUnlockTicket(MultiLocation, MultiAsset);
|
||||
pub struct TestUnlockTicket(Location, Asset);
|
||||
impl Enact for TestUnlockTicket {
|
||||
fn enact(self) -> Result<(), LockError> {
|
||||
let mut locked_assets = LockedAssets::get();
|
||||
@@ -183,33 +183,33 @@ impl AssetLock for TestAssetLocker {
|
||||
type ReduceTicket = TestReduceTicket;
|
||||
|
||||
fn prepare_lock(
|
||||
unlocker: MultiLocation,
|
||||
asset: MultiAsset,
|
||||
_owner: MultiLocation,
|
||||
unlocker: Location,
|
||||
asset: Asset,
|
||||
_owner: Location,
|
||||
) -> Result<TestLockTicket, LockError> {
|
||||
Ok(TestLockTicket(unlocker, asset))
|
||||
}
|
||||
|
||||
fn prepare_unlock(
|
||||
unlocker: MultiLocation,
|
||||
asset: MultiAsset,
|
||||
_owner: MultiLocation,
|
||||
unlocker: Location,
|
||||
asset: Asset,
|
||||
_owner: Location,
|
||||
) -> Result<TestUnlockTicket, LockError> {
|
||||
Ok(TestUnlockTicket(unlocker, asset))
|
||||
}
|
||||
|
||||
fn note_unlockable(
|
||||
_locker: MultiLocation,
|
||||
_asset: MultiAsset,
|
||||
_owner: MultiLocation,
|
||||
_locker: Location,
|
||||
_asset: Asset,
|
||||
_owner: Location,
|
||||
) -> Result<(), LockError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prepare_reduce_unlockable(
|
||||
_locker: MultiLocation,
|
||||
_asset: MultiAsset,
|
||||
_owner: MultiLocation,
|
||||
_locker: Location,
|
||||
_asset: Asset,
|
||||
_owner: Location,
|
||||
) -> Result<TestReduceTicket, LockError> {
|
||||
Ok(TestReduceTicket)
|
||||
}
|
||||
|
||||
@@ -66,20 +66,25 @@ fn alias_origin_should_work() {
|
||||
]);
|
||||
|
||||
let message = Xcm(vec![AliasOrigin((AccountId32 { network: None, id: [0; 32] }).into())]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(Parachain(1), AccountId32 { network: None, id: [0; 32] }),
|
||||
message.clone(),
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NoPermission }
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::NoPermission));
|
||||
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(Parent, Parachain(1), AccountId32 { network: None, id: [0; 32] }),
|
||||
message.clone(),
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
}
|
||||
|
||||
@@ -32,10 +32,15 @@ fn exchange_asset_should_work() {
|
||||
maximal: true,
|
||||
},
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r =
|
||||
XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, Weight::from_parts(50, 50));
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(40, 40)));
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(40, 40) });
|
||||
assert_eq!(asset_list(Parent), vec![(Here, 100u128).into(), (Parent, 950u128).into()]);
|
||||
assert_eq!(exchange_assets(), vec![(Parent, 50u128).into()].into());
|
||||
}
|
||||
@@ -56,10 +61,15 @@ fn exchange_asset_without_maximal_should_work() {
|
||||
maximal: false,
|
||||
},
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r =
|
||||
XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, Weight::from_parts(50, 50));
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(40, 40)));
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(40, 40) });
|
||||
assert_eq!(asset_list(Parent), vec![(Here, 50u128).into(), (Parent, 950u128).into()]);
|
||||
assert_eq!(exchange_assets(), vec![(Here, 50u128).into(), (Parent, 50u128).into()].into());
|
||||
}
|
||||
@@ -80,10 +90,18 @@ fn exchange_asset_should_fail_when_no_deal_possible() {
|
||||
maximal: false,
|
||||
},
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r =
|
||||
XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, Weight::from_parts(50, 50));
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(40, 40), XcmError::NoDeal));
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(40, 40), error: XcmError::NoDeal }
|
||||
);
|
||||
assert_eq!(asset_list(Parent), vec![(Parent, 1000u128).into()]);
|
||||
assert_eq!(exchange_assets(), vec![(Here, 100u128).into()].into());
|
||||
}
|
||||
@@ -100,32 +118,39 @@ fn paying_reserve_deposit_should_work() {
|
||||
BuyExecution { fees, weight_limit: Limited(Weight::from_parts(30, 30)) },
|
||||
DepositAsset { assets: AllCounted(1).into(), beneficiary: Here.into() },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(50, 50);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(30, 30)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(30, 30) });
|
||||
assert_eq!(asset_list(Here), vec![(Parent, 40u128).into()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transfer_should_work() {
|
||||
// we'll let them have message execution for free.
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into()]);
|
||||
// Child parachain #1 owns 1000 tokens held by us in reserve.
|
||||
add_asset(Parachain(1), (Here, 1000));
|
||||
// They want to transfer 100 of them to their sibling parachain #2
|
||||
let message = Xcm(vec![TransferAsset {
|
||||
assets: (Here, 100u128).into(),
|
||||
beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(),
|
||||
beneficiary: [AccountIndex64 { index: 3, network: None }].into(),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
assert_eq!(
|
||||
asset_list(AccountIndex64 { index: 3, network: None }),
|
||||
vec![(Here, 100u128).into()]
|
||||
@@ -136,27 +161,31 @@ fn transfer_should_work() {
|
||||
|
||||
#[test]
|
||||
fn reserve_transfer_should_work() {
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into()]);
|
||||
// Child parachain #1 owns 1000 tokens held by us in reserve.
|
||||
add_asset(Parachain(1), (Here, 1000));
|
||||
// The remote account owned by gav.
|
||||
let three: MultiLocation = X1(AccountIndex64 { index: 3, network: None }).into();
|
||||
let three: Location = [AccountIndex64 { index: 3, network: None }].into();
|
||||
|
||||
// They want to transfer 100 of our native asset from sovereign account of parachain #1 into #2
|
||||
// and let them know to hand it to account #3.
|
||||
let message = Xcm(vec![TransferReserveAsset {
|
||||
assets: (Here, 100u128).into(),
|
||||
dest: Parachain(2).into(),
|
||||
xcm: Xcm::<()>(vec![DepositAsset { assets: AllCounted(1).into(), beneficiary: three }]),
|
||||
xcm: Xcm::<()>(vec![DepositAsset {
|
||||
assets: AllCounted(1).into(),
|
||||
beneficiary: three.clone(),
|
||||
}]),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
|
||||
let expected_msg = Xcm::<()>(vec![
|
||||
ReserveAssetDeposited((Parent, 100u128).into()),
|
||||
@@ -171,7 +200,7 @@ fn reserve_transfer_should_work() {
|
||||
#[test]
|
||||
fn burn_should_work() {
|
||||
// we'll let them have message execution for free.
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into()]);
|
||||
// Child parachain #1 owns 1000 tokens held by us in reserve.
|
||||
add_asset(Parachain(1), (Here, 1000));
|
||||
// They want to burn 100 of them
|
||||
@@ -180,14 +209,15 @@ fn burn_should_work() {
|
||||
BurnAsset((Here, 100u128).into()),
|
||||
DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Parachain(1).into() },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(30, 30)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(30, 30) });
|
||||
assert_eq!(asset_list(Parachain(1)), vec![(Here, 900u128).into()]);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
|
||||
@@ -197,14 +227,15 @@ fn burn_should_work() {
|
||||
BurnAsset((Here, 1000u128).into()),
|
||||
DepositAsset { assets: Wild(AllCounted(1)), beneficiary: Parachain(1).into() },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(30, 30)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(30, 30) });
|
||||
assert_eq!(asset_list(Parachain(1)), vec![]);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
}
|
||||
@@ -212,7 +243,7 @@ fn burn_should_work() {
|
||||
#[test]
|
||||
fn basic_asset_trap_should_work() {
|
||||
// we'll let them have message execution for free.
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into(), X1(Parachain(2)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into(), [Parachain(2)].into()]);
|
||||
|
||||
// Child parachain #1 owns 1000 tokens held by us in reserve.
|
||||
add_asset(Parachain(1), (Here, 1000));
|
||||
@@ -224,14 +255,15 @@ fn basic_asset_trap_should_work() {
|
||||
beneficiary: AccountIndex64 { index: 3, network: None }.into(),
|
||||
},
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(20, 20),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(25, 25)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(25, 25) });
|
||||
assert_eq!(asset_list(Parachain(1)), vec![(Here, 900u128).into()]);
|
||||
assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![]);
|
||||
|
||||
@@ -243,15 +275,19 @@ fn basic_asset_trap_should_work() {
|
||||
beneficiary: AccountIndex64 { index: 3, network: None }.into(),
|
||||
},
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let old_trapped_assets = TrappedAssets::get();
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(20, 20),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::UnknownClaim }
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::UnknownClaim));
|
||||
assert_eq!(asset_list(Parachain(1)), vec![(Here, 900u128).into()]);
|
||||
assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![]);
|
||||
assert_eq!(old_trapped_assets, TrappedAssets::get());
|
||||
@@ -264,15 +300,19 @@ fn basic_asset_trap_should_work() {
|
||||
beneficiary: AccountIndex64 { index: 3, network: None }.into(),
|
||||
},
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let old_trapped_assets = TrappedAssets::get();
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(2),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(20, 20),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::UnknownClaim }
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::UnknownClaim));
|
||||
assert_eq!(asset_list(Parachain(1)), vec![(Here, 900u128).into()]);
|
||||
assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![]);
|
||||
assert_eq!(old_trapped_assets, TrappedAssets::get());
|
||||
@@ -285,15 +325,19 @@ fn basic_asset_trap_should_work() {
|
||||
beneficiary: AccountIndex64 { index: 3, network: None }.into(),
|
||||
},
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let old_trapped_assets = TrappedAssets::get();
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(20, 20),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::UnknownClaim }
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::UnknownClaim));
|
||||
assert_eq!(asset_list(Parachain(1)), vec![(Here, 900u128).into()]);
|
||||
assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![]);
|
||||
assert_eq!(old_trapped_assets, TrappedAssets::get());
|
||||
@@ -305,14 +349,15 @@ fn basic_asset_trap_should_work() {
|
||||
beneficiary: AccountIndex64 { index: 3, network: None }.into(),
|
||||
},
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(20, 20),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(20, 20)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(20, 20) });
|
||||
assert_eq!(asset_list(Parachain(1)), vec![(Here, 900u128).into()]);
|
||||
assert_eq!(
|
||||
asset_list(AccountIndex64 { index: 3, network: None }),
|
||||
@@ -327,141 +372,168 @@ fn basic_asset_trap_should_work() {
|
||||
beneficiary: AccountIndex64 { index: 3, network: None }.into(),
|
||||
},
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(20, 20),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::UnknownClaim }
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::UnknownClaim));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_assets_limit_should_work() {
|
||||
// we'll let them have message execution for free.
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into()]);
|
||||
// Child parachain #1 owns 1000 tokens held by us in reserve.
|
||||
add_asset(Parachain(1), ([1u8; 32], 1000u128));
|
||||
add_asset(Parachain(1), ([2u8; 32], 1000u128));
|
||||
add_asset(Parachain(1), ([3u8; 32], 1000u128));
|
||||
add_asset(Parachain(1), ([4u8; 32], 1000u128));
|
||||
add_asset(Parachain(1), ([5u8; 32], 1000u128));
|
||||
add_asset(Parachain(1), ([6u8; 32], 1000u128));
|
||||
add_asset(Parachain(1), ([7u8; 32], 1000u128));
|
||||
add_asset(Parachain(1), ([8u8; 32], 1000u128));
|
||||
add_asset(Parachain(1), ([9u8; 32], 1000u128));
|
||||
add_asset(Parachain(1), (Junctions::from([GeneralIndex(0)]), 1000u128));
|
||||
add_asset(Parachain(1), (Junctions::from([GeneralIndex(1)]), 1000u128));
|
||||
add_asset(Parachain(1), (Junctions::from([GeneralIndex(2)]), 1000u128));
|
||||
add_asset(Parachain(1), (Junctions::from([GeneralIndex(3)]), 1000u128));
|
||||
add_asset(Parachain(1), (Junctions::from([GeneralIndex(4)]), 1000u128));
|
||||
add_asset(Parachain(1), (Junctions::from([GeneralIndex(5)]), 1000u128));
|
||||
add_asset(Parachain(1), (Junctions::from([GeneralIndex(6)]), 1000u128));
|
||||
add_asset(Parachain(1), (Junctions::from([GeneralIndex(7)]), 1000u128));
|
||||
add_asset(Parachain(1), (Junctions::from([GeneralIndex(8)]), 1000u128));
|
||||
|
||||
// Attempt to withdraw 8 (=2x4)different assets. This will succeed.
|
||||
let message = Xcm(vec![
|
||||
WithdrawAsset(([1u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([2u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([3u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([4u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([5u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([6u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([7u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([8u8; 32], 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(0)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(1)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(2)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(3)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(4)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(5)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(6)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(7)]), 100u128).into()),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(100, 100),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(85, 85)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(85, 85) });
|
||||
|
||||
// Attempt to withdraw 9 different assets will fail.
|
||||
let message = Xcm(vec![
|
||||
WithdrawAsset(([1u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([2u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([3u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([4u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([5u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([6u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([7u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([8u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([9u8; 32], 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(0)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(1)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(2)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(3)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(4)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(5)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(6)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(7)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(8)]), 100u128).into()),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(100, 100),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete {
|
||||
used: Weight::from_parts(95, 95),
|
||||
error: XcmError::HoldingWouldOverflow
|
||||
}
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(95, 95), XcmError::HoldingWouldOverflow));
|
||||
|
||||
// Attempt to withdraw 4 different assets and then the same 4 and then a different 4 will
|
||||
// succeed.
|
||||
let message = Xcm(vec![
|
||||
WithdrawAsset(([1u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([2u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([3u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([4u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([1u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([2u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([3u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([4u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([5u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([6u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([7u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([8u8; 32], 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(0)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(1)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(2)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(3)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(0)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(1)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(2)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(3)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(4)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(5)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(6)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(7)]), 100u128).into()),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(200, 200),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(125, 125)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(125, 125) });
|
||||
|
||||
// Attempt to withdraw 4 different assets and then a different 4 and then the same 4 will fail.
|
||||
let message = Xcm(vec![
|
||||
WithdrawAsset(([1u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([2u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([3u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([4u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([5u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([6u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([7u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([8u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([1u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([2u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([3u8; 32], 100u128).into()),
|
||||
WithdrawAsset(([4u8; 32], 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(0)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(1)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(2)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(3)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(4)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(5)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(6)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(7)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(0)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(1)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(2)]), 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(3)]), 100u128).into()),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(200, 200),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete {
|
||||
used: Weight::from_parts(95, 95),
|
||||
error: XcmError::HoldingWouldOverflow
|
||||
}
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(95, 95), XcmError::HoldingWouldOverflow));
|
||||
|
||||
// Attempt to withdraw 4 different assets and then a different 4 and then the same 4 will fail.
|
||||
let message = Xcm(vec![
|
||||
WithdrawAsset(MultiAssets::from(vec![
|
||||
([1u8; 32], 100u128).into(),
|
||||
([2u8; 32], 100u128).into(),
|
||||
([3u8; 32], 100u128).into(),
|
||||
([4u8; 32], 100u128).into(),
|
||||
([5u8; 32], 100u128).into(),
|
||||
([6u8; 32], 100u128).into(),
|
||||
([7u8; 32], 100u128).into(),
|
||||
([8u8; 32], 100u128).into(),
|
||||
WithdrawAsset(Assets::from(vec![
|
||||
(Junctions::from([GeneralIndex(0)]), 100u128).into(),
|
||||
(Junctions::from([GeneralIndex(1)]), 100u128).into(),
|
||||
(Junctions::from([GeneralIndex(2)]), 100u128).into(),
|
||||
(Junctions::from([GeneralIndex(3)]), 100u128).into(),
|
||||
(Junctions::from([GeneralIndex(4)]), 100u128).into(),
|
||||
(Junctions::from([GeneralIndex(5)]), 100u128).into(),
|
||||
(Junctions::from([GeneralIndex(6)]), 100u128).into(),
|
||||
(Junctions::from([GeneralIndex(7)]), 100u128).into(),
|
||||
])),
|
||||
WithdrawAsset(([1u8; 32], 100u128).into()),
|
||||
WithdrawAsset((Junctions::from([GeneralIndex(0)]), 100u128).into()),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(200, 200),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete {
|
||||
used: Weight::from_parts(25, 25),
|
||||
error: XcmError::HoldingWouldOverflow
|
||||
}
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(25, 25), XcmError::HoldingWouldOverflow));
|
||||
}
|
||||
|
||||
@@ -27,14 +27,8 @@ fn basic_setup_works() {
|
||||
assert_eq!(to_account(Parachain(50)), Ok(1050));
|
||||
assert_eq!(to_account((Parent, Parachain(1))), Ok(2001));
|
||||
assert_eq!(to_account((Parent, Parachain(50))), Ok(2050));
|
||||
assert_eq!(
|
||||
to_account(MultiLocation::new(0, X1(AccountIndex64 { index: 1, network: None }))),
|
||||
Ok(1),
|
||||
);
|
||||
assert_eq!(
|
||||
to_account(MultiLocation::new(0, X1(AccountIndex64 { index: 42, network: None }))),
|
||||
Ok(42),
|
||||
);
|
||||
assert_eq!(to_account(Location::new(0, [AccountIndex64 { index: 1, network: None }])), Ok(1),);
|
||||
assert_eq!(to_account(Location::new(0, [AccountIndex64 { index: 42, network: None }])), Ok(42),);
|
||||
assert_eq!(to_account(Here), Ok(3000));
|
||||
}
|
||||
|
||||
@@ -65,7 +59,7 @@ fn code_registers_should_work() {
|
||||
SetErrorHandler(Xcm(vec![
|
||||
TransferAsset {
|
||||
assets: (Here, 2u128).into(),
|
||||
beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(),
|
||||
beneficiary: [AccountIndex64 { index: 3, network: None }].into(),
|
||||
},
|
||||
// It was handled fine.
|
||||
ClearError,
|
||||
@@ -73,33 +67,45 @@ fn code_registers_should_work() {
|
||||
// Set the appendix - this will always fire.
|
||||
SetAppendix(Xcm(vec![TransferAsset {
|
||||
assets: (Here, 4u128).into(),
|
||||
beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(),
|
||||
beneficiary: [AccountIndex64 { index: 3, network: None }].into(),
|
||||
}])),
|
||||
// First xfer always works ok
|
||||
TransferAsset {
|
||||
assets: (Here, 1u128).into(),
|
||||
beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(),
|
||||
beneficiary: [AccountIndex64 { index: 3, network: None }].into(),
|
||||
},
|
||||
// Second xfer results in error on the second message - our error handler will fire.
|
||||
TransferAsset {
|
||||
assets: (Here, 8u128).into(),
|
||||
beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(),
|
||||
beneficiary: [AccountIndex64 { index: 3, network: None }].into(),
|
||||
},
|
||||
]);
|
||||
// Weight limit of 70 is needed.
|
||||
let limit = <TestConfig as Config>::Weigher::weight(&mut message).unwrap();
|
||||
assert_eq!(limit, Weight::from_parts(70, 70));
|
||||
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Here, message.clone(), hash, limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(50, 50))); // We don't pay the 20 weight for the error handler.
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Here,
|
||||
message.clone(),
|
||||
&mut hash,
|
||||
limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(50, 50) }); // We don't pay the 20 weight for the error handler.
|
||||
assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![(Here, 13u128).into()]);
|
||||
assert_eq!(asset_list(Here), vec![(Here, 8u128).into()]);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Here, message, hash, limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(70, 70))); // We pay the full weight here.
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Here,
|
||||
message,
|
||||
&mut hash,
|
||||
limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(70, 70) }); // We pay the full weight here.
|
||||
assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![(Here, 20u128).into()]);
|
||||
assert_eq!(asset_list(Here), vec![(Here, 1u128).into()]);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
use super::*;
|
||||
|
||||
parameter_types! {
|
||||
pub UniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(1));
|
||||
pub RemoteUniversalLocation: Junctions = X2(GlobalConsensus(Remote::get()), Parachain(1));
|
||||
pub RemoteNetwork: MultiLocation = AncestorThen(2, GlobalConsensus(Remote::get())).into();
|
||||
pub UniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(1)].into();
|
||||
pub RemoteUniversalLocation: Junctions = [GlobalConsensus(Remote::get()), Parachain(1)].into();
|
||||
pub RemoteNetwork: Location = AncestorThen(2, GlobalConsensus(Remote::get())).into();
|
||||
}
|
||||
type TheBridge =
|
||||
TestBridge<BridgeBlobDispatcher<TestRemoteIncomingRouter, RemoteUniversalLocation, ()>>;
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
use super::*;
|
||||
|
||||
parameter_types! {
|
||||
pub UniversalLocation: Junctions = X1(GlobalConsensus(Local::get()));
|
||||
pub RemoteUniversalLocation: Junctions = X1(GlobalConsensus(Remote::get()));
|
||||
pub RemoteNetwork: MultiLocation = AncestorThen(1, GlobalConsensus(Remote::get())).into();
|
||||
pub UniversalLocation: Junctions = [GlobalConsensus(Local::get())].into();
|
||||
pub RemoteUniversalLocation: Junctions = [GlobalConsensus(Remote::get())].into();
|
||||
pub RemoteNetwork: Location = AncestorThen(1, GlobalConsensus(Remote::get())).into();
|
||||
}
|
||||
type TheBridge =
|
||||
TestBridge<BridgeBlobDispatcher<TestRemoteIncomingRouter, RemoteUniversalLocation, ()>>;
|
||||
|
||||
@@ -37,7 +37,7 @@ mod remote_relay_relay;
|
||||
parameter_types! {
|
||||
pub Local: NetworkId = ByGenesis([0; 32]);
|
||||
pub Remote: NetworkId = ByGenesis([1; 32]);
|
||||
pub Price: MultiAssets = MultiAssets::from((Here, 100u128));
|
||||
pub Price: Assets = Assets::from((Here, 100u128));
|
||||
pub static UsingTopic: bool = false;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ impl<R: SendXcm> SendXcm for TestTopic<R> {
|
||||
}
|
||||
}
|
||||
fn validate(
|
||||
destination: &mut Option<MultiLocation>,
|
||||
destination: &mut Option<Location>,
|
||||
message: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Self::Ticket> {
|
||||
Ok(if UsingTopic::get() {
|
||||
@@ -120,26 +120,26 @@ impl<D: DispatchBlob> HaulBlob for TestBridge<D> {
|
||||
}
|
||||
|
||||
std::thread_local! {
|
||||
static REMOTE_INCOMING_XCM: RefCell<Vec<(MultiLocation, Xcm<()>)>> = RefCell::new(Vec::new());
|
||||
static REMOTE_INCOMING_XCM: RefCell<Vec<(Location, Xcm<()>)>> = RefCell::new(Vec::new());
|
||||
}
|
||||
struct TestRemoteIncomingRouter;
|
||||
impl SendXcm for TestRemoteIncomingRouter {
|
||||
type Ticket = (MultiLocation, Xcm<()>);
|
||||
type Ticket = (Location, Xcm<()>);
|
||||
fn validate(
|
||||
dest: &mut Option<MultiLocation>,
|
||||
dest: &mut Option<Location>,
|
||||
msg: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<(MultiLocation, Xcm<()>)> {
|
||||
) -> SendResult<(Location, Xcm<()>)> {
|
||||
let pair = (dest.take().unwrap(), msg.take().unwrap());
|
||||
Ok((pair, MultiAssets::new()))
|
||||
Ok((pair, Assets::new()))
|
||||
}
|
||||
fn deliver(pair: (MultiLocation, Xcm<()>)) -> Result<XcmHash, SendError> {
|
||||
fn deliver(pair: (Location, Xcm<()>)) -> Result<XcmHash, SendError> {
|
||||
let hash = fake_id();
|
||||
REMOTE_INCOMING_XCM.with(|q| q.borrow_mut().push(pair));
|
||||
Ok(hash)
|
||||
}
|
||||
}
|
||||
|
||||
fn take_received_remote_messages() -> Vec<(MultiLocation, Xcm<()>)> {
|
||||
fn take_received_remote_messages() -> Vec<(Location, Xcm<()>)> {
|
||||
REMOTE_INCOMING_XCM.with(|r| r.replace(vec![]))
|
||||
}
|
||||
|
||||
@@ -152,18 +152,18 @@ struct UnpaidExecutingRouter<Local, Remote, RemoteExporter>(
|
||||
fn price<RemoteExporter: ExportXcm>(
|
||||
n: NetworkId,
|
||||
c: u32,
|
||||
s: &InteriorMultiLocation,
|
||||
d: &InteriorMultiLocation,
|
||||
s: &InteriorLocation,
|
||||
d: &InteriorLocation,
|
||||
m: &Xcm<()>,
|
||||
) -> Result<MultiAssets, SendError> {
|
||||
Ok(validate_export::<RemoteExporter>(n, c, *s, *d, m.clone())?.1)
|
||||
) -> Result<Assets, SendError> {
|
||||
Ok(validate_export::<RemoteExporter>(n, c, s.clone(), d.clone(), m.clone())?.1)
|
||||
}
|
||||
|
||||
fn deliver<RemoteExporter: ExportXcm>(
|
||||
n: NetworkId,
|
||||
c: u32,
|
||||
s: InteriorMultiLocation,
|
||||
d: InteriorMultiLocation,
|
||||
s: InteriorLocation,
|
||||
d: InteriorLocation,
|
||||
m: Xcm<()>,
|
||||
) -> Result<XcmHash, SendError> {
|
||||
export_xcm::<RemoteExporter>(n, c, s, d, m).map(|(hash, _)| hash)
|
||||
@@ -189,7 +189,7 @@ impl<Local: Get<Junctions>, Remote: Get<Junctions>, RemoteExporter: ExportXcm> S
|
||||
type Ticket = Xcm<()>;
|
||||
|
||||
fn validate(
|
||||
destination: &mut Option<MultiLocation>,
|
||||
destination: &mut Option<Location>,
|
||||
message: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Xcm<()>> {
|
||||
let expect_dest = Remote::get().relative_to(&Local::get());
|
||||
@@ -197,7 +197,7 @@ impl<Local: Get<Junctions>, Remote: Get<Junctions>, RemoteExporter: ExportXcm> S
|
||||
return Err(NotApplicable)
|
||||
}
|
||||
let message = message.take().ok_or(MissingArgument)?;
|
||||
Ok((message, MultiAssets::new()))
|
||||
Ok((message, Assets::new()))
|
||||
}
|
||||
|
||||
fn deliver(message: Xcm<()>) -> Result<XcmHash, SendError> {
|
||||
@@ -206,7 +206,7 @@ impl<Local: Get<Junctions>, Remote: Get<Junctions>, RemoteExporter: ExportXcm> S
|
||||
// though it is `Remote`.
|
||||
ExecutorUniversalLocation::set(Remote::get());
|
||||
let origin = Local::get().relative_to(&Remote::get());
|
||||
AllowUnpaidFrom::set(vec![origin]);
|
||||
AllowUnpaidFrom::set(vec![origin.clone()]);
|
||||
set_exporter_override(price::<RemoteExporter>, deliver::<RemoteExporter>);
|
||||
// The we execute it:
|
||||
let mut id = fake_id();
|
||||
@@ -222,9 +222,9 @@ impl<Local: Get<Junctions>, Remote: Get<Junctions>, RemoteExporter: ExportXcm> S
|
||||
let entry = LogEntry { local, remote, id, message, outcome: outcome.clone(), paid: false };
|
||||
RoutingLog::mutate(|l| l.push(entry));
|
||||
match outcome {
|
||||
Outcome::Complete(..) => Ok(id),
|
||||
Outcome::Incomplete(..) => Err(Transport("Error executing")),
|
||||
Outcome::Error(..) => Err(Transport("Unable to execute")),
|
||||
Outcome::Complete { .. } => Ok(id),
|
||||
Outcome::Incomplete { .. } => Err(Transport("Error executing")),
|
||||
Outcome::Error { .. } => Err(Transport("Unable to execute")),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -239,7 +239,7 @@ impl<Local: Get<Junctions>, Remote: Get<Junctions>, RemoteExporter: ExportXcm> S
|
||||
type Ticket = Xcm<()>;
|
||||
|
||||
fn validate(
|
||||
destination: &mut Option<MultiLocation>,
|
||||
destination: &mut Option<Location>,
|
||||
message: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Xcm<()>> {
|
||||
let expect_dest = Remote::get().relative_to(&Local::get());
|
||||
@@ -247,7 +247,7 @@ impl<Local: Get<Junctions>, Remote: Get<Junctions>, RemoteExporter: ExportXcm> S
|
||||
return Err(NotApplicable)
|
||||
}
|
||||
let message = message.take().ok_or(MissingArgument)?;
|
||||
Ok((message, MultiAssets::new()))
|
||||
Ok((message, Assets::new()))
|
||||
}
|
||||
|
||||
fn deliver(message: Xcm<()>) -> Result<XcmHash, SendError> {
|
||||
@@ -256,7 +256,7 @@ impl<Local: Get<Junctions>, Remote: Get<Junctions>, RemoteExporter: ExportXcm> S
|
||||
// though it is `Remote`.
|
||||
ExecutorUniversalLocation::set(Remote::get());
|
||||
let origin = Local::get().relative_to(&Remote::get());
|
||||
AllowPaidFrom::set(vec![origin]);
|
||||
AllowPaidFrom::set(vec![origin.clone()]);
|
||||
set_exporter_override(price::<RemoteExporter>, deliver::<RemoteExporter>);
|
||||
// Then we execute it:
|
||||
let mut id = fake_id();
|
||||
@@ -272,9 +272,9 @@ impl<Local: Get<Junctions>, Remote: Get<Junctions>, RemoteExporter: ExportXcm> S
|
||||
let entry = LogEntry { local, remote, id, message, outcome: outcome.clone(), paid: true };
|
||||
RoutingLog::mutate(|l| l.push(entry));
|
||||
match outcome {
|
||||
Outcome::Complete(..) => Ok(id),
|
||||
Outcome::Incomplete(..) => Err(Transport("Error executing")),
|
||||
Outcome::Error(..) => Err(Transport("Unable to execute")),
|
||||
Outcome::Complete { .. } => Ok(id),
|
||||
Outcome::Incomplete { .. } => Err(Transport("Error executing")),
|
||||
Outcome::Error { .. } => Err(Transport("Unable to execute")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,15 +27,15 @@ parameter_types! {
|
||||
// 100 to use the bridge (export) and 80 for the remote execution weight (4 instructions x (10 +
|
||||
// 10) weight each).
|
||||
pub SendOverBridgePrice: u128 = 180u128 + if UsingTopic::get() { 20 } else { 0 };
|
||||
pub UniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(100));
|
||||
pub RelayUniversalLocation: Junctions = X1(GlobalConsensus(Local::get()));
|
||||
pub RemoteUniversalLocation: Junctions = X1(GlobalConsensus(Remote::get()));
|
||||
pub RemoteNetwork: MultiLocation = AncestorThen(1, GlobalConsensus(Remote::get())).into();
|
||||
pub UniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(100)].into();
|
||||
pub RelayUniversalLocation: Junctions = [GlobalConsensus(Local::get())].into();
|
||||
pub RemoteUniversalLocation: Junctions = [GlobalConsensus(Remote::get())].into();
|
||||
pub RemoteNetwork: Location = AncestorThen(1, GlobalConsensus(Remote::get())).into();
|
||||
pub BridgeTable: Vec<NetworkExportTableItem> = vec![
|
||||
NetworkExportTableItem::new(
|
||||
Remote::get(),
|
||||
None,
|
||||
MultiLocation::parent(),
|
||||
Location::parent(),
|
||||
Some((Parent, SendOverBridgePrice::get()).into())
|
||||
)
|
||||
];
|
||||
@@ -64,7 +64,7 @@ type LocalRouter = TestTopic<(LocalInnerRouter, LocalBridgeRouter)>;
|
||||
#[test]
|
||||
fn sending_to_bridged_chain_works() {
|
||||
maybe_with_topic(|| {
|
||||
let dest: MultiLocation = (Parent, Parent, Remote::get()).into();
|
||||
let dest: Location = (Parent, Parent, Remote::get()).into();
|
||||
|
||||
// Initialize the local relay so that our parachain has funds to pay for export.
|
||||
clear_assets(Parachain(100));
|
||||
@@ -99,7 +99,7 @@ fn sending_to_bridged_chain_works() {
|
||||
message: xcm_with_topic(
|
||||
maybe_forward_id_for(&[0; 32]),
|
||||
vec![
|
||||
WithdrawAsset(MultiAsset::from((Here, price)).into()),
|
||||
WithdrawAsset(Asset::from((Here, price)).into()),
|
||||
BuyExecution { fees: (Here, price).into(), weight_limit: Unlimited },
|
||||
ExportMessage {
|
||||
network: ByGenesis([1; 32]),
|
||||
@@ -109,7 +109,7 @@ fn sending_to_bridged_chain_works() {
|
||||
DepositAsset { assets: Wild(All), beneficiary: Parachain(100).into() },
|
||||
],
|
||||
),
|
||||
outcome: Outcome::Complete(test_weight(4)),
|
||||
outcome: Outcome::Complete { used: test_weight(4) },
|
||||
paid: true,
|
||||
};
|
||||
assert_eq!(RoutingLog::take(), vec![entry]);
|
||||
@@ -117,7 +117,7 @@ fn sending_to_bridged_chain_works() {
|
||||
}
|
||||
#[test]
|
||||
fn sending_to_bridged_chain_without_funds_fails() {
|
||||
let dest: MultiLocation = (Parent, Parent, Remote::get()).into();
|
||||
let dest: Location = (Parent, Parent, Remote::get()).into();
|
||||
// Routing won't work if we don't have enough funds.
|
||||
assert_eq!(
|
||||
send_xcm::<LocalRouter>(dest, Xcm(vec![Trap(1)])),
|
||||
@@ -138,7 +138,7 @@ fn sending_to_bridged_chain_without_funds_fails() {
|
||||
#[test]
|
||||
fn sending_to_parachain_of_bridged_chain_works() {
|
||||
maybe_with_topic(|| {
|
||||
let dest: MultiLocation = (Parent, Parent, Remote::get(), Parachain(100)).into();
|
||||
let dest: Location = (Parent, Parent, Remote::get(), Parachain(100)).into();
|
||||
|
||||
// Initialize the local relay so that our parachain has funds to pay for export.
|
||||
clear_assets(Parachain(100));
|
||||
@@ -173,7 +173,7 @@ fn sending_to_parachain_of_bridged_chain_works() {
|
||||
message: xcm_with_topic(
|
||||
maybe_forward_id_for(&[0; 32]),
|
||||
vec![
|
||||
WithdrawAsset(MultiAsset::from((Here, price)).into()),
|
||||
WithdrawAsset(Asset::from((Here, price)).into()),
|
||||
BuyExecution { fees: (Here, price).into(), weight_limit: Unlimited },
|
||||
ExportMessage {
|
||||
network: ByGenesis([1; 32]),
|
||||
@@ -183,7 +183,7 @@ fn sending_to_parachain_of_bridged_chain_works() {
|
||||
DepositAsset { assets: Wild(All), beneficiary: Parachain(100).into() },
|
||||
],
|
||||
),
|
||||
outcome: Outcome::Complete(test_weight(4)),
|
||||
outcome: Outcome::Complete { used: test_weight(4) },
|
||||
paid: true,
|
||||
};
|
||||
assert_eq!(RoutingLog::take(), vec![entry]);
|
||||
@@ -191,7 +191,7 @@ fn sending_to_parachain_of_bridged_chain_works() {
|
||||
}
|
||||
#[test]
|
||||
fn sending_to_parachain_of_bridged_chain_without_funds_fails() {
|
||||
let dest: MultiLocation = (Parent, Parent, Remote::get(), Parachain(100)).into();
|
||||
let dest: Location = (Parent, Parent, Remote::get(), Parachain(100)).into();
|
||||
// Routing won't work if we don't have enough funds.
|
||||
assert_eq!(
|
||||
send_xcm::<LocalRouter>(dest, Xcm(vec![Trap(1)])),
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
use super::*;
|
||||
|
||||
parameter_types! {
|
||||
pub UniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(1000));
|
||||
pub ParaBridgeUniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(1));
|
||||
pub RemoteParaBridgeUniversalLocation: Junctions = X2(GlobalConsensus(Remote::get()), Parachain(1));
|
||||
pub RemoteNetwork: MultiLocation = AncestorThen(2, GlobalConsensus(Remote::get())).into();
|
||||
pub UniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(1000)].into();
|
||||
pub ParaBridgeUniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(1)].into();
|
||||
pub RemoteParaBridgeUniversalLocation: Junctions = [GlobalConsensus(Remote::get()), Parachain(1)].into();
|
||||
pub RemoteNetwork: Location = AncestorThen(2, GlobalConsensus(Remote::get())).into();
|
||||
pub BridgeTable: Vec<NetworkExportTableItem> = vec![
|
||||
NetworkExportTableItem::new(
|
||||
Remote::get(),
|
||||
@@ -62,7 +62,7 @@ fn sending_to_bridged_chain_works() {
|
||||
send_xcm::<LocalRouter>((Parent, Parent, Remote::get(), Parachain(1)).into(), msg)
|
||||
.unwrap()
|
||||
.1,
|
||||
MultiAssets::new()
|
||||
Assets::new()
|
||||
);
|
||||
assert_eq!(TheBridge::service(), 1);
|
||||
assert_eq!(
|
||||
@@ -94,7 +94,7 @@ fn sending_to_bridged_chain_works() {
|
||||
},
|
||||
],
|
||||
),
|
||||
outcome: Outcome::Complete(test_weight(2)),
|
||||
outcome: Outcome::Complete { used: test_weight(2) },
|
||||
paid: false,
|
||||
};
|
||||
assert_eq!(RoutingLog::take(), vec![entry]);
|
||||
@@ -116,7 +116,7 @@ fn sending_to_sibling_of_bridged_chain_works() {
|
||||
maybe_with_topic(|| {
|
||||
let msg = Xcm(vec![Trap(1)]);
|
||||
let dest = (Parent, Parent, Remote::get(), Parachain(1000)).into();
|
||||
assert_eq!(send_xcm::<LocalRouter>(dest, msg).unwrap().1, MultiAssets::new());
|
||||
assert_eq!(send_xcm::<LocalRouter>(dest, msg).unwrap().1, Assets::new());
|
||||
assert_eq!(TheBridge::service(), 1);
|
||||
let expected = vec![(
|
||||
(Parent, Parachain(1000)).into(),
|
||||
@@ -145,7 +145,7 @@ fn sending_to_sibling_of_bridged_chain_works() {
|
||||
},
|
||||
],
|
||||
),
|
||||
outcome: Outcome::Complete(test_weight(2)),
|
||||
outcome: Outcome::Complete { used: test_weight(2) },
|
||||
paid: false,
|
||||
};
|
||||
assert_eq!(RoutingLog::take(), vec![entry]);
|
||||
@@ -167,7 +167,7 @@ fn sending_to_relay_of_bridged_chain_works() {
|
||||
maybe_with_topic(|| {
|
||||
let msg = Xcm(vec![Trap(1)]);
|
||||
let dest = (Parent, Parent, Remote::get()).into();
|
||||
assert_eq!(send_xcm::<LocalRouter>(dest, msg).unwrap().1, MultiAssets::new());
|
||||
assert_eq!(send_xcm::<LocalRouter>(dest, msg).unwrap().1, Assets::new());
|
||||
assert_eq!(TheBridge::service(), 1);
|
||||
let expected = vec![(
|
||||
Parent.into(),
|
||||
@@ -196,7 +196,7 @@ fn sending_to_relay_of_bridged_chain_works() {
|
||||
},
|
||||
],
|
||||
),
|
||||
outcome: Outcome::Complete(test_weight(2)),
|
||||
outcome: Outcome::Complete { used: test_weight(2) },
|
||||
paid: false,
|
||||
};
|
||||
assert_eq!(RoutingLog::take(), vec![entry]);
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
use super::*;
|
||||
|
||||
parameter_types! {
|
||||
pub UniversalLocation: Junctions = X1(GlobalConsensus(Local::get()));
|
||||
pub ParaBridgeUniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(1));
|
||||
pub RemoteParaBridgeUniversalLocation: Junctions = X2(GlobalConsensus(Remote::get()), Parachain(1));
|
||||
pub RemoteNetwork: MultiLocation = AncestorThen(2, GlobalConsensus(Remote::get())).into();
|
||||
pub UniversalLocation: Junctions = [GlobalConsensus(Local::get())].into();
|
||||
pub ParaBridgeUniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(1)].into();
|
||||
pub RemoteParaBridgeUniversalLocation: Junctions = [GlobalConsensus(Remote::get()), Parachain(1)].into();
|
||||
pub RemoteNetwork: Location = AncestorThen(2, GlobalConsensus(Remote::get())).into();
|
||||
pub BridgeTable: Vec<NetworkExportTableItem> = vec![
|
||||
NetworkExportTableItem::new(
|
||||
Remote::get(),
|
||||
@@ -62,7 +62,7 @@ fn sending_to_bridged_chain_works() {
|
||||
send_xcm::<LocalRouter>((Parent, Remote::get(), Parachain(1)).into(), msg)
|
||||
.unwrap()
|
||||
.1,
|
||||
MultiAssets::new()
|
||||
Assets::new()
|
||||
);
|
||||
assert_eq!(TheBridge::service(), 1);
|
||||
let expected = vec![(
|
||||
@@ -85,7 +85,7 @@ fn sending_to_bridged_chain_works() {
|
||||
},
|
||||
],
|
||||
),
|
||||
outcome: Outcome::Complete(test_weight(2)),
|
||||
outcome: Outcome::Complete { used: test_weight(2) },
|
||||
paid: false,
|
||||
};
|
||||
assert_eq!(RoutingLog::take(), vec![entry]);
|
||||
@@ -107,7 +107,7 @@ fn sending_to_sibling_of_bridged_chain_works() {
|
||||
maybe_with_topic(|| {
|
||||
let msg = Xcm(vec![Trap(1)]);
|
||||
let dest = (Parent, Remote::get(), Parachain(1000)).into();
|
||||
assert_eq!(send_xcm::<LocalRouter>(dest, msg).unwrap().1, MultiAssets::new());
|
||||
assert_eq!(send_xcm::<LocalRouter>(dest, msg).unwrap().1, Assets::new());
|
||||
assert_eq!(TheBridge::service(), 1);
|
||||
let expected = vec![(
|
||||
(Parent, Parachain(1000)).into(),
|
||||
@@ -129,7 +129,7 @@ fn sending_to_sibling_of_bridged_chain_works() {
|
||||
},
|
||||
],
|
||||
),
|
||||
outcome: Outcome::Complete(test_weight(2)),
|
||||
outcome: Outcome::Complete { used: test_weight(2) },
|
||||
paid: false,
|
||||
};
|
||||
assert_eq!(RoutingLog::take(), vec![entry]);
|
||||
@@ -151,7 +151,7 @@ fn sending_to_relay_of_bridged_chain_works() {
|
||||
maybe_with_topic(|| {
|
||||
let msg = Xcm(vec![Trap(1)]);
|
||||
let dest = (Parent, Remote::get()).into();
|
||||
assert_eq!(send_xcm::<LocalRouter>(dest, msg).unwrap().1, MultiAssets::new());
|
||||
assert_eq!(send_xcm::<LocalRouter>(dest, msg).unwrap().1, Assets::new());
|
||||
assert_eq!(TheBridge::service(), 1);
|
||||
let expected = vec![(
|
||||
Parent.into(),
|
||||
@@ -173,7 +173,7 @@ fn sending_to_relay_of_bridged_chain_works() {
|
||||
},
|
||||
],
|
||||
),
|
||||
outcome: Outcome::Complete(test_weight(2)),
|
||||
outcome: Outcome::Complete { used: test_weight(2) },
|
||||
paid: false,
|
||||
};
|
||||
assert_eq!(RoutingLog::take(), vec![entry]);
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
use super::*;
|
||||
|
||||
parameter_types! {
|
||||
pub UniversalLocation: Junctions = X2(GlobalConsensus(Local::get()), Parachain(1000));
|
||||
pub RelayUniversalLocation: Junctions = X1(GlobalConsensus(Local::get()));
|
||||
pub RemoteUniversalLocation: Junctions = X1(GlobalConsensus(Remote::get()));
|
||||
pub RemoteNetwork: MultiLocation = AncestorThen(1, GlobalConsensus(Remote::get())).into();
|
||||
pub UniversalLocation: Junctions = [GlobalConsensus(Local::get()), Parachain(1000)].into();
|
||||
pub RelayUniversalLocation: Junctions = [GlobalConsensus(Local::get())].into();
|
||||
pub RemoteUniversalLocation: Junctions = [GlobalConsensus(Remote::get())].into();
|
||||
pub RemoteNetwork: Location = AncestorThen(1, GlobalConsensus(Remote::get())).into();
|
||||
pub BridgeTable: Vec<NetworkExportTableItem> = vec![
|
||||
NetworkExportTableItem::new(
|
||||
Remote::get(),
|
||||
None,
|
||||
MultiLocation::parent(),
|
||||
Location::parent(),
|
||||
None
|
||||
)
|
||||
];
|
||||
@@ -59,7 +59,7 @@ fn sending_to_bridged_chain_works() {
|
||||
let msg = Xcm(vec![Trap(1)]);
|
||||
assert_eq!(
|
||||
send_xcm::<LocalRouter>((Parent, Parent, Remote::get()).into(), msg).unwrap().1,
|
||||
MultiAssets::new()
|
||||
Assets::new()
|
||||
);
|
||||
assert_eq!(TheBridge::service(), 1);
|
||||
assert_eq!(
|
||||
@@ -91,7 +91,7 @@ fn sending_to_bridged_chain_works() {
|
||||
},
|
||||
],
|
||||
),
|
||||
outcome: Outcome::Complete(test_weight(2)),
|
||||
outcome: Outcome::Complete { used: test_weight(2) },
|
||||
paid: false,
|
||||
};
|
||||
assert_eq!(RoutingLog::take(), vec![entry]);
|
||||
@@ -113,7 +113,7 @@ fn sending_to_parachain_of_bridged_chain_works() {
|
||||
maybe_with_topic(|| {
|
||||
let msg = Xcm(vec![Trap(1)]);
|
||||
let dest = (Parent, Parent, Remote::get(), Parachain(1000)).into();
|
||||
assert_eq!(send_xcm::<LocalRouter>(dest, msg).unwrap().1, MultiAssets::new());
|
||||
assert_eq!(send_xcm::<LocalRouter>(dest, msg).unwrap().1, Assets::new());
|
||||
assert_eq!(TheBridge::service(), 1);
|
||||
let expected = vec![(
|
||||
Parachain(1000).into(),
|
||||
@@ -142,7 +142,7 @@ fn sending_to_parachain_of_bridged_chain_works() {
|
||||
},
|
||||
],
|
||||
),
|
||||
outcome: Outcome::Complete(test_weight(2)),
|
||||
outcome: Outcome::Complete { used: test_weight(2) },
|
||||
paid: false,
|
||||
};
|
||||
assert_eq!(RoutingLog::take(), vec![entry]);
|
||||
|
||||
@@ -18,7 +18,7 @@ use super::*;
|
||||
|
||||
#[test]
|
||||
fn expect_pallet_should_work() {
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into()]);
|
||||
// They want to transfer 100 of our native asset from sovereign account of parachain #1 into #2
|
||||
// and let them know to hand it to account #3.
|
||||
let message = Xcm(vec![ExpectPallet {
|
||||
@@ -28,14 +28,15 @@ fn expect_pallet_should_work() {
|
||||
crate_major: 1,
|
||||
min_crate_minor: 42,
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
|
||||
let message = Xcm(vec![ExpectPallet {
|
||||
index: 1,
|
||||
@@ -44,19 +45,20 @@ fn expect_pallet_should_work() {
|
||||
crate_major: 1,
|
||||
min_crate_minor: 41,
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expect_pallet_should_fail_correctly() {
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into()]);
|
||||
let message = Xcm(vec![ExpectPallet {
|
||||
index: 1,
|
||||
name: b"Balances".as_ref().into(),
|
||||
@@ -64,14 +66,21 @@ fn expect_pallet_should_fail_correctly() {
|
||||
crate_major: 1,
|
||||
min_crate_minor: 60,
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete {
|
||||
used: Weight::from_parts(10, 10),
|
||||
error: XcmError::VersionIncompatible
|
||||
}
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::VersionIncompatible));
|
||||
|
||||
let message = Xcm(vec![ExpectPallet {
|
||||
index: 1,
|
||||
@@ -80,14 +89,18 @@ fn expect_pallet_should_fail_correctly() {
|
||||
crate_major: 1,
|
||||
min_crate_minor: 42,
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NameMismatch }
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::NameMismatch));
|
||||
|
||||
let message = Xcm(vec![ExpectPallet {
|
||||
index: 1,
|
||||
@@ -96,14 +109,18 @@ fn expect_pallet_should_fail_correctly() {
|
||||
crate_major: 1,
|
||||
min_crate_minor: 42,
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NameMismatch }
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::NameMismatch));
|
||||
|
||||
let message = Xcm(vec![ExpectPallet {
|
||||
index: 0,
|
||||
@@ -112,14 +129,18 @@ fn expect_pallet_should_fail_correctly() {
|
||||
crate_major: 1,
|
||||
min_crate_minor: 42,
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NameMismatch }
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::NameMismatch));
|
||||
|
||||
let message = Xcm(vec![ExpectPallet {
|
||||
index: 2,
|
||||
@@ -128,14 +149,18 @@ fn expect_pallet_should_fail_correctly() {
|
||||
crate_major: 1,
|
||||
min_crate_minor: 42,
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::PalletNotFound }
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::PalletNotFound));
|
||||
|
||||
let message = Xcm(vec![ExpectPallet {
|
||||
index: 1,
|
||||
@@ -144,14 +169,21 @@ fn expect_pallet_should_fail_correctly() {
|
||||
crate_major: 2,
|
||||
min_crate_minor: 42,
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete {
|
||||
used: Weight::from_parts(10, 10),
|
||||
error: XcmError::VersionIncompatible
|
||||
}
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::VersionIncompatible));
|
||||
|
||||
let message = Xcm(vec![ExpectPallet {
|
||||
index: 1,
|
||||
@@ -160,14 +192,21 @@ fn expect_pallet_should_fail_correctly() {
|
||||
crate_major: 0,
|
||||
min_crate_minor: 42,
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete {
|
||||
used: Weight::from_parts(10, 10),
|
||||
error: XcmError::VersionIncompatible
|
||||
}
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::VersionIncompatible));
|
||||
|
||||
let message = Xcm(vec![ExpectPallet {
|
||||
index: 1,
|
||||
@@ -176,12 +215,19 @@ fn expect_pallet_should_fail_correctly() {
|
||||
crate_major: 1,
|
||||
min_crate_minor: 43,
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete {
|
||||
used: Weight::from_parts(10, 10),
|
||||
error: XcmError::VersionIncompatible
|
||||
}
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::VersionIncompatible));
|
||||
}
|
||||
|
||||
@@ -34,10 +34,15 @@ fn lock_roundtrip_should_work() {
|
||||
),
|
||||
LockAsset { asset: (Parent, 100u128).into(), unlocker: (Parent, Parachain(1)).into() },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r =
|
||||
XcmExecutor::<TestConfig>::execute_xcm((3u64,), message, hash, Weight::from_parts(50, 50));
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(40, 40)));
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(3u64,),
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(40, 40) });
|
||||
assert_eq!(asset_list((3u64,)), vec![(Parent, 990u128).into()]);
|
||||
|
||||
let expected_msg = Xcm::<()>(vec![NoteUnlockable {
|
||||
@@ -58,14 +63,15 @@ fn lock_roundtrip_should_work() {
|
||||
// Now we'll unlock it.
|
||||
let message =
|
||||
Xcm(vec![UnlockAsset { asset: (Parent, 100u128).into(), target: (3u64,).into() }]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(Parent, Parachain(1)),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -82,10 +88,15 @@ fn auto_fee_paying_should_work() {
|
||||
SetFeesMode { jit_withdraw: true },
|
||||
LockAsset { asset: (Parent, 100u128).into(), unlocker: (Parent, Parachain(1)).into() },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r =
|
||||
XcmExecutor::<TestConfig>::execute_xcm((3u64,), message, hash, Weight::from_parts(50, 50));
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(20, 20)));
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(3u64,),
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(20, 20) });
|
||||
assert_eq!(asset_list((3u64,)), vec![(Parent, 990u128).into()]);
|
||||
}
|
||||
|
||||
@@ -100,10 +111,18 @@ fn lock_should_fail_correctly() {
|
||||
asset: (Parent, 100u128).into(),
|
||||
unlocker: (Parent, Parachain(1)).into(),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r =
|
||||
XcmExecutor::<TestConfig>::execute_xcm((3u64,), message, hash, Weight::from_parts(50, 50));
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::LockError));
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(3u64,),
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::LockError }
|
||||
);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
assert_eq!(take_lock_trace(), vec![]);
|
||||
|
||||
@@ -118,10 +137,18 @@ fn lock_should_fail_correctly() {
|
||||
asset: (Parent, 100u128).into(),
|
||||
unlocker: (Parent, Parachain(1)).into(),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r =
|
||||
XcmExecutor::<TestConfig>::execute_xcm((3u64,), message, hash, Weight::from_parts(50, 50));
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::NotHoldingFees));
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(3u64,),
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NotHoldingFees }
|
||||
);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
assert_eq!(take_lock_trace(), vec![]);
|
||||
}
|
||||
@@ -140,14 +167,15 @@ fn remote_unlock_roundtrip_should_work() {
|
||||
// This caused Parachain #1 to send us the NoteUnlockable instruction.
|
||||
let message =
|
||||
Xcm(vec![NoteUnlockable { asset: (Parent, 100u128).into(), owner: (3u64,).into() }]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(Parent, Parachain(1)),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
assert_eq!(
|
||||
take_lock_trace(),
|
||||
vec![Note {
|
||||
@@ -165,10 +193,15 @@ fn remote_unlock_roundtrip_should_work() {
|
||||
),
|
||||
RequestUnlock { asset: (Parent, 100u128).into(), locker: (Parent, Parachain(1)).into() },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r =
|
||||
XcmExecutor::<TestConfig>::execute_xcm((3u64,), message, hash, Weight::from_parts(50, 50));
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(40, 40)));
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(3u64,),
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(40, 40) });
|
||||
assert_eq!(asset_list((3u64,)), vec![(Parent, 990u128).into()]);
|
||||
|
||||
let expected_msg = Xcm::<()>(vec![UnlockAsset {
|
||||
@@ -201,24 +234,33 @@ fn remote_unlock_should_fail_correctly() {
|
||||
asset: (Parent, 100u128).into(),
|
||||
locker: (Parent, Parachain(1)).into(),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r =
|
||||
XcmExecutor::<TestConfig>::execute_xcm((3u64,), message, hash, Weight::from_parts(50, 50));
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::LockError));
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(3u64,),
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::LockError }
|
||||
);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
assert_eq!(take_lock_trace(), vec![]);
|
||||
|
||||
// We have been told by Parachain #1 that Account #3 has locked funds which we can unlock.
|
||||
let message =
|
||||
Xcm(vec![NoteUnlockable { asset: (Parent, 100u128).into(), owner: (3u64,).into() }]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(Parent, Parachain(1)),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
let _discard = take_lock_trace();
|
||||
|
||||
// We want to unlock 100 of the native parent tokens which were locked for us on parachain.
|
||||
@@ -228,10 +270,18 @@ fn remote_unlock_should_fail_correctly() {
|
||||
asset: (Parent, 100u128).into(),
|
||||
locker: (Parent, Parachain(1)).into(),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r =
|
||||
XcmExecutor::<TestConfig>::execute_xcm((3u64,), message, hash, Weight::from_parts(50, 50));
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::NotHoldingFees));
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
(3u64,),
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NotHoldingFees }
|
||||
);
|
||||
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
assert_eq!(take_lock_trace(), vec![]);
|
||||
|
||||
@@ -28,7 +28,7 @@ pub use crate::{
|
||||
use frame_support::traits::{ContainsPair, Everything};
|
||||
pub use frame_support::{
|
||||
dispatch::{DispatchInfo, DispatchResultWithPostInfo, GetDispatchInfo, PostDispatchInfo},
|
||||
ensure, match_types, parameter_types,
|
||||
ensure, parameter_types,
|
||||
sp_runtime::{traits::Dispatchable, DispatchError, DispatchErrorWithPostInfo},
|
||||
traits::{Contains, Get, IsInVec},
|
||||
};
|
||||
@@ -45,7 +45,7 @@ pub use xcm_executor::{
|
||||
AssetExchange, AssetLock, CheckSuspension, ConvertOrigin, Enact, ExportXcm, FeeManager,
|
||||
FeeReason, LockError, OnResponse, TransactAsset,
|
||||
},
|
||||
Assets, Config,
|
||||
AssetsInHolding, Config,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -110,52 +110,52 @@ impl GetDispatchInfo for TestCall {
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub static SENT_XCM: RefCell<Vec<(MultiLocation, Xcm<()>, XcmHash)>> = RefCell::new(Vec::new());
|
||||
pub static SENT_XCM: RefCell<Vec<(Location, Xcm<()>, XcmHash)>> = RefCell::new(Vec::new());
|
||||
pub static EXPORTED_XCM: RefCell<
|
||||
Vec<(NetworkId, u32, InteriorMultiLocation, InteriorMultiLocation, Xcm<()>, XcmHash)>
|
||||
Vec<(NetworkId, u32, InteriorLocation, InteriorLocation, Xcm<()>, XcmHash)>
|
||||
> = RefCell::new(Vec::new());
|
||||
pub static EXPORTER_OVERRIDE: RefCell<Option<(
|
||||
fn(
|
||||
NetworkId,
|
||||
u32,
|
||||
&InteriorMultiLocation,
|
||||
&InteriorMultiLocation,
|
||||
&InteriorLocation,
|
||||
&InteriorLocation,
|
||||
&Xcm<()>,
|
||||
) -> Result<MultiAssets, SendError>,
|
||||
) -> Result<Assets, SendError>,
|
||||
fn(
|
||||
NetworkId,
|
||||
u32,
|
||||
InteriorMultiLocation,
|
||||
InteriorMultiLocation,
|
||||
InteriorLocation,
|
||||
InteriorLocation,
|
||||
Xcm<()>,
|
||||
) -> Result<XcmHash, SendError>,
|
||||
)>> = RefCell::new(None);
|
||||
pub static SEND_PRICE: RefCell<MultiAssets> = RefCell::new(MultiAssets::new());
|
||||
pub static SEND_PRICE: RefCell<Assets> = RefCell::new(Assets::new());
|
||||
pub static SUSPENDED: Cell<bool> = Cell::new(false);
|
||||
}
|
||||
pub fn sent_xcm() -> Vec<(MultiLocation, opaque::Xcm, XcmHash)> {
|
||||
pub fn sent_xcm() -> Vec<(Location, opaque::Xcm, XcmHash)> {
|
||||
SENT_XCM.with(|q| (*q.borrow()).clone())
|
||||
}
|
||||
pub fn set_send_price(p: impl Into<MultiAsset>) {
|
||||
pub fn set_send_price(p: impl Into<Asset>) {
|
||||
SEND_PRICE.with(|l| l.replace(p.into().into()));
|
||||
}
|
||||
pub fn exported_xcm(
|
||||
) -> Vec<(NetworkId, u32, InteriorMultiLocation, InteriorMultiLocation, opaque::Xcm, XcmHash)> {
|
||||
) -> Vec<(NetworkId, u32, InteriorLocation, InteriorLocation, opaque::Xcm, XcmHash)> {
|
||||
EXPORTED_XCM.with(|q| (*q.borrow()).clone())
|
||||
}
|
||||
pub fn set_exporter_override(
|
||||
price: fn(
|
||||
NetworkId,
|
||||
u32,
|
||||
&InteriorMultiLocation,
|
||||
&InteriorMultiLocation,
|
||||
&InteriorLocation,
|
||||
&InteriorLocation,
|
||||
&Xcm<()>,
|
||||
) -> Result<MultiAssets, SendError>,
|
||||
) -> Result<Assets, SendError>,
|
||||
deliver: fn(
|
||||
NetworkId,
|
||||
u32,
|
||||
InteriorMultiLocation,
|
||||
InteriorMultiLocation,
|
||||
InteriorLocation,
|
||||
InteriorLocation,
|
||||
Xcm<()>,
|
||||
) -> Result<XcmHash, SendError>,
|
||||
) {
|
||||
@@ -167,17 +167,17 @@ pub fn clear_exporter_override() {
|
||||
}
|
||||
pub struct TestMessageSender;
|
||||
impl SendXcm for TestMessageSender {
|
||||
type Ticket = (MultiLocation, Xcm<()>, XcmHash);
|
||||
type Ticket = (Location, Xcm<()>, XcmHash);
|
||||
fn validate(
|
||||
dest: &mut Option<MultiLocation>,
|
||||
dest: &mut Option<Location>,
|
||||
msg: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<(MultiLocation, Xcm<()>, XcmHash)> {
|
||||
) -> SendResult<(Location, Xcm<()>, XcmHash)> {
|
||||
let msg = msg.take().unwrap();
|
||||
let hash = fake_message_hash(&msg);
|
||||
let triplet = (dest.take().unwrap(), msg, hash);
|
||||
Ok((triplet, SEND_PRICE.with(|l| l.borrow().clone())))
|
||||
}
|
||||
fn deliver(triplet: (MultiLocation, Xcm<()>, XcmHash)) -> Result<XcmHash, SendError> {
|
||||
fn deliver(triplet: (Location, Xcm<()>, XcmHash)) -> Result<XcmHash, SendError> {
|
||||
let hash = triplet.2;
|
||||
SENT_XCM.with(|q| q.borrow_mut().push(triplet));
|
||||
Ok(hash)
|
||||
@@ -185,21 +185,20 @@ impl SendXcm for TestMessageSender {
|
||||
}
|
||||
pub struct TestMessageExporter;
|
||||
impl ExportXcm for TestMessageExporter {
|
||||
type Ticket = (NetworkId, u32, InteriorMultiLocation, InteriorMultiLocation, Xcm<()>, XcmHash);
|
||||
type Ticket = (NetworkId, u32, InteriorLocation, InteriorLocation, Xcm<()>, XcmHash);
|
||||
fn validate(
|
||||
network: NetworkId,
|
||||
channel: u32,
|
||||
uni_src: &mut Option<InteriorMultiLocation>,
|
||||
dest: &mut Option<InteriorMultiLocation>,
|
||||
uni_src: &mut Option<InteriorLocation>,
|
||||
dest: &mut Option<InteriorLocation>,
|
||||
msg: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<(NetworkId, u32, InteriorMultiLocation, InteriorMultiLocation, Xcm<()>, XcmHash)>
|
||||
{
|
||||
) -> SendResult<(NetworkId, u32, InteriorLocation, InteriorLocation, Xcm<()>, XcmHash)> {
|
||||
let (s, d, m) = (uni_src.take().unwrap(), dest.take().unwrap(), msg.take().unwrap());
|
||||
let r: Result<MultiAssets, SendError> = EXPORTER_OVERRIDE.with(|e| {
|
||||
let r: Result<Assets, SendError> = EXPORTER_OVERRIDE.with(|e| {
|
||||
if let Some((ref f, _)) = &*e.borrow() {
|
||||
f(network, channel, &s, &d, &m)
|
||||
} else {
|
||||
Ok(MultiAssets::new())
|
||||
Ok(Assets::new())
|
||||
}
|
||||
});
|
||||
let h = fake_message_hash(&m);
|
||||
@@ -214,7 +213,7 @@ impl ExportXcm for TestMessageExporter {
|
||||
}
|
||||
}
|
||||
fn deliver(
|
||||
tuple: (NetworkId, u32, InteriorMultiLocation, InteriorMultiLocation, Xcm<()>, XcmHash),
|
||||
tuple: (NetworkId, u32, InteriorLocation, InteriorLocation, Xcm<()>, XcmHash),
|
||||
) -> Result<XcmHash, SendError> {
|
||||
EXPORTER_OVERRIDE.with(|e| {
|
||||
if let Some((_, ref f)) = &*e.borrow() {
|
||||
@@ -230,37 +229,42 @@ impl ExportXcm for TestMessageExporter {
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub static ASSETS: RefCell<BTreeMap<MultiLocation, Assets>> = RefCell::new(BTreeMap::new());
|
||||
pub static ASSETS: RefCell<BTreeMap<Location, AssetsInHolding>> = RefCell::new(BTreeMap::new());
|
||||
}
|
||||
pub fn assets(who: impl Into<MultiLocation>) -> Assets {
|
||||
pub fn assets(who: impl Into<Location>) -> AssetsInHolding {
|
||||
ASSETS.with(|a| a.borrow().get(&who.into()).cloned()).unwrap_or_default()
|
||||
}
|
||||
pub fn asset_list(who: impl Into<MultiLocation>) -> Vec<MultiAsset> {
|
||||
MultiAssets::from(assets(who)).into_inner()
|
||||
pub fn asset_list(who: impl Into<Location>) -> Vec<Asset> {
|
||||
Assets::from(assets(who)).into_inner()
|
||||
}
|
||||
pub fn add_asset(who: impl Into<MultiLocation>, what: impl Into<MultiAsset>) {
|
||||
ASSETS.with(|a| a.borrow_mut().entry(who.into()).or_insert(Assets::new()).subsume(what.into()));
|
||||
pub fn add_asset(who: impl Into<Location>, what: impl Into<Asset>) {
|
||||
ASSETS.with(|a| {
|
||||
a.borrow_mut()
|
||||
.entry(who.into())
|
||||
.or_insert(AssetsInHolding::new())
|
||||
.subsume(what.into())
|
||||
});
|
||||
}
|
||||
pub fn clear_assets(who: impl Into<MultiLocation>) {
|
||||
pub fn clear_assets(who: impl Into<Location>) {
|
||||
ASSETS.with(|a| a.borrow_mut().remove(&who.into()));
|
||||
}
|
||||
|
||||
pub struct TestAssetTransactor;
|
||||
impl TransactAsset for TestAssetTransactor {
|
||||
fn deposit_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
what: &Asset,
|
||||
who: &Location,
|
||||
_context: Option<&XcmContext>,
|
||||
) -> Result<(), XcmError> {
|
||||
add_asset(*who, what.clone());
|
||||
add_asset(who.clone(), what.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation,
|
||||
what: &Asset,
|
||||
who: &Location,
|
||||
_maybe_context: Option<&XcmContext>,
|
||||
) -> Result<Assets, XcmError> {
|
||||
) -> Result<AssetsInHolding, XcmError> {
|
||||
ASSETS.with(|a| {
|
||||
a.borrow_mut()
|
||||
.get_mut(who)
|
||||
@@ -271,19 +275,20 @@ impl TransactAsset for TestAssetTransactor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_account(l: impl Into<MultiLocation>) -> Result<u64, MultiLocation> {
|
||||
Ok(match l.into() {
|
||||
pub fn to_account(l: impl Into<Location>) -> Result<u64, Location> {
|
||||
let l = l.into();
|
||||
Ok(match l.unpack() {
|
||||
// Siblings at 2000+id
|
||||
MultiLocation { parents: 1, interior: X1(Parachain(id)) } => 2000 + id as u64,
|
||||
(1, [Parachain(id)]) => 2000 + *id as u64,
|
||||
// Accounts are their number
|
||||
MultiLocation { parents: 0, interior: X1(AccountIndex64 { index, .. }) } => index,
|
||||
(0, [AccountIndex64 { index, .. }]) => *index,
|
||||
// Children at 1000+id
|
||||
MultiLocation { parents: 0, interior: X1(Parachain(id)) } => 1000 + id as u64,
|
||||
(0, [Parachain(id)]) => 1000 + *id as u64,
|
||||
// Self at 3000
|
||||
MultiLocation { parents: 0, interior: Here } => 3000,
|
||||
(0, []) => 3000,
|
||||
// Parent at 3001
|
||||
MultiLocation { parents: 1, interior: Here } => 3001,
|
||||
l => {
|
||||
(1, []) => 3001,
|
||||
_ => {
|
||||
// Is it a foreign-consensus?
|
||||
let uni = ExecutorUniversalLocation::get();
|
||||
if l.parents as usize != uni.len() {
|
||||
@@ -301,36 +306,35 @@ pub fn to_account(l: impl Into<MultiLocation>) -> Result<u64, MultiLocation> {
|
||||
pub struct TestOriginConverter;
|
||||
impl ConvertOrigin<TestOrigin> for TestOriginConverter {
|
||||
fn convert_origin(
|
||||
origin: impl Into<MultiLocation>,
|
||||
origin: impl Into<Location>,
|
||||
kind: OriginKind,
|
||||
) -> Result<TestOrigin, MultiLocation> {
|
||||
) -> Result<TestOrigin, Location> {
|
||||
use OriginKind::*;
|
||||
match (kind, origin.into()) {
|
||||
let origin = origin.into();
|
||||
match (kind, origin.unpack()) {
|
||||
(Superuser, _) => Ok(TestOrigin::Root),
|
||||
(SovereignAccount, l) => Ok(TestOrigin::Signed(to_account(l)?)),
|
||||
(Native, MultiLocation { parents: 0, interior: X1(Parachain(id)) }) =>
|
||||
Ok(TestOrigin::Parachain(id)),
|
||||
(Native, MultiLocation { parents: 1, interior: Here }) => Ok(TestOrigin::Relay),
|
||||
(Native, MultiLocation { parents: 0, interior: X1(AccountIndex64 { index, .. }) }) =>
|
||||
Ok(TestOrigin::Signed(index)),
|
||||
(_, origin) => Err(origin),
|
||||
(SovereignAccount, _) => Ok(TestOrigin::Signed(to_account(origin)?)),
|
||||
(Native, (0, [Parachain(id)])) => Ok(TestOrigin::Parachain(*id)),
|
||||
(Native, (1, [])) => Ok(TestOrigin::Relay),
|
||||
(Native, (0, [AccountIndex64 { index, .. }])) => Ok(TestOrigin::Signed(*index)),
|
||||
_ => Err(origin),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub static IS_RESERVE: RefCell<BTreeMap<MultiLocation, Vec<MultiAssetFilter>>> = RefCell::new(BTreeMap::new());
|
||||
pub static IS_TELEPORTER: RefCell<BTreeMap<MultiLocation, Vec<MultiAssetFilter>>> = RefCell::new(BTreeMap::new());
|
||||
pub static UNIVERSAL_ALIASES: RefCell<BTreeSet<(MultiLocation, Junction)>> = RefCell::new(BTreeSet::new());
|
||||
pub static IS_RESERVE: RefCell<BTreeMap<Location, Vec<AssetFilter>>> = RefCell::new(BTreeMap::new());
|
||||
pub static IS_TELEPORTER: RefCell<BTreeMap<Location, Vec<AssetFilter>>> = RefCell::new(BTreeMap::new());
|
||||
pub static UNIVERSAL_ALIASES: RefCell<BTreeSet<(Location, Junction)>> = RefCell::new(BTreeSet::new());
|
||||
}
|
||||
pub fn add_reserve(from: MultiLocation, asset: MultiAssetFilter) {
|
||||
pub fn add_reserve(from: Location, asset: AssetFilter) {
|
||||
IS_RESERVE.with(|r| r.borrow_mut().entry(from).or_default().push(asset));
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn add_teleporter(from: MultiLocation, asset: MultiAssetFilter) {
|
||||
pub fn add_teleporter(from: Location, asset: AssetFilter) {
|
||||
IS_TELEPORTER.with(|r| r.borrow_mut().entry(from).or_default().push(asset));
|
||||
}
|
||||
pub fn add_universal_alias(bridge: impl Into<MultiLocation>, consensus: impl Into<Junction>) {
|
||||
pub fn add_universal_alias(bridge: impl Into<Location>, consensus: impl Into<Junction>) {
|
||||
UNIVERSAL_ALIASES.with(|r| r.borrow_mut().insert((bridge.into(), consensus.into())));
|
||||
}
|
||||
pub fn clear_universal_aliases() {
|
||||
@@ -338,29 +342,29 @@ pub fn clear_universal_aliases() {
|
||||
}
|
||||
|
||||
pub struct TestIsReserve;
|
||||
impl ContainsPair<MultiAsset, MultiLocation> for TestIsReserve {
|
||||
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
|
||||
impl ContainsPair<Asset, Location> for TestIsReserve {
|
||||
fn contains(asset: &Asset, origin: &Location) -> bool {
|
||||
IS_RESERVE
|
||||
.with(|r| r.borrow().get(origin).map_or(false, |v| v.iter().any(|a| a.matches(asset))))
|
||||
}
|
||||
}
|
||||
pub struct TestIsTeleporter;
|
||||
impl ContainsPair<MultiAsset, MultiLocation> for TestIsTeleporter {
|
||||
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
|
||||
impl ContainsPair<Asset, Location> for TestIsTeleporter {
|
||||
fn contains(asset: &Asset, origin: &Location) -> bool {
|
||||
IS_TELEPORTER
|
||||
.with(|r| r.borrow().get(origin).map_or(false, |v| v.iter().any(|a| a.matches(asset))))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestUniversalAliases;
|
||||
impl Contains<(MultiLocation, Junction)> for TestUniversalAliases {
|
||||
fn contains(t: &(MultiLocation, Junction)) -> bool {
|
||||
impl Contains<(Location, Junction)> for TestUniversalAliases {
|
||||
fn contains(t: &(Location, Junction)) -> bool {
|
||||
UNIVERSAL_ALIASES.with(|r| r.borrow().contains(t))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ResponseSlot {
|
||||
Expecting(MultiLocation),
|
||||
Expecting(Location),
|
||||
Received(Response),
|
||||
}
|
||||
thread_local! {
|
||||
@@ -368,20 +372,16 @@ thread_local! {
|
||||
}
|
||||
pub struct TestResponseHandler;
|
||||
impl OnResponse for TestResponseHandler {
|
||||
fn expecting_response(
|
||||
origin: &MultiLocation,
|
||||
query_id: u64,
|
||||
_querier: Option<&MultiLocation>,
|
||||
) -> bool {
|
||||
fn expecting_response(origin: &Location, query_id: u64, _querier: Option<&Location>) -> bool {
|
||||
QUERIES.with(|q| match q.borrow().get(&query_id) {
|
||||
Some(ResponseSlot::Expecting(ref l)) => l == origin,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
fn on_response(
|
||||
_origin: &MultiLocation,
|
||||
_origin: &Location,
|
||||
query_id: u64,
|
||||
_querier: Option<&MultiLocation>,
|
||||
_querier: Option<&Location>,
|
||||
response: xcm::latest::Response,
|
||||
_max_weight: Weight,
|
||||
_context: &XcmContext,
|
||||
@@ -396,7 +396,7 @@ impl OnResponse for TestResponseHandler {
|
||||
Weight::from_parts(10, 10)
|
||||
}
|
||||
}
|
||||
pub fn expect_response(query_id: u64, from: MultiLocation) {
|
||||
pub fn expect_response(query_id: u64, from: Location) {
|
||||
QUERIES.with(|q| q.borrow_mut().insert(query_id, ResponseSlot::Expecting(from)));
|
||||
}
|
||||
pub fn response(query_id: u64) -> Option<Response> {
|
||||
@@ -420,9 +420,9 @@ impl<T: Config, BlockNumber: sp_runtime::traits::Zero + Encode> QueryHandler
|
||||
type UniversalLocation = T::UniversalLocation;
|
||||
|
||||
fn new_query(
|
||||
responder: impl Into<MultiLocation>,
|
||||
responder: impl Into<Location>,
|
||||
_timeout: Self::BlockNumber,
|
||||
_match_querier: impl Into<MultiLocation>,
|
||||
_match_querier: impl Into<Location>,
|
||||
) -> Self::QueryId {
|
||||
let query_id = 1;
|
||||
expect_response(query_id, responder.into());
|
||||
@@ -431,7 +431,7 @@ impl<T: Config, BlockNumber: sp_runtime::traits::Zero + Encode> QueryHandler
|
||||
|
||||
fn report_outcome(
|
||||
message: &mut Xcm<()>,
|
||||
responder: impl Into<MultiLocation>,
|
||||
responder: impl Into<Location>,
|
||||
timeout: Self::BlockNumber,
|
||||
) -> Result<Self::QueryId, Self::Error> {
|
||||
let responder = responder.into();
|
||||
@@ -466,16 +466,16 @@ impl<T: Config, BlockNumber: sp_runtime::traits::Zero + Encode> QueryHandler
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub static ExecutorUniversalLocation: InteriorMultiLocation
|
||||
pub static ExecutorUniversalLocation: InteriorLocation
|
||||
= (ByGenesis([0; 32]), Parachain(42)).into();
|
||||
pub UnitWeightCost: Weight = Weight::from_parts(10, 10);
|
||||
}
|
||||
parameter_types! {
|
||||
// Nothing is allowed to be paid/unpaid by default.
|
||||
pub static AllowExplicitUnpaidFrom: Vec<MultiLocation> = vec![];
|
||||
pub static AllowUnpaidFrom: Vec<MultiLocation> = vec![];
|
||||
pub static AllowPaidFrom: Vec<MultiLocation> = vec![];
|
||||
pub static AllowSubsFrom: Vec<MultiLocation> = vec![];
|
||||
pub static AllowExplicitUnpaidFrom: Vec<Location> = vec![];
|
||||
pub static AllowUnpaidFrom: Vec<Location> = vec![];
|
||||
pub static AllowPaidFrom: Vec<Location> = vec![];
|
||||
pub static AllowSubsFrom: Vec<Location> = vec![];
|
||||
// 1_000_000_000_000 => 1 unit of asset for 1 unit of ref time weight.
|
||||
// 1024 * 1024 => 1 unit of asset for 1 unit of proof size weight.
|
||||
pub static WeightPrice: (AssetId, u128, u128) =
|
||||
@@ -486,7 +486,7 @@ parameter_types! {
|
||||
pub struct TestSuspender;
|
||||
impl CheckSuspension for TestSuspender {
|
||||
fn is_suspended<Call>(
|
||||
_origin: &MultiLocation,
|
||||
_origin: &Location,
|
||||
_instructions: &mut [Instruction<Call>],
|
||||
_max_weight: Weight,
|
||||
_properties: &mut Properties,
|
||||
@@ -520,34 +520,34 @@ pub fn set_fee_waiver(waived: Vec<FeeReason>) {
|
||||
|
||||
pub struct TestFeeManager;
|
||||
impl FeeManager for TestFeeManager {
|
||||
fn is_waived(_: Option<&MultiLocation>, r: FeeReason) -> bool {
|
||||
fn is_waived(_: Option<&Location>, r: FeeReason) -> bool {
|
||||
IS_WAIVED.with(|l| l.borrow().contains(&r))
|
||||
}
|
||||
|
||||
fn handle_fee(_: MultiAssets, _: Option<&XcmContext>, _: FeeReason) {}
|
||||
fn handle_fee(_: Assets, _: Option<&XcmContext>, _: FeeReason) {}
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Debug)]
|
||||
pub enum LockTraceItem {
|
||||
Lock { unlocker: MultiLocation, asset: MultiAsset, owner: MultiLocation },
|
||||
Unlock { unlocker: MultiLocation, asset: MultiAsset, owner: MultiLocation },
|
||||
Note { locker: MultiLocation, asset: MultiAsset, owner: MultiLocation },
|
||||
Reduce { locker: MultiLocation, asset: MultiAsset, owner: MultiLocation },
|
||||
Lock { unlocker: Location, asset: Asset, owner: Location },
|
||||
Unlock { unlocker: Location, asset: Asset, owner: Location },
|
||||
Note { locker: Location, asset: Asset, owner: Location },
|
||||
Reduce { locker: Location, asset: Asset, owner: Location },
|
||||
}
|
||||
thread_local! {
|
||||
pub static NEXT_INDEX: RefCell<u32> = RefCell::new(0);
|
||||
pub static LOCK_TRACE: RefCell<Vec<LockTraceItem>> = RefCell::new(Vec::new());
|
||||
pub static ALLOWED_UNLOCKS: RefCell<BTreeMap<(MultiLocation, MultiLocation), Assets>> = RefCell::new(BTreeMap::new());
|
||||
pub static ALLOWED_REQUEST_UNLOCKS: RefCell<BTreeMap<(MultiLocation, MultiLocation), Assets>> = RefCell::new(BTreeMap::new());
|
||||
pub static ALLOWED_UNLOCKS: RefCell<BTreeMap<(Location, Location), AssetsInHolding>> = RefCell::new(BTreeMap::new());
|
||||
pub static ALLOWED_REQUEST_UNLOCKS: RefCell<BTreeMap<(Location, Location), AssetsInHolding>> = RefCell::new(BTreeMap::new());
|
||||
}
|
||||
|
||||
pub fn take_lock_trace() -> Vec<LockTraceItem> {
|
||||
LOCK_TRACE.with(|l| l.replace(Vec::new()))
|
||||
}
|
||||
pub fn allow_unlock(
|
||||
unlocker: impl Into<MultiLocation>,
|
||||
asset: impl Into<MultiAsset>,
|
||||
owner: impl Into<MultiLocation>,
|
||||
unlocker: impl Into<Location>,
|
||||
asset: impl Into<Asset>,
|
||||
owner: impl Into<Location>,
|
||||
) {
|
||||
ALLOWED_UNLOCKS.with(|l| {
|
||||
l.borrow_mut()
|
||||
@@ -557,9 +557,9 @@ pub fn allow_unlock(
|
||||
});
|
||||
}
|
||||
pub fn disallow_unlock(
|
||||
unlocker: impl Into<MultiLocation>,
|
||||
asset: impl Into<MultiAsset>,
|
||||
owner: impl Into<MultiLocation>,
|
||||
unlocker: impl Into<Location>,
|
||||
asset: impl Into<Asset>,
|
||||
owner: impl Into<Location>,
|
||||
) {
|
||||
ALLOWED_UNLOCKS.with(|l| {
|
||||
l.borrow_mut()
|
||||
@@ -568,17 +568,17 @@ pub fn disallow_unlock(
|
||||
.saturating_take(asset.into().into())
|
||||
});
|
||||
}
|
||||
pub fn unlock_allowed(unlocker: &MultiLocation, asset: &MultiAsset, owner: &MultiLocation) -> bool {
|
||||
pub fn unlock_allowed(unlocker: &Location, asset: &Asset, owner: &Location) -> bool {
|
||||
ALLOWED_UNLOCKS.with(|l| {
|
||||
l.borrow_mut()
|
||||
.get(&(*owner, *unlocker))
|
||||
.get(&(owner.clone(), unlocker.clone()))
|
||||
.map_or(false, |x| x.contains_asset(asset))
|
||||
})
|
||||
}
|
||||
pub fn allow_request_unlock(
|
||||
locker: impl Into<MultiLocation>,
|
||||
asset: impl Into<MultiAsset>,
|
||||
owner: impl Into<MultiLocation>,
|
||||
locker: impl Into<Location>,
|
||||
asset: impl Into<Asset>,
|
||||
owner: impl Into<Location>,
|
||||
) {
|
||||
ALLOWED_REQUEST_UNLOCKS.with(|l| {
|
||||
l.borrow_mut()
|
||||
@@ -588,9 +588,9 @@ pub fn allow_request_unlock(
|
||||
});
|
||||
}
|
||||
pub fn disallow_request_unlock(
|
||||
locker: impl Into<MultiLocation>,
|
||||
asset: impl Into<MultiAsset>,
|
||||
owner: impl Into<MultiLocation>,
|
||||
locker: impl Into<Location>,
|
||||
asset: impl Into<Asset>,
|
||||
owner: impl Into<Location>,
|
||||
) {
|
||||
ALLOWED_REQUEST_UNLOCKS.with(|l| {
|
||||
l.borrow_mut()
|
||||
@@ -599,14 +599,10 @@ pub fn disallow_request_unlock(
|
||||
.saturating_take(asset.into().into())
|
||||
});
|
||||
}
|
||||
pub fn request_unlock_allowed(
|
||||
locker: &MultiLocation,
|
||||
asset: &MultiAsset,
|
||||
owner: &MultiLocation,
|
||||
) -> bool {
|
||||
pub fn request_unlock_allowed(locker: &Location, asset: &Asset, owner: &Location) -> bool {
|
||||
ALLOWED_REQUEST_UNLOCKS.with(|l| {
|
||||
l.borrow_mut()
|
||||
.get(&(*owner, *locker))
|
||||
.get(&(owner.clone(), locker.clone()))
|
||||
.map_or(false, |x| x.contains_asset(asset))
|
||||
})
|
||||
}
|
||||
@@ -616,11 +612,11 @@ impl Enact for TestTicket {
|
||||
fn enact(self) -> Result<(), LockError> {
|
||||
match &self.0 {
|
||||
LockTraceItem::Lock { unlocker, asset, owner } =>
|
||||
allow_unlock(*unlocker, asset.clone(), *owner),
|
||||
allow_unlock(unlocker.clone(), asset.clone(), owner.clone()),
|
||||
LockTraceItem::Unlock { unlocker, asset, owner } =>
|
||||
disallow_unlock(*unlocker, asset.clone(), *owner),
|
||||
disallow_unlock(unlocker.clone(), asset.clone(), owner.clone()),
|
||||
LockTraceItem::Reduce { locker, asset, owner } =>
|
||||
disallow_request_unlock(*locker, asset.clone(), *owner),
|
||||
disallow_request_unlock(locker.clone(), asset.clone(), owner.clone()),
|
||||
_ => {},
|
||||
}
|
||||
LOCK_TRACE.with(move |l| l.borrow_mut().push(self.0));
|
||||
@@ -635,38 +631,34 @@ impl AssetLock for TestAssetLock {
|
||||
type ReduceTicket = TestTicket;
|
||||
|
||||
fn prepare_lock(
|
||||
unlocker: MultiLocation,
|
||||
asset: MultiAsset,
|
||||
owner: MultiLocation,
|
||||
unlocker: Location,
|
||||
asset: Asset,
|
||||
owner: Location,
|
||||
) -> Result<Self::LockTicket, LockError> {
|
||||
ensure!(assets(owner).contains_asset(&asset), LockError::AssetNotOwned);
|
||||
ensure!(assets(owner.clone()).contains_asset(&asset), LockError::AssetNotOwned);
|
||||
Ok(TestTicket(LockTraceItem::Lock { unlocker, asset, owner }))
|
||||
}
|
||||
|
||||
fn prepare_unlock(
|
||||
unlocker: MultiLocation,
|
||||
asset: MultiAsset,
|
||||
owner: MultiLocation,
|
||||
unlocker: Location,
|
||||
asset: Asset,
|
||||
owner: Location,
|
||||
) -> Result<Self::UnlockTicket, LockError> {
|
||||
ensure!(unlock_allowed(&unlocker, &asset, &owner), LockError::NotLocked);
|
||||
Ok(TestTicket(LockTraceItem::Unlock { unlocker, asset, owner }))
|
||||
}
|
||||
|
||||
fn note_unlockable(
|
||||
locker: MultiLocation,
|
||||
asset: MultiAsset,
|
||||
owner: MultiLocation,
|
||||
) -> Result<(), LockError> {
|
||||
allow_request_unlock(locker, asset.clone(), owner);
|
||||
fn note_unlockable(locker: Location, asset: Asset, owner: Location) -> Result<(), LockError> {
|
||||
allow_request_unlock(locker.clone(), asset.clone(), owner.clone());
|
||||
let item = LockTraceItem::Note { locker, asset, owner };
|
||||
LOCK_TRACE.with(move |l| l.borrow_mut().push(item));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prepare_reduce_unlockable(
|
||||
locker: MultiLocation,
|
||||
asset: MultiAsset,
|
||||
owner: MultiLocation,
|
||||
locker: Location,
|
||||
asset: Asset,
|
||||
owner: Location,
|
||||
) -> Result<Self::ReduceTicket, xcm_executor::traits::LockError> {
|
||||
ensure!(request_unlock_allowed(&locker, &asset, &owner), LockError::NotLocked);
|
||||
Ok(TestTicket(LockTraceItem::Reduce { locker, asset, owner }))
|
||||
@@ -674,26 +666,26 @@ impl AssetLock for TestAssetLock {
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub static EXCHANGE_ASSETS: RefCell<Assets> = RefCell::new(Assets::new());
|
||||
pub static EXCHANGE_ASSETS: RefCell<AssetsInHolding> = RefCell::new(AssetsInHolding::new());
|
||||
}
|
||||
pub fn set_exchange_assets(assets: impl Into<MultiAssets>) {
|
||||
pub fn set_exchange_assets(assets: impl Into<Assets>) {
|
||||
EXCHANGE_ASSETS.with(|a| a.replace(assets.into().into()));
|
||||
}
|
||||
pub fn exchange_assets() -> MultiAssets {
|
||||
pub fn exchange_assets() -> Assets {
|
||||
EXCHANGE_ASSETS.with(|a| a.borrow().clone().into())
|
||||
}
|
||||
pub struct TestAssetExchange;
|
||||
impl AssetExchange for TestAssetExchange {
|
||||
fn exchange_asset(
|
||||
_origin: Option<&MultiLocation>,
|
||||
give: Assets,
|
||||
want: &MultiAssets,
|
||||
_origin: Option<&Location>,
|
||||
give: AssetsInHolding,
|
||||
want: &Assets,
|
||||
maximal: bool,
|
||||
) -> Result<Assets, Assets> {
|
||||
) -> Result<AssetsInHolding, AssetsInHolding> {
|
||||
let mut have = EXCHANGE_ASSETS.with(|l| l.borrow().clone());
|
||||
ensure!(have.contains_assets(want), give);
|
||||
let get = if maximal {
|
||||
std::mem::replace(&mut have, Assets::new())
|
||||
std::mem::replace(&mut have, AssetsInHolding::new())
|
||||
} else {
|
||||
have.saturating_take(want.clone().into())
|
||||
};
|
||||
@@ -703,16 +695,25 @@ impl AssetExchange for TestAssetExchange {
|
||||
}
|
||||
}
|
||||
|
||||
match_types! {
|
||||
pub type SiblingPrefix: impl Contains<MultiLocation> = {
|
||||
MultiLocation { parents: 1, interior: X1(Parachain(_)) }
|
||||
};
|
||||
pub type ChildPrefix: impl Contains<MultiLocation> = {
|
||||
MultiLocation { parents: 0, interior: X1(Parachain(_)) }
|
||||
};
|
||||
pub type ParentPrefix: impl Contains<MultiLocation> = {
|
||||
MultiLocation { parents: 1, interior: Here }
|
||||
};
|
||||
pub struct SiblingPrefix;
|
||||
impl Contains<Location> for SiblingPrefix {
|
||||
fn contains(loc: &Location) -> bool {
|
||||
matches!(loc.unpack(), (1, [Parachain(_)]))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ChildPrefix;
|
||||
impl Contains<Location> for ChildPrefix {
|
||||
fn contains(loc: &Location) -> bool {
|
||||
matches!(loc.unpack(), (0, [Parachain(_)]))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ParentPrefix;
|
||||
impl Contains<Location> for ParentPrefix {
|
||||
fn contains(loc: &Location) -> bool {
|
||||
matches!(loc.unpack(), (1, []))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestConfig;
|
||||
@@ -743,7 +744,7 @@ impl Config for TestConfig {
|
||||
type Aliasers = AliasForeignAccountId32<SiblingPrefix>;
|
||||
}
|
||||
|
||||
pub fn fungible_multi_asset(location: MultiLocation, amount: u128) -> MultiAsset {
|
||||
pub fn fungible_multi_asset(location: Location, amount: u128) -> Asset {
|
||||
(AssetId::from(location), Fungibility::Fungible(amount)).into()
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ use super::*;
|
||||
|
||||
#[test]
|
||||
fn universal_origin_should_work() {
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into(), X1(Parachain(2)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into(), [Parachain(2)].into()]);
|
||||
clear_universal_aliases();
|
||||
// Parachain 1 may represent Kusama to us
|
||||
add_universal_alias(Parachain(1), Kusama);
|
||||
@@ -29,48 +29,57 @@ fn universal_origin_should_work() {
|
||||
UniversalOrigin(GlobalConsensus(Kusama)),
|
||||
TransferAsset { assets: (Parent, 100u128).into(), beneficiary: Here.into() },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(2),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::InvalidLocation }
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::InvalidLocation));
|
||||
|
||||
let message = Xcm(vec![
|
||||
UniversalOrigin(GlobalConsensus(Kusama)),
|
||||
TransferAsset { assets: (Parent, 100u128).into(), beneficiary: Here.into() },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::NotWithdrawable }
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(20, 20), XcmError::NotWithdrawable));
|
||||
|
||||
add_asset((Ancestor(2), GlobalConsensus(Kusama)), (Parent, 100));
|
||||
let message = Xcm(vec![
|
||||
UniversalOrigin(GlobalConsensus(Kusama)),
|
||||
TransferAsset { assets: (Parent, 100u128).into(), beneficiary: Here.into() },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(20, 20)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(20, 20) });
|
||||
assert_eq!(asset_list((Ancestor(2), GlobalConsensus(Kusama))), vec![]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn export_message_should_work() {
|
||||
// Bridge chain (assumed to be Relay) lets Parachain #1 have message execution for free.
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into()]);
|
||||
// Local parachain #1 issues a transfer asset on Polkadot Relay-chain, transfering 100 Planck to
|
||||
// Polkadot parachain #2.
|
||||
let expected_message = Xcm(vec![TransferAsset {
|
||||
@@ -83,14 +92,15 @@ fn export_message_should_work() {
|
||||
destination: Here,
|
||||
xcm: expected_message.clone(),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
let uni_src = (ByGenesis([0; 32]), Parachain(42), Parachain(1)).into();
|
||||
assert_eq!(
|
||||
exported_xcm(),
|
||||
@@ -101,40 +111,46 @@ fn export_message_should_work() {
|
||||
#[test]
|
||||
fn unpaid_execution_should_work() {
|
||||
// Bridge chain (assumed to be Relay) lets Parachain #1 have message execution for free.
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into()]);
|
||||
// Bridge chain (assumed to be Relay) lets Parachain #2 have message execution for free if it
|
||||
// asks.
|
||||
AllowExplicitUnpaidFrom::set(vec![X1(Parachain(2)).into()]);
|
||||
AllowExplicitUnpaidFrom::set(vec![[Parachain(2)].into()]);
|
||||
// Asking for unpaid execution of up to 9 weight on the assumption it is origin of #2.
|
||||
let message = Xcm(vec![UnpaidExecution {
|
||||
weight_limit: Limited(Weight::from_parts(9, 9)),
|
||||
check_origin: Some(Parachain(2).into()),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message.clone(),
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::BadOrigin));
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::BadOrigin }
|
||||
);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(2),
|
||||
message.clone(),
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Error(XcmError::Barrier));
|
||||
assert_eq!(r, Outcome::Error { error: XcmError::Barrier });
|
||||
|
||||
let message = Xcm(vec![UnpaidExecution {
|
||||
weight_limit: Limited(Weight::from_parts(10, 10)),
|
||||
check_origin: Some(Parachain(2).into()),
|
||||
}]);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(2),
|
||||
message.clone(),
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
}
|
||||
|
||||
@@ -115,14 +115,14 @@ impl pallet_assets::Config for Test {
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const RelayLocation: MultiLocation = Here.into_location();
|
||||
pub const RelayLocation: Location = Here.into_location();
|
||||
pub const AnyNetwork: Option<NetworkId> = None;
|
||||
pub UniversalLocation: InteriorMultiLocation = (ByGenesis([0; 32]), Parachain(42)).into();
|
||||
pub UniversalLocation: InteriorLocation = (ByGenesis([0; 32]), Parachain(42)).into();
|
||||
pub UnitWeightCost: u64 = 1_000;
|
||||
pub static AdvertisedXcmVersion: u32 = 3;
|
||||
pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000);
|
||||
pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (Concrete(RelayLocation::get()), 1, 1);
|
||||
pub TrustedAssets: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into());
|
||||
pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (AssetId(RelayLocation::get()), 1, 1);
|
||||
pub TrustedAssets: (AssetFilter, Location) = (All.into(), Here.into());
|
||||
pub const MaxInstructions: u32 = 100;
|
||||
pub const MaxAssetsIntoHolding: u32 = 64;
|
||||
pub CheckingAccount: AccountId = XcmPallet::check_account();
|
||||
@@ -130,28 +130,25 @@ parameter_types! {
|
||||
|
||||
type AssetIdForAssets = u128;
|
||||
|
||||
pub struct FromMultiLocationToAsset<MultiLocation, AssetId>(
|
||||
core::marker::PhantomData<(MultiLocation, AssetId)>,
|
||||
);
|
||||
impl MaybeEquivalence<MultiLocation, AssetIdForAssets>
|
||||
for FromMultiLocationToAsset<MultiLocation, AssetIdForAssets>
|
||||
pub struct FromLocationToAsset<Location, AssetId>(core::marker::PhantomData<(Location, AssetId)>);
|
||||
impl MaybeEquivalence<Location, AssetIdForAssets>
|
||||
for FromLocationToAsset<Location, AssetIdForAssets>
|
||||
{
|
||||
fn convert(value: &MultiLocation) -> Option<AssetIdForAssets> {
|
||||
match value {
|
||||
MultiLocation { parents: 0, interior: Here } => Some(0 as AssetIdForAssets),
|
||||
MultiLocation { parents: 1, interior: Here } => Some(1 as AssetIdForAssets),
|
||||
MultiLocation { parents: 0, interior: X2(PalletInstance(1), GeneralIndex(index)) }
|
||||
if ![0, 1].contains(index) =>
|
||||
fn convert(value: &Location) -> Option<AssetIdForAssets> {
|
||||
match value.unpack() {
|
||||
(0, []) => Some(0 as AssetIdForAssets),
|
||||
(1, []) => Some(1 as AssetIdForAssets),
|
||||
(0, [PalletInstance(1), GeneralIndex(index)]) if ![0, 1].contains(index) =>
|
||||
Some(*index as AssetIdForAssets),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_back(value: &AssetIdForAssets) -> Option<MultiLocation> {
|
||||
fn convert_back(value: &AssetIdForAssets) -> Option<Location> {
|
||||
match value {
|
||||
0u128 => Some(MultiLocation { parents: 1, interior: Here }),
|
||||
0u128 => Some(Location { parents: 1, interior: Here }),
|
||||
para_id @ 1..=1000 =>
|
||||
Some(MultiLocation { parents: 1, interior: X1(Parachain(*para_id as u32)) }),
|
||||
Some(Location { parents: 1, interior: [Parachain(*para_id as u32)].into() }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -163,7 +160,7 @@ pub type LocalAssetsTransactor = FungiblesAdapter<
|
||||
ConvertedConcreteId<
|
||||
AssetIdForAssets,
|
||||
Balance,
|
||||
FromMultiLocationToAsset<MultiLocation, AssetIdForAssets>,
|
||||
FromLocationToAsset<Location, AssetIdForAssets>,
|
||||
JustTry,
|
||||
>,
|
||||
SovereignAccountOf,
|
||||
@@ -187,10 +184,10 @@ impl WeightTrader for DummyWeightTrader {
|
||||
fn buy_weight(
|
||||
&mut self,
|
||||
_weight: Weight,
|
||||
_payment: xcm_executor::Assets,
|
||||
_payment: xcm_executor::AssetsInHolding,
|
||||
_context: &XcmContext,
|
||||
) -> Result<xcm_executor::Assets, XcmError> {
|
||||
Ok(xcm_executor::Assets::default())
|
||||
) -> Result<xcm_executor::AssetsInHolding, XcmError> {
|
||||
Ok(xcm_executor::AssetsInHolding::default())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,13 +225,10 @@ parameter_types! {
|
||||
|
||||
pub struct TreasuryToAccount;
|
||||
impl ConvertLocation<AccountId> for TreasuryToAccount {
|
||||
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
|
||||
match location {
|
||||
MultiLocation {
|
||||
parents: 1,
|
||||
interior:
|
||||
X2(Parachain(42), Plurality { id: BodyId::Treasury, part: BodyPart::Voice }),
|
||||
} => Some(TreasuryAccountId::get()), // Hardcoded test treasury account id
|
||||
fn convert_location(location: &Location) -> Option<AccountId> {
|
||||
match location.unpack() {
|
||||
(1, [Parachain(42), Plurality { id: BodyId::Treasury, part: BodyPart::Voice }]) =>
|
||||
Some(TreasuryAccountId::get()), // Hardcoded test treasury account id
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -277,7 +271,7 @@ pub const INITIAL_BALANCE: Balance = 100 * UNITS;
|
||||
pub const MINIMUM_BALANCE: Balance = 1 * UNITS;
|
||||
|
||||
pub fn sibling_chain_account_id(para_id: u32, account: [u8; 32]) -> AccountId {
|
||||
let location: MultiLocation =
|
||||
let location: Location =
|
||||
(Parent, Parachain(para_id), Junction::AccountId32 { id: account, network: None }).into();
|
||||
SovereignAccountOf::convert_location(&location).unwrap()
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ use frame_support::{assert_ok, traits::tokens::Pay};
|
||||
|
||||
/// Type representing both a location and an asset that is held at that location.
|
||||
/// The id of the held asset is relative to the location where it is being held.
|
||||
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Encode, Decode, Clone, PartialEq, Eq)]
|
||||
pub struct AssetKind {
|
||||
destination: MultiLocation,
|
||||
destination: Location,
|
||||
asset_id: AssetId,
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ impl sp_runtime::traits::TryConvert<AssetKind, LocatableAssetId> for LocatableAs
|
||||
|
||||
parameter_types! {
|
||||
pub SenderAccount: AccountId = AccountId::new([3u8; 32]);
|
||||
pub InteriorAccount: InteriorMultiLocation = AccountId32 { id: SenderAccount::get().into(), network: None }.into();
|
||||
pub InteriorBody: InteriorMultiLocation = Plurality { id: BodyId::Treasury, part: BodyPart::Voice }.into();
|
||||
pub InteriorAccount: InteriorLocation = AccountId32 { id: SenderAccount::get().into(), network: None }.into();
|
||||
pub InteriorBody: InteriorLocation = Plurality { id: BodyId::Treasury, part: BodyPart::Voice }.into();
|
||||
pub Timeout: BlockNumber = 5; // 5 blocks
|
||||
}
|
||||
|
||||
@@ -91,13 +91,19 @@ fn pay_over_xcm_works() {
|
||||
vec![((Parent, Parachain(2)).into(), expected_message, expected_hash)]
|
||||
);
|
||||
|
||||
let (_, message, hash) = sent_xcm()[0].clone();
|
||||
let (_, message, mut hash) = sent_xcm()[0].clone();
|
||||
let message =
|
||||
Xcm::<<XcmConfig as xcm_executor::Config>::RuntimeCall>::from(message.clone());
|
||||
|
||||
// Execute message in parachain 2 with parachain 42's origin
|
||||
let origin = (Parent, Parachain(42));
|
||||
XcmExecutor::<XcmConfig>::execute_xcm(origin, message, hash, Weight::MAX);
|
||||
XcmExecutor::<XcmConfig>::prepare_and_execute(
|
||||
origin,
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::MAX,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(mock::Assets::balance(0, &recipient), amount);
|
||||
});
|
||||
}
|
||||
@@ -152,13 +158,19 @@ fn pay_over_xcm_governance_body() {
|
||||
vec![((Parent, Parachain(2)).into(), expected_message, expected_hash)]
|
||||
);
|
||||
|
||||
let (_, message, hash) = sent_xcm()[0].clone();
|
||||
let (_, message, mut hash) = sent_xcm()[0].clone();
|
||||
let message =
|
||||
Xcm::<<XcmConfig as xcm_executor::Config>::RuntimeCall>::from(message.clone());
|
||||
|
||||
// Execute message in parachain 2 with parachain 42's origin
|
||||
let origin = (Parent, Parachain(42));
|
||||
XcmExecutor::<XcmConfig>::execute_xcm(origin, message, hash, Weight::MAX);
|
||||
XcmExecutor::<XcmConfig>::prepare_and_execute(
|
||||
origin,
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::MAX,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(mock::Assets::balance(relay_asset_index, &recipient), amount);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,9 +25,9 @@ use frame_support::{
|
||||
use sp_runtime::{traits::ConvertToValue, DispatchResult};
|
||||
|
||||
parameter_types! {
|
||||
pub Interior: InteriorMultiLocation = Plurality { id: BodyId::Treasury, part: BodyPart::Voice }.into();
|
||||
pub Interior: InteriorLocation = Plurality { id: BodyId::Treasury, part: BodyPart::Voice }.into();
|
||||
pub Timeout: BlockNumber = 5;
|
||||
pub AssetHub: MultiLocation = (Parent, Parachain(1)).into();
|
||||
pub AssetHub: Location = (Parent, Parachain(1)).into();
|
||||
pub AssetIdGeneralIndex: u128 = 100;
|
||||
pub AssetHubAssetId: AssetId = (PalletInstance(1), GeneralIndex(AssetIdGeneralIndex::get())).into();
|
||||
pub LocatableAsset: LocatableAssetId = LocatableAssetId { asset_id: AssetHubAssetId::get(), location: AssetHub::get() };
|
||||
@@ -140,7 +140,7 @@ fn salary_pay_over_xcm_works() {
|
||||
assert_ok!(Salary::payout(RuntimeOrigin::signed(recipient.clone())));
|
||||
|
||||
// Get message from mock transport layer
|
||||
let (_, message, hash) = sent_xcm()[0].clone();
|
||||
let (_, message, mut hash) = sent_xcm()[0].clone();
|
||||
// Change type from `Xcm<()>` to `Xcm<RuntimeCall>` to be able to execute later
|
||||
let message =
|
||||
Xcm::<<XcmConfig as xcm_executor::Config>::RuntimeCall>::from(message.clone());
|
||||
@@ -164,7 +164,13 @@ fn salary_pay_over_xcm_works() {
|
||||
assert_eq!(message, expected_message);
|
||||
|
||||
// Execute message as the asset hub
|
||||
XcmExecutor::<XcmConfig>::execute_xcm((Parent, Parachain(42)), message, hash, Weight::MAX);
|
||||
XcmExecutor::<XcmConfig>::prepare_and_execute(
|
||||
(Parent, Parachain(42)),
|
||||
message,
|
||||
&mut hash,
|
||||
Weight::MAX,
|
||||
Weight::zero(),
|
||||
);
|
||||
|
||||
// Recipient receives the payment
|
||||
assert_eq!(
|
||||
|
||||
@@ -18,7 +18,7 @@ use super::*;
|
||||
|
||||
#[test]
|
||||
fn pallet_query_should_work() {
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into()]);
|
||||
// They want to transfer 100 of our native asset from sovereign account of parachain #1 into #2
|
||||
// and let them know to hand it to account #3.
|
||||
let message = Xcm(vec![QueryPallet {
|
||||
@@ -29,14 +29,15 @@ fn pallet_query_should_work() {
|
||||
max_weight: Weight::from_parts(50, 50),
|
||||
},
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
|
||||
let expected_msg = Xcm::<()>(vec![QueryResponse {
|
||||
query_id: 1,
|
||||
@@ -50,7 +51,7 @@ fn pallet_query_should_work() {
|
||||
|
||||
#[test]
|
||||
fn pallet_query_with_results_should_work() {
|
||||
AllowUnpaidFrom::set(vec![X1(Parachain(1)).into()]);
|
||||
AllowUnpaidFrom::set(vec![[Parachain(1)].into()]);
|
||||
// They want to transfer 100 of our native asset from sovereign account of parachain #1 into #2
|
||||
// and let them know to hand it to account #3.
|
||||
let message = Xcm(vec![QueryPallet {
|
||||
@@ -61,14 +62,15 @@ fn pallet_query_with_results_should_work() {
|
||||
max_weight: Weight::from_parts(50, 50),
|
||||
},
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parachain(1),
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
Weight::from_parts(50, 50),
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
|
||||
let expected_msg = Xcm::<()>(vec![QueryResponse {
|
||||
query_id: 1,
|
||||
@@ -106,15 +108,27 @@ fn prepaid_result_of_query_should_get_free_execution() {
|
||||
max_weight: Weight::from_parts(10, 10),
|
||||
querier: Some(Here.into()),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(10, 10);
|
||||
|
||||
// First time the response gets through since we're expecting it...
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message.clone(), hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message.clone(),
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
assert_eq!(response(query_id).unwrap(), the_response);
|
||||
|
||||
// Second time it doesn't, since we're not.
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message.clone(), hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Error(XcmError::Barrier));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message.clone(),
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Error { error: XcmError::Barrier });
|
||||
}
|
||||
|
||||
@@ -25,10 +25,16 @@ fn transacting_should_work() {
|
||||
require_weight_at_most: Weight::from_parts(50, 50),
|
||||
call: TestCall::Any(Weight::from_parts(50, 50), None).encode().into(),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(60, 60);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(60, 60)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(60, 60) });
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -40,10 +46,19 @@ fn transacting_should_respect_max_weight_requirement() {
|
||||
require_weight_at_most: Weight::from_parts(40, 40),
|
||||
call: TestCall::Any(Weight::from_parts(50, 50), None).encode().into(),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(60, 60);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(50, 50), XcmError::MaxWeightInvalid));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(50, 50), error: XcmError::MaxWeightInvalid }
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -57,20 +72,26 @@ fn transacting_should_refund_weight() {
|
||||
.encode()
|
||||
.into(),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(60, 60);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(40, 40)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(40, 40) });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn paid_transacting_should_refund_payment_for_unused_weight() {
|
||||
let one: MultiLocation = AccountIndex64 { index: 1, network: None }.into();
|
||||
AllowPaidFrom::set(vec![one]);
|
||||
let one: Location = AccountIndex64 { index: 1, network: None }.into();
|
||||
AllowPaidFrom::set(vec![one.clone()]);
|
||||
add_asset(AccountIndex64 { index: 1, network: None }, (Parent, 200u128));
|
||||
WeightPrice::set((Parent.into(), 1_000_000_000_000, 1024 * 1024));
|
||||
|
||||
let origin = one;
|
||||
let origin = one.clone();
|
||||
let fees = (Parent, 200u128).into();
|
||||
let message = Xcm::<TestCall>(vec![
|
||||
WithdrawAsset((Parent, 200u128).into()), // enough for 200 units of weight.
|
||||
@@ -86,10 +107,16 @@ fn paid_transacting_should_refund_payment_for_unused_weight() {
|
||||
RefundSurplus,
|
||||
DepositAsset { assets: AllCounted(1).into(), beneficiary: one },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(100, 100);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(origin, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(60, 60)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
origin,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(60, 60) });
|
||||
assert_eq!(
|
||||
asset_list(AccountIndex64 { index: 1, network: None }),
|
||||
vec![(Parent, 80u128).into()]
|
||||
@@ -112,10 +139,16 @@ fn report_successful_transact_status_should_work() {
|
||||
max_weight: Weight::from_parts(5000, 5000),
|
||||
}),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(70, 70);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(70, 70)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(70, 70) });
|
||||
let expected_msg = Xcm(vec![QueryResponse {
|
||||
response: Response::DispatchResult(MaybeErrorCode::Success),
|
||||
query_id: 42,
|
||||
@@ -142,10 +175,16 @@ fn report_failed_transact_status_should_work() {
|
||||
max_weight: Weight::from_parts(5000, 5000),
|
||||
}),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(70, 70);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(70, 70)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(70, 70) });
|
||||
let expected_msg = Xcm(vec![QueryResponse {
|
||||
response: Response::DispatchResult(vec![2].into()),
|
||||
query_id: 42,
|
||||
@@ -168,10 +207,16 @@ fn expect_successful_transact_status_should_work() {
|
||||
},
|
||||
ExpectTransactStatus(MaybeErrorCode::Success),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(70, 70);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(70, 70)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(70, 70) });
|
||||
|
||||
let message = Xcm::<TestCall>(vec![
|
||||
Transact {
|
||||
@@ -181,10 +226,19 @@ fn expect_successful_transact_status_should_work() {
|
||||
},
|
||||
ExpectTransactStatus(MaybeErrorCode::Success),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(70, 70);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(70, 70), XcmError::ExpectationFalse));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(70, 70), error: XcmError::ExpectationFalse }
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -199,10 +253,16 @@ fn expect_failed_transact_status_should_work() {
|
||||
},
|
||||
ExpectTransactStatus(vec![2].into()),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(70, 70);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(70, 70)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(70, 70) });
|
||||
|
||||
let message = Xcm::<TestCall>(vec![
|
||||
Transact {
|
||||
@@ -212,10 +272,19 @@ fn expect_failed_transact_status_should_work() {
|
||||
},
|
||||
ExpectTransactStatus(vec![2].into()),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(70, 70);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(70, 70), XcmError::ExpectationFalse));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(70, 70), error: XcmError::ExpectationFalse }
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -235,10 +304,16 @@ fn clear_transact_status_should_work() {
|
||||
max_weight: Weight::from_parts(5000, 5000),
|
||||
}),
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(80, 80);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(80, 80)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(80, 80) });
|
||||
let expected_msg = Xcm(vec![QueryResponse {
|
||||
response: Response::DispatchResult(MaybeErrorCode::Success),
|
||||
query_id: 42,
|
||||
|
||||
@@ -25,23 +25,41 @@ fn simple_version_subscriptions_should_work() {
|
||||
SetAppendix(Xcm(vec![])),
|
||||
SubscribeVersion { query_id: 42, max_response_weight: Weight::from_parts(5000, 5000) },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(20, 20);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(origin, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Error(XcmError::Barrier));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
origin,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Error { error: XcmError::Barrier });
|
||||
|
||||
let origin = Parachain(1000);
|
||||
let message = Xcm::<TestCall>(vec![SubscribeVersion {
|
||||
query_id: 42,
|
||||
max_response_weight: Weight::from_parts(5000, 5000),
|
||||
}]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(10, 10);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(origin, message.clone(), hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Error(XcmError::Barrier));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
origin,
|
||||
message.clone(),
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Error { error: XcmError::Barrier });
|
||||
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
|
||||
assert_eq!(
|
||||
SubscriptionRequests::get(),
|
||||
@@ -53,33 +71,36 @@ fn simple_version_subscriptions_should_work() {
|
||||
fn version_subscription_instruction_should_work() {
|
||||
let origin = Parachain(1000);
|
||||
let message = Xcm::<TestCall>(vec![
|
||||
DescendOrigin(X1(AccountIndex64 { index: 1, network: None })),
|
||||
DescendOrigin([AccountIndex64 { index: 1, network: None }].into()),
|
||||
SubscribeVersion { query_id: 42, max_response_weight: Weight::from_parts(5000, 5000) },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(20, 20);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm_in_credit(
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
origin,
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
weight_limit,
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(20, 20), XcmError::BadOrigin));
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::BadOrigin }
|
||||
);
|
||||
|
||||
let message = Xcm::<TestCall>(vec![
|
||||
SetAppendix(Xcm(vec![])),
|
||||
SubscribeVersion { query_id: 42, max_response_weight: Weight::from_parts(5000, 5000) },
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm_in_credit(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
origin,
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
weight_limit,
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(20, 20)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(20, 20) });
|
||||
|
||||
assert_eq!(
|
||||
SubscriptionRequests::get(),
|
||||
@@ -93,20 +114,38 @@ fn simple_version_unsubscriptions_should_work() {
|
||||
|
||||
let origin = Parachain(1000);
|
||||
let message = Xcm::<TestCall>(vec![SetAppendix(Xcm(vec![])), UnsubscribeVersion]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(20, 20);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(origin, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Error(XcmError::Barrier));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
origin,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Error { error: XcmError::Barrier });
|
||||
|
||||
let origin = Parachain(1000);
|
||||
let message = Xcm::<TestCall>(vec![UnsubscribeVersion]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(10, 10);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(origin, message.clone(), hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Error(XcmError::Barrier));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
origin,
|
||||
message.clone(),
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Error { error: XcmError::Barrier });
|
||||
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Parent, message, hash, weight_limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(10, 10)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Parent,
|
||||
message,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(10, 10) });
|
||||
|
||||
assert_eq!(SubscriptionRequests::get(), vec![(Parent.into(), None)]);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
@@ -118,31 +157,34 @@ fn version_unsubscription_instruction_should_work() {
|
||||
|
||||
// Not allowed to do it when origin has been changed.
|
||||
let message = Xcm::<TestCall>(vec![
|
||||
DescendOrigin(X1(AccountIndex64 { index: 1, network: None })),
|
||||
DescendOrigin([AccountIndex64 { index: 1, network: None }].into()),
|
||||
UnsubscribeVersion,
|
||||
]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let weight_limit = Weight::from_parts(20, 20);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm_in_credit(
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
origin,
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
weight_limit,
|
||||
);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(20, 20), XcmError::BadOrigin));
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::BadOrigin }
|
||||
);
|
||||
|
||||
// Fine to do it when origin is untouched.
|
||||
let message = Xcm::<TestCall>(vec![SetAppendix(Xcm(vec![])), UnsubscribeVersion]);
|
||||
let hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm_in_credit(
|
||||
let mut hash = fake_message_hash(&message);
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
origin,
|
||||
message,
|
||||
hash,
|
||||
&mut hash,
|
||||
weight_limit,
|
||||
weight_limit,
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(20, 20)));
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(20, 20) });
|
||||
|
||||
assert_eq!(SubscriptionRequests::get(), vec![(Parachain(1000).into(), None)]);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
|
||||
@@ -74,45 +74,78 @@ fn errors_should_return_unused_weight() {
|
||||
// First xfer results in an error on the last message only
|
||||
TransferAsset {
|
||||
assets: (Here, 1u128).into(),
|
||||
beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(),
|
||||
beneficiary: [AccountIndex64 { index: 3, network: None }].into(),
|
||||
},
|
||||
// Second xfer results in error third message and after
|
||||
TransferAsset {
|
||||
assets: (Here, 2u128).into(),
|
||||
beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(),
|
||||
beneficiary: [AccountIndex64 { index: 3, network: None }].into(),
|
||||
},
|
||||
// Third xfer results in error second message and after
|
||||
TransferAsset {
|
||||
assets: (Here, 4u128).into(),
|
||||
beneficiary: X1(AccountIndex64 { index: 3, network: None }).into(),
|
||||
beneficiary: [AccountIndex64 { index: 3, network: None }].into(),
|
||||
},
|
||||
]);
|
||||
// Weight limit of 70 is needed.
|
||||
let limit = <TestConfig as Config>::Weigher::weight(&mut message).unwrap();
|
||||
assert_eq!(limit, Weight::from_parts(30, 30));
|
||||
|
||||
let hash = fake_message_hash(&message);
|
||||
let mut hash = fake_message_hash(&message);
|
||||
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Here, message.clone(), hash, limit);
|
||||
assert_eq!(r, Outcome::Complete(Weight::from_parts(30, 30)));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Here,
|
||||
message.clone(),
|
||||
&mut hash,
|
||||
limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(r, Outcome::Complete { used: Weight::from_parts(30, 30) });
|
||||
assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![(Here, 7u128).into()]);
|
||||
assert_eq!(asset_list(Here), vec![(Here, 4u128).into()]);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Here, message.clone(), hash, limit);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(30, 30), XcmError::NotWithdrawable));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Here,
|
||||
message.clone(),
|
||||
&mut hash,
|
||||
limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(30, 30), error: XcmError::NotWithdrawable }
|
||||
);
|
||||
assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![(Here, 10u128).into()]);
|
||||
assert_eq!(asset_list(Here), vec![(Here, 1u128).into()]);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Here, message.clone(), hash, limit);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(20, 20), XcmError::NotWithdrawable));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Here,
|
||||
message.clone(),
|
||||
&mut hash,
|
||||
limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::NotWithdrawable }
|
||||
);
|
||||
assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![(Here, 11u128).into()]);
|
||||
assert_eq!(asset_list(Here), vec![]);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
|
||||
let r = XcmExecutor::<TestConfig>::execute_xcm(Here, message, hash, limit);
|
||||
assert_eq!(r, Outcome::Incomplete(Weight::from_parts(10, 10), XcmError::NotWithdrawable));
|
||||
let r = XcmExecutor::<TestConfig>::prepare_and_execute(
|
||||
Here,
|
||||
message,
|
||||
&mut hash,
|
||||
limit,
|
||||
Weight::zero(),
|
||||
);
|
||||
assert_eq!(
|
||||
r,
|
||||
Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::NotWithdrawable }
|
||||
);
|
||||
assert_eq!(asset_list(AccountIndex64 { index: 3, network: None }), vec![(Here, 11u128).into()]);
|
||||
assert_eq!(asset_list(Here), vec![]);
|
||||
assert_eq!(sent_xcm(), vec![]);
|
||||
@@ -148,8 +181,8 @@ fn weight_bounds_should_respect_instructions_limit() {
|
||||
|
||||
#[test]
|
||||
fn weight_trader_tuple_should_work() {
|
||||
let para_1: MultiLocation = Parachain(1).into();
|
||||
let para_2: MultiLocation = Parachain(2).into();
|
||||
let para_1: Location = Parachain(1).into();
|
||||
let para_2: Location = Parachain(2).into();
|
||||
|
||||
parameter_types! {
|
||||
pub static HereWeightPrice: (AssetId, u128, u128) =
|
||||
@@ -186,7 +219,11 @@ fn weight_trader_tuple_should_work() {
|
||||
let mut traders = Traders::new();
|
||||
// trader one failed; trader two buys weight
|
||||
assert_eq!(
|
||||
traders.buy_weight(Weight::from_parts(5, 5), fungible_multi_asset(para_1, 10).into(), &ctx),
|
||||
traders.buy_weight(
|
||||
Weight::from_parts(5, 5),
|
||||
fungible_multi_asset(para_1.clone(), 10).into(),
|
||||
&ctx
|
||||
),
|
||||
Ok(vec![].into()),
|
||||
);
|
||||
// trader two refunds
|
||||
|
||||
@@ -28,18 +28,18 @@ use SendError::*;
|
||||
/// chain, itself situated at `universal_local` within the consensus universe. If
|
||||
/// `dest` is not a location in remote consensus, then an error is returned.
|
||||
pub fn ensure_is_remote(
|
||||
universal_local: impl Into<InteriorMultiLocation>,
|
||||
dest: impl Into<MultiLocation>,
|
||||
) -> Result<(NetworkId, InteriorMultiLocation), MultiLocation> {
|
||||
universal_local: impl Into<InteriorLocation>,
|
||||
dest: impl Into<Location>,
|
||||
) -> Result<(NetworkId, InteriorLocation), Location> {
|
||||
let dest = dest.into();
|
||||
let universal_local = universal_local.into();
|
||||
let local_net = match universal_local.global_consensus() {
|
||||
Ok(x) => x,
|
||||
Err(_) => return Err(dest),
|
||||
};
|
||||
let universal_destination: InteriorMultiLocation = universal_local
|
||||
let universal_destination: InteriorLocation = universal_local
|
||||
.into_location()
|
||||
.appended_with(dest)
|
||||
.appended_with(dest.clone())
|
||||
.map_err(|x| x.1)?
|
||||
.try_into()?;
|
||||
let (remote_dest, remote_net) = match universal_destination.split_first() {
|
||||
@@ -59,18 +59,18 @@ pub fn ensure_is_remote(
|
||||
pub struct UnpaidLocalExporter<Exporter, UniversalLocation>(
|
||||
PhantomData<(Exporter, UniversalLocation)>,
|
||||
);
|
||||
impl<Exporter: ExportXcm, UniversalLocation: Get<InteriorMultiLocation>> SendXcm
|
||||
impl<Exporter: ExportXcm, UniversalLocation: Get<InteriorLocation>> SendXcm
|
||||
for UnpaidLocalExporter<Exporter, UniversalLocation>
|
||||
{
|
||||
type Ticket = Exporter::Ticket;
|
||||
|
||||
fn validate(
|
||||
dest: &mut Option<MultiLocation>,
|
||||
dest: &mut Option<Location>,
|
||||
xcm: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Exporter::Ticket> {
|
||||
let d = dest.take().ok_or(MissingArgument)?;
|
||||
let universal_source = UniversalLocation::get();
|
||||
let devolved = match ensure_is_remote(universal_source, d) {
|
||||
let devolved = match ensure_is_remote(universal_source.clone(), d) {
|
||||
Ok(x) => x,
|
||||
Err(d) => {
|
||||
*dest = Some(d);
|
||||
@@ -96,18 +96,18 @@ pub trait ExporterFor {
|
||||
/// the bridge chain as well as payment for the use of the `ExportMessage` instruction.
|
||||
fn exporter_for(
|
||||
network: &NetworkId,
|
||||
remote_location: &InteriorMultiLocation,
|
||||
remote_location: &InteriorLocation,
|
||||
message: &Xcm<()>,
|
||||
) -> Option<(MultiLocation, Option<MultiAsset>)>;
|
||||
) -> Option<(Location, Option<Asset>)>;
|
||||
}
|
||||
|
||||
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||
impl ExporterFor for Tuple {
|
||||
fn exporter_for(
|
||||
network: &NetworkId,
|
||||
remote_location: &InteriorMultiLocation,
|
||||
remote_location: &InteriorLocation,
|
||||
message: &Xcm<()>,
|
||||
) -> Option<(MultiLocation, Option<MultiAsset>)> {
|
||||
) -> Option<(Location, Option<Asset>)> {
|
||||
for_tuples!( #(
|
||||
if let Some(r) = Tuple::exporter_for(network, remote_location, message) {
|
||||
return Some(r);
|
||||
@@ -125,21 +125,21 @@ pub struct NetworkExportTableItem {
|
||||
/// If `Some`, the requested remote location must be equal to one of the items in the vector.
|
||||
/// These are locations in the remote network.
|
||||
/// If `None`, then the check is skipped.
|
||||
pub remote_location_filter: Option<Vec<InteriorMultiLocation>>,
|
||||
pub remote_location_filter: Option<Vec<InteriorLocation>>,
|
||||
/// Locally-routable bridge with bridging capabilities to the `remote_network` and
|
||||
/// `remote_location`. See [`ExporterFor`] for more details.
|
||||
pub bridge: MultiLocation,
|
||||
pub bridge: Location,
|
||||
/// The local payment.
|
||||
/// See [`ExporterFor`] for more details.
|
||||
pub payment: Option<MultiAsset>,
|
||||
pub payment: Option<Asset>,
|
||||
}
|
||||
|
||||
impl NetworkExportTableItem {
|
||||
pub fn new(
|
||||
remote_network: NetworkId,
|
||||
remote_location_filter: Option<Vec<InteriorMultiLocation>>,
|
||||
bridge: MultiLocation,
|
||||
payment: Option<MultiAsset>,
|
||||
remote_location_filter: Option<Vec<InteriorLocation>>,
|
||||
bridge: Location,
|
||||
payment: Option<Asset>,
|
||||
) -> Self {
|
||||
Self { remote_network, remote_location_filter, bridge, payment }
|
||||
}
|
||||
@@ -152,9 +152,9 @@ pub struct NetworkExportTable<T>(sp_std::marker::PhantomData<T>);
|
||||
impl<T: Get<Vec<NetworkExportTableItem>>> ExporterFor for NetworkExportTable<T> {
|
||||
fn exporter_for(
|
||||
network: &NetworkId,
|
||||
remote_location: &InteriorMultiLocation,
|
||||
remote_location: &InteriorLocation,
|
||||
_: &Xcm<()>,
|
||||
) -> Option<(MultiLocation, Option<MultiAsset>)> {
|
||||
) -> Option<(Location, Option<Asset>)> {
|
||||
T::get()
|
||||
.into_iter()
|
||||
.find(|item| {
|
||||
@@ -194,16 +194,16 @@ pub fn forward_id_for(original_id: &XcmHash) -> XcmHash {
|
||||
pub struct UnpaidRemoteExporter<Bridges, Router, UniversalLocation>(
|
||||
PhantomData<(Bridges, Router, UniversalLocation)>,
|
||||
);
|
||||
impl<Bridges: ExporterFor, Router: SendXcm, UniversalLocation: Get<InteriorMultiLocation>> SendXcm
|
||||
impl<Bridges: ExporterFor, Router: SendXcm, UniversalLocation: Get<InteriorLocation>> SendXcm
|
||||
for UnpaidRemoteExporter<Bridges, Router, UniversalLocation>
|
||||
{
|
||||
type Ticket = Router::Ticket;
|
||||
|
||||
fn validate(
|
||||
dest: &mut Option<MultiLocation>,
|
||||
dest: &mut Option<Location>,
|
||||
msg: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Router::Ticket> {
|
||||
let d = dest.ok_or(MissingArgument)?;
|
||||
let d = dest.clone().ok_or(MissingArgument)?;
|
||||
let devolved = ensure_is_remote(UniversalLocation::get(), d).map_err(|_| NotApplicable)?;
|
||||
let (remote_network, remote_location) = devolved;
|
||||
let xcm = msg.take().ok_or(MissingArgument)?;
|
||||
@@ -261,17 +261,18 @@ impl<Bridges: ExporterFor, Router: SendXcm, UniversalLocation: Get<InteriorMulti
|
||||
pub struct SovereignPaidRemoteExporter<Bridges, Router, UniversalLocation>(
|
||||
PhantomData<(Bridges, Router, UniversalLocation)>,
|
||||
);
|
||||
impl<Bridges: ExporterFor, Router: SendXcm, UniversalLocation: Get<InteriorMultiLocation>> SendXcm
|
||||
impl<Bridges: ExporterFor, Router: SendXcm, UniversalLocation: Get<InteriorLocation>> SendXcm
|
||||
for SovereignPaidRemoteExporter<Bridges, Router, UniversalLocation>
|
||||
{
|
||||
type Ticket = Router::Ticket;
|
||||
|
||||
fn validate(
|
||||
dest: &mut Option<MultiLocation>,
|
||||
dest: &mut Option<Location>,
|
||||
msg: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Router::Ticket> {
|
||||
let d = *dest.as_ref().ok_or(MissingArgument)?;
|
||||
let devolved = ensure_is_remote(UniversalLocation::get(), d).map_err(|_| NotApplicable)?;
|
||||
let d = dest.as_ref().ok_or(MissingArgument)?;
|
||||
let devolved =
|
||||
ensure_is_remote(UniversalLocation::get(), d.clone()).map_err(|_| NotApplicable)?;
|
||||
let (remote_network, remote_location) = devolved;
|
||||
let xcm = msg.take().ok_or(MissingArgument)?;
|
||||
|
||||
@@ -299,7 +300,7 @@ impl<Bridges: ExporterFor, Router: SendXcm, UniversalLocation: Get<InteriorMulti
|
||||
let mut message = Xcm(if let Some(ref payment) = maybe_payment {
|
||||
let fees = payment
|
||||
.clone()
|
||||
.reanchored(&bridge, UniversalLocation::get())
|
||||
.reanchored(&bridge, &UniversalLocation::get())
|
||||
.map_err(|_| Unroutable)?;
|
||||
vec![
|
||||
WithdrawAsset(fees.clone().into()),
|
||||
@@ -366,7 +367,7 @@ pub struct BridgeMessage {
|
||||
/// The message destination as a *Universal Location*. This means it begins with a
|
||||
/// `GlobalConsensus` junction describing the network under which global consensus happens.
|
||||
/// If this does not match our global consensus then it's a fatal error.
|
||||
pub universal_dest: VersionedInteriorMultiLocation,
|
||||
pub universal_dest: VersionedInteriorLocation,
|
||||
pub message: VersionedXcm<()>,
|
||||
}
|
||||
|
||||
@@ -386,8 +387,8 @@ pub struct BridgeBlobDispatcher<Router, OurPlace, OurPlaceBridgeInstance>(
|
||||
);
|
||||
impl<
|
||||
Router: SendXcm,
|
||||
OurPlace: Get<InteriorMultiLocation>,
|
||||
OurPlaceBridgeInstance: Get<Option<InteriorMultiLocation>>,
|
||||
OurPlace: Get<InteriorLocation>,
|
||||
OurPlaceBridgeInstance: Get<Option<InteriorLocation>>,
|
||||
> DispatchBlob for BridgeBlobDispatcher<Router, OurPlace, OurPlaceBridgeInstance>
|
||||
{
|
||||
fn dispatch_blob(blob: Vec<u8>) -> Result<(), DispatchBlobError> {
|
||||
@@ -396,7 +397,7 @@ impl<
|
||||
our_universal.global_consensus().map_err(|()| DispatchBlobError::Unbridgable)?;
|
||||
let BridgeMessage { universal_dest, message } =
|
||||
Decode::decode(&mut &blob[..]).map_err(|_| DispatchBlobError::InvalidEncoding)?;
|
||||
let universal_dest: InteriorMultiLocation = universal_dest
|
||||
let universal_dest: InteriorLocation = universal_dest
|
||||
.try_into()
|
||||
.map_err(|_| DispatchBlobError::UnsupportedLocationVersion)?;
|
||||
// `universal_dest` is the desired destination within the universe: first we need to check
|
||||
@@ -437,9 +438,9 @@ pub struct HaulBlobExporter<Bridge, BridgedNetwork, DestinationVersion, Price>(
|
||||
/// ```
|
||||
impl<
|
||||
Bridge: HaulBlob,
|
||||
BridgedNetwork: Get<MultiLocation>,
|
||||
BridgedNetwork: Get<Location>,
|
||||
DestinationVersion: GetVersion,
|
||||
Price: Get<MultiAssets>,
|
||||
Price: Get<Assets>,
|
||||
> ExportXcm for HaulBlobExporter<Bridge, BridgedNetwork, DestinationVersion, Price>
|
||||
{
|
||||
type Ticket = (Vec<u8>, XcmHash);
|
||||
@@ -447,12 +448,12 @@ impl<
|
||||
fn validate(
|
||||
network: NetworkId,
|
||||
_channel: u32,
|
||||
universal_source: &mut Option<InteriorMultiLocation>,
|
||||
destination: &mut Option<InteriorMultiLocation>,
|
||||
universal_source: &mut Option<InteriorLocation>,
|
||||
destination: &mut Option<InteriorLocation>,
|
||||
message: &mut Option<Xcm<()>>,
|
||||
) -> Result<((Vec<u8>, XcmHash), MultiAssets), SendError> {
|
||||
) -> Result<((Vec<u8>, XcmHash), Assets), SendError> {
|
||||
let (bridged_network, bridged_network_location_parents) = {
|
||||
let MultiLocation { parents, interior: mut junctions } = BridgedNetwork::get();
|
||||
let Location { parents, interior: mut junctions } = BridgedNetwork::get();
|
||||
match junctions.take_first() {
|
||||
Some(GlobalConsensus(network)) => (network, parents),
|
||||
_ => return Err(SendError::NotApplicable),
|
||||
@@ -467,8 +468,8 @@ impl<
|
||||
let (universal_dest, version) =
|
||||
match dest.pushed_front_with(GlobalConsensus(bridged_network)) {
|
||||
Ok(d) => {
|
||||
let version = DestinationVersion::get_version_for(&MultiLocation::from(
|
||||
AncestorThen(bridged_network_location_parents, d),
|
||||
let version = DestinationVersion::get_version_for(&Location::from(
|
||||
AncestorThen(bridged_network_location_parents, d.clone()),
|
||||
))
|
||||
.ok_or(SendError::DestinationUnsupported)?;
|
||||
(d, version)
|
||||
@@ -501,7 +502,7 @@ impl<
|
||||
let message = VersionedXcm::from(message)
|
||||
.into_version(version)
|
||||
.map_err(|()| SendError::DestinationUnsupported)?;
|
||||
let universal_dest = VersionedInteriorMultiLocation::from(universal_dest)
|
||||
let universal_dest = VersionedInteriorLocation::from(universal_dest)
|
||||
.into_version(version)
|
||||
.map_err(|()| SendError::DestinationUnsupported)?;
|
||||
|
||||
@@ -548,10 +549,10 @@ mod tests {
|
||||
type Ticket = ();
|
||||
|
||||
fn validate(
|
||||
_destination: &mut Option<MultiLocation>,
|
||||
_destination: &mut Option<Location>,
|
||||
_message: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Self::Ticket> {
|
||||
Ok(((), MultiAssets::new()))
|
||||
Ok(((), Assets::new()))
|
||||
}
|
||||
|
||||
fn deliver(_ticket: Self::Ticket) -> Result<XcmHash, SendError> {
|
||||
@@ -562,10 +563,10 @@ mod tests {
|
||||
/// Generic test case asserting that dest and msg is not consumed by `validate` implementation
|
||||
/// of `SendXcm` in case of expected result.
|
||||
fn ensure_validate_does_not_consume_dest_or_msg<S: SendXcm>(
|
||||
dest: MultiLocation,
|
||||
dest: Location,
|
||||
assert_result: impl Fn(SendResult<S::Ticket>),
|
||||
) {
|
||||
let mut dest_wrapper = Some(dest);
|
||||
let mut dest_wrapper = Some(dest.clone());
|
||||
let msg = Xcm::<()>::new();
|
||||
let mut msg_wrapper = Some(msg.clone());
|
||||
|
||||
@@ -580,19 +581,19 @@ mod tests {
|
||||
fn remote_exporters_does_not_consume_dest_or_msg_on_not_applicable() {
|
||||
frame_support::parameter_types! {
|
||||
pub Local: NetworkId = ByGenesis([0; 32]);
|
||||
pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(Local::get()), Parachain(1234));
|
||||
pub UniversalLocation: InteriorLocation = [GlobalConsensus(Local::get()), Parachain(1234)].into();
|
||||
pub DifferentRemote: NetworkId = ByGenesis([22; 32]);
|
||||
// no routers
|
||||
pub BridgeTable: Vec<NetworkExportTableItem> = vec![];
|
||||
}
|
||||
|
||||
// check with local destination (should be remote)
|
||||
let local_dest = (Parent, Parachain(5678)).into();
|
||||
assert!(ensure_is_remote(UniversalLocation::get(), local_dest).is_err());
|
||||
let local_dest: Location = (Parent, Parachain(5678)).into();
|
||||
assert!(ensure_is_remote(UniversalLocation::get(), local_dest.clone()).is_err());
|
||||
|
||||
ensure_validate_does_not_consume_dest_or_msg::<
|
||||
UnpaidRemoteExporter<NetworkExportTable<BridgeTable>, OkSender, UniversalLocation>,
|
||||
>(local_dest, |result| assert_eq!(Err(NotApplicable), result));
|
||||
>(local_dest.clone(), |result| assert_eq!(Err(NotApplicable), result));
|
||||
|
||||
ensure_validate_does_not_consume_dest_or_msg::<
|
||||
SovereignPaidRemoteExporter<
|
||||
@@ -603,12 +604,12 @@ mod tests {
|
||||
>(local_dest, |result| assert_eq!(Err(NotApplicable), result));
|
||||
|
||||
// check with not applicable destination
|
||||
let remote_dest = (Parent, Parent, DifferentRemote::get()).into();
|
||||
assert!(ensure_is_remote(UniversalLocation::get(), remote_dest).is_ok());
|
||||
let remote_dest: Location = (Parent, Parent, DifferentRemote::get()).into();
|
||||
assert!(ensure_is_remote(UniversalLocation::get(), remote_dest.clone()).is_ok());
|
||||
|
||||
ensure_validate_does_not_consume_dest_or_msg::<
|
||||
UnpaidRemoteExporter<NetworkExportTable<BridgeTable>, OkSender, UniversalLocation>,
|
||||
>(remote_dest, |result| assert_eq!(Err(NotApplicable), result));
|
||||
>(remote_dest.clone(), |result| assert_eq!(Err(NotApplicable), result));
|
||||
|
||||
ensure_validate_does_not_consume_dest_or_msg::<
|
||||
SovereignPaidRemoteExporter<
|
||||
@@ -623,15 +624,15 @@ mod tests {
|
||||
fn network_export_table_works() {
|
||||
frame_support::parameter_types! {
|
||||
pub NetworkA: NetworkId = ByGenesis([0; 32]);
|
||||
pub Parachain1000InNetworkA: InteriorMultiLocation = X1(Parachain(1000));
|
||||
pub Parachain2000InNetworkA: InteriorMultiLocation = X1(Parachain(2000));
|
||||
pub Parachain1000InNetworkA: InteriorLocation = [Parachain(1000)].into();
|
||||
pub Parachain2000InNetworkA: InteriorLocation = [Parachain(2000)].into();
|
||||
|
||||
pub NetworkB: NetworkId = ByGenesis([1; 32]);
|
||||
|
||||
pub BridgeToALocation: MultiLocation = MultiLocation::new(1, X1(Parachain(1234)));
|
||||
pub BridgeToBLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(4321)));
|
||||
pub BridgeToALocation: Location = Location::new(1, [Parachain(1234)]);
|
||||
pub BridgeToBLocation: Location = Location::new(1, [Parachain(4321)]);
|
||||
|
||||
pub PaymentForNetworkAAndParachain2000: MultiAsset = (MultiLocation::parent(), 150).into();
|
||||
pub PaymentForNetworkAAndParachain2000: Asset = (Location::parent(), 150).into();
|
||||
|
||||
pub BridgeTable: sp_std::vec::Vec<NetworkExportTableItem> = sp_std::vec![
|
||||
// NetworkA allows `Parachain(1000)` as remote location WITHOUT payment.
|
||||
@@ -658,19 +659,19 @@ mod tests {
|
||||
];
|
||||
}
|
||||
|
||||
let test_data = vec![
|
||||
(NetworkA::get(), X1(Parachain(1000)), Some((BridgeToALocation::get(), None))),
|
||||
(NetworkA::get(), X2(Parachain(1000), GeneralIndex(1)), None),
|
||||
let test_data: Vec<(NetworkId, InteriorLocation, Option<(Location, Option<Asset>)>)> = vec![
|
||||
(NetworkA::get(), [Parachain(1000)].into(), Some((BridgeToALocation::get(), None))),
|
||||
(NetworkA::get(), [Parachain(1000), GeneralIndex(1)].into(), None),
|
||||
(
|
||||
NetworkA::get(),
|
||||
X1(Parachain(2000)),
|
||||
[Parachain(2000)].into(),
|
||||
Some((BridgeToALocation::get(), Some(PaymentForNetworkAAndParachain2000::get()))),
|
||||
),
|
||||
(NetworkA::get(), X2(Parachain(2000), GeneralIndex(1)), None),
|
||||
(NetworkA::get(), X1(Parachain(3000)), None),
|
||||
(NetworkB::get(), X1(Parachain(1000)), Some((BridgeToBLocation::get(), None))),
|
||||
(NetworkB::get(), X1(Parachain(2000)), Some((BridgeToBLocation::get(), None))),
|
||||
(NetworkB::get(), X1(Parachain(3000)), Some((BridgeToBLocation::get(), None))),
|
||||
(NetworkA::get(), [Parachain(2000), GeneralIndex(1)].into(), None),
|
||||
(NetworkA::get(), [Parachain(3000)].into(), None),
|
||||
(NetworkB::get(), [Parachain(1000)].into(), Some((BridgeToBLocation::get(), None))),
|
||||
(NetworkB::get(), [Parachain(2000)].into(), Some((BridgeToBLocation::get(), None))),
|
||||
(NetworkB::get(), [Parachain(3000)].into(), Some((BridgeToBLocation::get(), None))),
|
||||
];
|
||||
|
||||
for (network, remote_location, expected_result) in test_data {
|
||||
|
||||
@@ -25,10 +25,10 @@ use frame_support::{
|
||||
use parity_scale_codec::Decode;
|
||||
use sp_runtime::traits::{SaturatedConversion, Saturating, Zero};
|
||||
use sp_std::{marker::PhantomData, result::Result};
|
||||
use xcm::latest::{prelude::*, Weight};
|
||||
use xcm::latest::{prelude::*, GetWeight, Weight};
|
||||
use xcm_executor::{
|
||||
traits::{WeightBounds, WeightTrader},
|
||||
Assets,
|
||||
AssetsInHolding,
|
||||
};
|
||||
|
||||
pub struct FixedWeightBounds<T, C, M>(PhantomData<(T, C, M)>);
|
||||
@@ -114,16 +114,16 @@ where
|
||||
}
|
||||
|
||||
/// Function trait for handling some revenue. Similar to a negative imbalance (credit) handler, but
|
||||
/// for a `MultiAsset`. Sensible implementations will deposit the asset in some known treasury or
|
||||
/// for a `Asset`. Sensible implementations will deposit the asset in some known treasury or
|
||||
/// block-author account.
|
||||
pub trait TakeRevenue {
|
||||
/// Do something with the given `revenue`, which is a single non-wildcard `MultiAsset`.
|
||||
fn take_revenue(revenue: MultiAsset);
|
||||
/// Do something with the given `revenue`, which is a single non-wildcard `Asset`.
|
||||
fn take_revenue(revenue: Asset);
|
||||
}
|
||||
|
||||
/// Null implementation just burns the revenue.
|
||||
impl TakeRevenue for () {
|
||||
fn take_revenue(_revenue: MultiAsset) {}
|
||||
fn take_revenue(_revenue: Asset) {}
|
||||
}
|
||||
|
||||
/// Simple fee calculator that requires payment in a single fungible at a fixed rate.
|
||||
@@ -143,9 +143,9 @@ impl<T: Get<(AssetId, u128, u128)>, R: TakeRevenue> WeightTrader for FixedRateOf
|
||||
fn buy_weight(
|
||||
&mut self,
|
||||
weight: Weight,
|
||||
payment: Assets,
|
||||
payment: AssetsInHolding,
|
||||
context: &XcmContext,
|
||||
) -> Result<Assets, XcmError> {
|
||||
) -> Result<AssetsInHolding, XcmError> {
|
||||
log::trace!(
|
||||
target: "xcm::weight",
|
||||
"FixedRateOfFungible::buy_weight weight: {:?}, payment: {:?}, context: {:?}",
|
||||
@@ -165,7 +165,7 @@ impl<T: Get<(AssetId, u128, u128)>, R: TakeRevenue> WeightTrader for FixedRateOf
|
||||
Ok(unused)
|
||||
}
|
||||
|
||||
fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option<MultiAsset> {
|
||||
fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option<Asset> {
|
||||
log::trace!(target: "xcm::weight", "FixedRateOfFungible::refund_weight weight: {:?}, context: {:?}", weight, context);
|
||||
let (id, units_per_second, units_per_mb) = T::get();
|
||||
let weight = weight.min(self.0);
|
||||
@@ -194,22 +194,22 @@ impl<T: Get<(AssetId, u128, u128)>, R: TakeRevenue> Drop for FixedRateOfFungible
|
||||
/// places any weight bought into the right account.
|
||||
pub struct UsingComponents<
|
||||
WeightToFee: WeightToFeeT<Balance = Currency::Balance>,
|
||||
AssetId: Get<MultiLocation>,
|
||||
AssetIdValue: Get<Location>,
|
||||
AccountId,
|
||||
Currency: CurrencyT<AccountId>,
|
||||
OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
|
||||
>(
|
||||
Weight,
|
||||
Currency::Balance,
|
||||
PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,
|
||||
PhantomData<(WeightToFee, AssetIdValue, AccountId, Currency, OnUnbalanced)>,
|
||||
);
|
||||
impl<
|
||||
WeightToFee: WeightToFeeT<Balance = Currency::Balance>,
|
||||
AssetId: Get<MultiLocation>,
|
||||
AssetIdValue: Get<Location>,
|
||||
AccountId,
|
||||
Currency: CurrencyT<AccountId>,
|
||||
OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
|
||||
> WeightTrader for UsingComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
|
||||
> WeightTrader for UsingComponents<WeightToFee, AssetIdValue, AccountId, Currency, OnUnbalanced>
|
||||
{
|
||||
fn new() -> Self {
|
||||
Self(Weight::zero(), Zero::zero(), PhantomData)
|
||||
@@ -218,20 +218,20 @@ impl<
|
||||
fn buy_weight(
|
||||
&mut self,
|
||||
weight: Weight,
|
||||
payment: Assets,
|
||||
payment: AssetsInHolding,
|
||||
context: &XcmContext,
|
||||
) -> Result<Assets, XcmError> {
|
||||
) -> Result<AssetsInHolding, XcmError> {
|
||||
log::trace!(target: "xcm::weight", "UsingComponents::buy_weight weight: {:?}, payment: {:?}, context: {:?}", weight, payment, context);
|
||||
let amount = WeightToFee::weight_to_fee(&weight);
|
||||
let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;
|
||||
let required = (Concrete(AssetId::get()), u128_amount).into();
|
||||
let required = (AssetId(AssetIdValue::get()), u128_amount).into();
|
||||
let unused = payment.checked_sub(required).map_err(|_| XcmError::TooExpensive)?;
|
||||
self.0 = self.0.saturating_add(weight);
|
||||
self.1 = self.1.saturating_add(amount);
|
||||
Ok(unused)
|
||||
}
|
||||
|
||||
fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option<MultiAsset> {
|
||||
fn refund_weight(&mut self, weight: Weight, context: &XcmContext) -> Option<Asset> {
|
||||
log::trace!(target: "xcm::weight", "UsingComponents::refund_weight weight: {:?}, context: {:?}", weight, context);
|
||||
let weight = weight.min(self.0);
|
||||
let amount = WeightToFee::weight_to_fee(&weight);
|
||||
@@ -239,7 +239,7 @@ impl<
|
||||
self.1 = self.1.saturating_sub(amount);
|
||||
let amount: u128 = amount.saturated_into();
|
||||
if amount > 0 {
|
||||
Some((AssetId::get(), amount).into())
|
||||
Some((AssetIdValue::get(), amount).into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -247,7 +247,7 @@ impl<
|
||||
}
|
||||
impl<
|
||||
WeightToFee: WeightToFeeT<Balance = Currency::Balance>,
|
||||
AssetId: Get<MultiLocation>,
|
||||
AssetId: Get<Location>,
|
||||
AccountId,
|
||||
Currency: CurrencyT<AccountId>,
|
||||
OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
|
||||
|
||||
Reference in New Issue
Block a user