mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 02:51:01 +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
@@ -54,8 +54,8 @@ use scale_info::TypeInfo;
|
||||
use sp_core::{H160, H256};
|
||||
use sp_std::{convert::TryFrom, vec};
|
||||
use xcm::prelude::{
|
||||
send_xcm, Instruction::SetTopic, Junction::*, Junctions::*, MultiLocation,
|
||||
SendError as XcmpSendError, SendXcm, Xcm, XcmContext, XcmHash,
|
||||
send_xcm, Instruction::SetTopic, Junction::*, Location, SendError as XcmpSendError, SendXcm,
|
||||
Xcm, XcmContext, XcmHash,
|
||||
};
|
||||
use xcm_executor::traits::TransactAsset;
|
||||
|
||||
@@ -324,7 +324,7 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
pub fn send_xcm(xcm: Xcm<()>, dest: ParaId) -> Result<XcmHash, Error<T>> {
|
||||
let dest = MultiLocation { parents: 1, interior: X1(Parachain(dest.into())) };
|
||||
let dest = Location::new(1, [Parachain(dest.into())]);
|
||||
let (xcm_hash, _) = send_xcm::<T::XcmSender>(dest, xcm).map_err(Error::<T>::from)?;
|
||||
Ok(xcm_hash)
|
||||
}
|
||||
@@ -341,8 +341,8 @@ pub mod pallet {
|
||||
pub fn burn_fees(para_id: ParaId, fee: BalanceOf<T>) -> DispatchResult {
|
||||
let dummy_context =
|
||||
XcmContext { origin: None, message_id: Default::default(), topic: None };
|
||||
let dest = MultiLocation { parents: 1, interior: X1(Parachain(para_id.into())) };
|
||||
let fees = (MultiLocation::parent(), fee.saturated_into::<u128>()).into();
|
||||
let dest = Location::new(1, [Parachain(para_id.into())]);
|
||||
let fees = (Location::parent(), fee.saturated_into::<u128>()).into();
|
||||
T::AssetTransactor::can_check_out(&dest, &fees, &dummy_context).map_err(|error| {
|
||||
log::error!(
|
||||
target: LOG_TARGET,
|
||||
|
||||
@@ -21,8 +21,8 @@ use sp_runtime::{
|
||||
BuildStorage, FixedU128, MultiSignature,
|
||||
};
|
||||
use sp_std::convert::From;
|
||||
use xcm::v3::{prelude::*, MultiAssets, SendXcm};
|
||||
use xcm_executor::Assets;
|
||||
use xcm::v4::{prelude::*, SendXcm};
|
||||
use xcm_executor::AssetsInHolding;
|
||||
|
||||
use crate::{self as inbound_queue};
|
||||
|
||||
@@ -155,17 +155,16 @@ impl SendXcm for MockXcmSender {
|
||||
type Ticket = Xcm<()>;
|
||||
|
||||
fn validate(
|
||||
dest: &mut Option<MultiLocation>,
|
||||
xcm: &mut Option<xcm::v3::Xcm<()>>,
|
||||
dest: &mut Option<Location>,
|
||||
xcm: &mut Option<Xcm<()>>,
|
||||
) -> SendResult<Self::Ticket> {
|
||||
match dest {
|
||||
Some(MultiLocation { interior, .. }) => {
|
||||
if let X1(Parachain(1001)) = interior {
|
||||
return Err(XcmpSendError::NotApplicable)
|
||||
}
|
||||
Ok((xcm.clone().unwrap(), MultiAssets::default()))
|
||||
},
|
||||
_ => Ok((xcm.clone().unwrap(), MultiAssets::default())),
|
||||
if let Some(location) = dest {
|
||||
match location.unpack() {
|
||||
(_, [Parachain(1001)]) => return Err(XcmpSendError::NotApplicable),
|
||||
_ => Ok((xcm.clone().unwrap(), Assets::default())),
|
||||
}
|
||||
} else {
|
||||
Ok((xcm.clone().unwrap(), Assets::default()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,45 +202,33 @@ impl StaticLookup for MockChannelLookup {
|
||||
|
||||
pub struct SuccessfulTransactor;
|
||||
impl TransactAsset for SuccessfulTransactor {
|
||||
fn can_check_in(
|
||||
_origin: &MultiLocation,
|
||||
_what: &MultiAsset,
|
||||
_context: &XcmContext,
|
||||
) -> XcmResult {
|
||||
fn can_check_in(_origin: &Location, _what: &Asset, _context: &XcmContext) -> XcmResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn can_check_out(
|
||||
_dest: &MultiLocation,
|
||||
_what: &MultiAsset,
|
||||
_context: &XcmContext,
|
||||
) -> XcmResult {
|
||||
fn can_check_out(_dest: &Location, _what: &Asset, _context: &XcmContext) -> XcmResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deposit_asset(
|
||||
_what: &MultiAsset,
|
||||
_who: &MultiLocation,
|
||||
_context: Option<&XcmContext>,
|
||||
) -> XcmResult {
|
||||
fn deposit_asset(_what: &Asset, _who: &Location, _context: Option<&XcmContext>) -> XcmResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
_what: &MultiAsset,
|
||||
_who: &MultiLocation,
|
||||
_what: &Asset,
|
||||
_who: &Location,
|
||||
_context: Option<&XcmContext>,
|
||||
) -> Result<Assets, XcmError> {
|
||||
Ok(Assets::default())
|
||||
) -> Result<AssetsInHolding, XcmError> {
|
||||
Ok(AssetsInHolding::default())
|
||||
}
|
||||
|
||||
fn internal_transfer_asset(
|
||||
_what: &MultiAsset,
|
||||
_from: &MultiLocation,
|
||||
_to: &MultiLocation,
|
||||
_what: &Asset,
|
||||
_from: &Location,
|
||||
_to: &Location,
|
||||
_context: &XcmContext,
|
||||
) -> Result<Assets, XcmError> {
|
||||
Ok(Assets::default())
|
||||
) -> Result<AssetsInHolding, XcmError> {
|
||||
Ok(AssetsInHolding::default())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,8 +41,8 @@ fn test_submit_happy_path() {
|
||||
.into(),
|
||||
nonce: 1,
|
||||
message_id: [
|
||||
27, 217, 88, 127, 46, 143, 199, 70, 236, 66, 212, 244, 85, 221, 153, 104, 175, 37,
|
||||
224, 20, 140, 95, 140, 7, 27, 74, 182, 199, 77, 12, 194, 236,
|
||||
57, 61, 232, 3, 66, 61, 25, 190, 234, 188, 193, 174, 13, 186, 1, 64, 237, 94, 73,
|
||||
83, 14, 18, 209, 213, 78, 121, 43, 108, 251, 245, 107, 67,
|
||||
],
|
||||
fee_burned: 110000000000,
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use snowbridge_core::AgentId;
|
||||
use xcm::VersionedMultiLocation;
|
||||
use xcm::VersionedLocation;
|
||||
|
||||
sp_api::decl_runtime_apis! {
|
||||
pub trait ControlApi
|
||||
{
|
||||
fn agent_id(location: VersionedMultiLocation) -> Option<AgentId>;
|
||||
fn agent_id(location: VersionedLocation) -> Option<AgentId>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
//! Helpers for implementing runtime api
|
||||
|
||||
use snowbridge_core::AgentId;
|
||||
use xcm::{prelude::*, VersionedMultiLocation};
|
||||
use xcm::{prelude::*, VersionedLocation};
|
||||
|
||||
use crate::{agent_id_of, Config};
|
||||
|
||||
pub fn agent_id<Runtime>(location: VersionedMultiLocation) -> Option<AgentId>
|
||||
pub fn agent_id<Runtime>(location: VersionedLocation) -> Option<AgentId>
|
||||
where
|
||||
Runtime: Config,
|
||||
{
|
||||
let location: MultiLocation = location.try_into().ok()?;
|
||||
let location: Location = location.try_into().ok()?;
|
||||
agent_id_of::<Runtime>(&location).ok()
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ mod benchmarks {
|
||||
#[benchmark]
|
||||
fn create_agent() -> Result<(), BenchmarkError> {
|
||||
let origin_para_id = 2000;
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(origin_para_id)) };
|
||||
let origin_location = Location::new(1, [Parachain(origin_para_id)]);
|
||||
let origin = T::Helper::make_xcm_origin(origin_location);
|
||||
fund_sovereign_account::<T>(origin_para_id.into())?;
|
||||
|
||||
@@ -76,7 +76,7 @@ mod benchmarks {
|
||||
#[benchmark]
|
||||
fn create_channel() -> Result<(), BenchmarkError> {
|
||||
let origin_para_id = 2000;
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(origin_para_id)) };
|
||||
let origin_location = Location::new(1, [Parachain(origin_para_id)]);
|
||||
let origin = T::Helper::make_xcm_origin(origin_location);
|
||||
fund_sovereign_account::<T>(origin_para_id.into())?;
|
||||
|
||||
@@ -91,7 +91,7 @@ mod benchmarks {
|
||||
#[benchmark]
|
||||
fn update_channel() -> Result<(), BenchmarkError> {
|
||||
let origin_para_id = 2000;
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(origin_para_id)) };
|
||||
let origin_location = Location::new(1, [Parachain(origin_para_id)]);
|
||||
let origin = T::Helper::make_xcm_origin(origin_location);
|
||||
fund_sovereign_account::<T>(origin_para_id.into())?;
|
||||
SnowbridgeControl::<T>::create_agent(origin.clone())?;
|
||||
@@ -106,7 +106,7 @@ mod benchmarks {
|
||||
#[benchmark]
|
||||
fn force_update_channel() -> Result<(), BenchmarkError> {
|
||||
let origin_para_id = 2000;
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(origin_para_id)) };
|
||||
let origin_location = Location::new(1, [Parachain(origin_para_id)]);
|
||||
let origin = T::Helper::make_xcm_origin(origin_location);
|
||||
let channel_id: ChannelId = ParaId::from(origin_para_id).into();
|
||||
|
||||
@@ -123,7 +123,7 @@ mod benchmarks {
|
||||
#[benchmark]
|
||||
fn transfer_native_from_agent() -> Result<(), BenchmarkError> {
|
||||
let origin_para_id = 2000;
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(origin_para_id)) };
|
||||
let origin_location = Location::new(1, [Parachain(origin_para_id)]);
|
||||
let origin = T::Helper::make_xcm_origin(origin_location);
|
||||
fund_sovereign_account::<T>(origin_para_id.into())?;
|
||||
SnowbridgeControl::<T>::create_agent(origin.clone())?;
|
||||
@@ -138,12 +138,12 @@ mod benchmarks {
|
||||
#[benchmark]
|
||||
fn force_transfer_native_from_agent() -> Result<(), BenchmarkError> {
|
||||
let origin_para_id = 2000;
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(origin_para_id)) };
|
||||
let origin = T::Helper::make_xcm_origin(origin_location);
|
||||
let origin_location = Location::new(1, [Parachain(origin_para_id)]);
|
||||
let origin = T::Helper::make_xcm_origin(origin_location.clone());
|
||||
fund_sovereign_account::<T>(origin_para_id.into())?;
|
||||
SnowbridgeControl::<T>::create_agent(origin.clone())?;
|
||||
|
||||
let versioned_location: VersionedMultiLocation = origin_location.into();
|
||||
let versioned_location: VersionedLocation = origin_location.into();
|
||||
|
||||
#[extrinsic_call]
|
||||
_(RawOrigin::Root, Box::new(versioned_location), H160::default(), 1);
|
||||
|
||||
@@ -87,12 +87,12 @@ pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
|
||||
pub type PricingParametersOf<T> = PricingParametersRecord<BalanceOf<T>>;
|
||||
|
||||
/// Ensure origin location is a sibling
|
||||
fn ensure_sibling<T>(location: &MultiLocation) -> Result<(ParaId, H256), DispatchError>
|
||||
fn ensure_sibling<T>(location: &Location) -> Result<(ParaId, H256), DispatchError>
|
||||
where
|
||||
T: Config,
|
||||
{
|
||||
match location {
|
||||
MultiLocation { parents: 1, interior: X1(Parachain(para_id)) } => {
|
||||
match location.unpack() {
|
||||
(1, [Parachain(para_id)]) => {
|
||||
let agent_id = agent_id_of::<T>(location)?;
|
||||
Ok(((*para_id).into(), agent_id))
|
||||
},
|
||||
@@ -101,7 +101,7 @@ where
|
||||
}
|
||||
|
||||
/// Hash the location to produce an agent id
|
||||
fn agent_id_of<T: Config>(location: &MultiLocation) -> Result<H256, DispatchError> {
|
||||
fn agent_id_of<T: Config>(location: &Location) -> Result<H256, DispatchError> {
|
||||
T::AgentIdOf::convert_location(location).ok_or(Error::<T>::LocationConversionFailed.into())
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ pub trait BenchmarkHelper<O>
|
||||
where
|
||||
O: OriginTrait,
|
||||
{
|
||||
fn make_xcm_origin(location: MultiLocation) -> O;
|
||||
fn make_xcm_origin(location: Location) -> O;
|
||||
}
|
||||
|
||||
/// Whether a fee should be withdrawn to an account for sending an outbound message
|
||||
@@ -145,9 +145,9 @@ pub mod pallet {
|
||||
type OutboundQueue: SendMessage<Balance = BalanceOf<Self>>;
|
||||
|
||||
/// Origin check for XCM locations that can create agents
|
||||
type SiblingOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = MultiLocation>;
|
||||
type SiblingOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Location>;
|
||||
|
||||
/// Converts MultiLocation to AgentId
|
||||
/// Converts Location to AgentId
|
||||
type AgentIdOf: ConvertLocation<AgentId>;
|
||||
|
||||
/// Token reserved for control operations
|
||||
@@ -180,7 +180,7 @@ pub mod pallet {
|
||||
},
|
||||
/// An CreateAgent message was sent to the Gateway
|
||||
CreateAgent {
|
||||
location: Box<MultiLocation>,
|
||||
location: Box<Location>,
|
||||
agent_id: AgentId,
|
||||
},
|
||||
/// An CreateChannel message was sent to the Gateway
|
||||
@@ -299,7 +299,7 @@ pub mod pallet {
|
||||
///
|
||||
/// Fee required: No
|
||||
///
|
||||
/// - `origin`: Must be `MultiLocation`
|
||||
/// - `origin`: Must be `Location`
|
||||
#[pallet::call_index(1)]
|
||||
#[pallet::weight((T::WeightInfo::set_operating_mode(), DispatchClass::Operational))]
|
||||
pub fn set_operating_mode(origin: OriginFor<T>, mode: OperatingMode) -> DispatchResult {
|
||||
@@ -342,11 +342,11 @@ pub mod pallet {
|
||||
///
|
||||
/// Fee required: Yes
|
||||
///
|
||||
/// - `origin`: Must be `MultiLocation` of a sibling parachain
|
||||
/// - `origin`: Must be `Location` of a sibling parachain
|
||||
#[pallet::call_index(3)]
|
||||
#[pallet::weight(T::WeightInfo::create_agent())]
|
||||
pub fn create_agent(origin: OriginFor<T>) -> DispatchResult {
|
||||
let origin_location: MultiLocation = T::SiblingOrigin::ensure_origin(origin)?;
|
||||
let origin_location: Location = T::SiblingOrigin::ensure_origin(origin)?;
|
||||
|
||||
// Ensure that origin location is some consensus system on a sibling parachain
|
||||
let (para_id, agent_id) = ensure_sibling::<T>(&origin_location)?;
|
||||
@@ -375,12 +375,12 @@ pub mod pallet {
|
||||
///
|
||||
/// The message is sent over the bridge on BridgeHub's own channel to the Gateway.
|
||||
///
|
||||
/// - `origin`: Must be `MultiLocation`
|
||||
/// - `origin`: Must be `Location`
|
||||
/// - `mode`: Initial operating mode of the channel
|
||||
#[pallet::call_index(4)]
|
||||
#[pallet::weight(T::WeightInfo::create_channel())]
|
||||
pub fn create_channel(origin: OriginFor<T>, mode: OperatingMode) -> DispatchResult {
|
||||
let origin_location: MultiLocation = T::SiblingOrigin::ensure_origin(origin)?;
|
||||
let origin_location: Location = T::SiblingOrigin::ensure_origin(origin)?;
|
||||
|
||||
// Ensure that origin location is a sibling parachain
|
||||
let (para_id, agent_id) = ensure_sibling::<T>(&origin_location)?;
|
||||
@@ -407,12 +407,12 @@ pub mod pallet {
|
||||
///
|
||||
/// A partial fee will be charged for local processing only.
|
||||
///
|
||||
/// - `origin`: Must be `MultiLocation`
|
||||
/// - `origin`: Must be `Location`
|
||||
/// - `mode`: Initial operating mode of the channel
|
||||
#[pallet::call_index(5)]
|
||||
#[pallet::weight(T::WeightInfo::update_channel())]
|
||||
pub fn update_channel(origin: OriginFor<T>, mode: OperatingMode) -> DispatchResult {
|
||||
let origin_location: MultiLocation = T::SiblingOrigin::ensure_origin(origin)?;
|
||||
let origin_location: Location = T::SiblingOrigin::ensure_origin(origin)?;
|
||||
|
||||
// Ensure that origin location is a sibling parachain
|
||||
let (para_id, _) = ensure_sibling::<T>(&origin_location)?;
|
||||
@@ -461,7 +461,7 @@ pub mod pallet {
|
||||
///
|
||||
/// A partial fee will be charged for local processing only.
|
||||
///
|
||||
/// - `origin`: Must be `MultiLocation`
|
||||
/// - `origin`: Must be `Location`
|
||||
#[pallet::call_index(7)]
|
||||
#[pallet::weight(T::WeightInfo::transfer_native_from_agent())]
|
||||
pub fn transfer_native_from_agent(
|
||||
@@ -469,7 +469,7 @@ pub mod pallet {
|
||||
recipient: H160,
|
||||
amount: u128,
|
||||
) -> DispatchResult {
|
||||
let origin_location: MultiLocation = T::SiblingOrigin::ensure_origin(origin)?;
|
||||
let origin_location: Location = T::SiblingOrigin::ensure_origin(origin)?;
|
||||
|
||||
// Ensure that origin location is some consensus system on a sibling parachain
|
||||
let (para_id, agent_id) = ensure_sibling::<T>(&origin_location)?;
|
||||
@@ -501,14 +501,14 @@ pub mod pallet {
|
||||
#[pallet::weight(T::WeightInfo::force_transfer_native_from_agent())]
|
||||
pub fn force_transfer_native_from_agent(
|
||||
origin: OriginFor<T>,
|
||||
location: Box<VersionedMultiLocation>,
|
||||
location: Box<VersionedLocation>,
|
||||
recipient: H160,
|
||||
amount: u128,
|
||||
) -> DispatchResult {
|
||||
ensure_root(origin)?;
|
||||
|
||||
// Ensure that location is some consensus system on a sibling parachain
|
||||
let location: MultiLocation =
|
||||
let location: Location =
|
||||
(*location).try_into().map_err(|_| Error::<T>::UnsupportedLocationVersion)?;
|
||||
let (_, agent_id) =
|
||||
ensure_sibling::<T>(&location).map_err(|_| Error::<T>::InvalidLocation)?;
|
||||
@@ -621,8 +621,8 @@ pub mod pallet {
|
||||
/// Initializes agents and channels.
|
||||
pub fn initialize(para_id: ParaId, asset_hub_para_id: ParaId) -> Result<(), DispatchError> {
|
||||
// Asset Hub
|
||||
let asset_hub_location: MultiLocation =
|
||||
ParentThen(X1(Parachain(asset_hub_para_id.into()))).into();
|
||||
let asset_hub_location: Location =
|
||||
ParentThen(Parachain(asset_hub_para_id.into()).into()).into();
|
||||
let asset_hub_agent_id = agent_id_of::<T>(&asset_hub_location)?;
|
||||
let asset_hub_channel_id: ChannelId = asset_hub_para_id.into();
|
||||
Agents::<T>::insert(asset_hub_agent_id, ());
|
||||
@@ -632,7 +632,7 @@ pub mod pallet {
|
||||
);
|
||||
|
||||
// Governance channels
|
||||
let bridge_hub_agent_id = agent_id_of::<T>(&MultiLocation::here())?;
|
||||
let bridge_hub_agent_id = agent_id_of::<T>(&Location::here())?;
|
||||
// Agent for BridgeHub
|
||||
Agents::<T>::insert(bridge_hub_agent_id, ());
|
||||
|
||||
|
||||
@@ -49,22 +49,22 @@ mod pallet_xcm_origin {
|
||||
// Insert this custom Origin into the aggregate RuntimeOrigin
|
||||
#[pallet::origin]
|
||||
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)]
|
||||
pub struct Origin(pub MultiLocation);
|
||||
pub struct Origin(pub Location);
|
||||
|
||||
impl From<MultiLocation> for Origin {
|
||||
fn from(location: MultiLocation) -> Origin {
|
||||
impl From<Location> for Origin {
|
||||
fn from(location: Location) -> Origin {
|
||||
Origin(location)
|
||||
}
|
||||
}
|
||||
|
||||
/// `EnsureOrigin` implementation succeeding with a `MultiLocation` value to recognize and
|
||||
/// `EnsureOrigin` implementation succeeding with a `Location` value to recognize and
|
||||
/// filter the contained location
|
||||
pub struct EnsureXcm<F>(PhantomData<F>);
|
||||
impl<O: OriginTrait + From<Origin>, F: Contains<MultiLocation>> EnsureOrigin<O> for EnsureXcm<F>
|
||||
impl<O: OriginTrait + From<Origin>, F: Contains<Location>> EnsureOrigin<O> for EnsureXcm<F>
|
||||
where
|
||||
O::PalletsOrigin: From<Origin> + TryInto<Origin, Error = O::PalletsOrigin>,
|
||||
{
|
||||
type Success = MultiLocation;
|
||||
type Success = Location;
|
||||
|
||||
fn try_origin(outer: O) -> Result<Self::Success, O> {
|
||||
outer.try_with_caller(|caller| {
|
||||
@@ -77,7 +77,7 @@ mod pallet_xcm_origin {
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn try_successful_origin() -> Result<O, ()> {
|
||||
Ok(O::from(Origin(MultiLocation { parents: 1, interior: X1(Parachain(2000)) })))
|
||||
Ok(O::from(Origin(Location::new(1, [Parachain(2000)]))))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,9 +186,9 @@ parameter_types! {
|
||||
pub const SS58Prefix: u8 = 42;
|
||||
pub const AnyNetwork: Option<NetworkId> = None;
|
||||
pub const RelayNetwork: Option<NetworkId> = Some(NetworkId::Kusama);
|
||||
pub const RelayLocation: MultiLocation = MultiLocation::parent();
|
||||
pub UniversalLocation: InteriorMultiLocation =
|
||||
X2(GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(1013));
|
||||
pub const RelayLocation: Location = Location::parent();
|
||||
pub UniversalLocation: InteriorLocation =
|
||||
[GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(1013)].into();
|
||||
}
|
||||
|
||||
pub const DOT: u128 = 10_000_000_000;
|
||||
@@ -211,7 +211,7 @@ parameter_types! {
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
impl BenchmarkHelper<RuntimeOrigin> for () {
|
||||
fn make_xcm_origin(location: MultiLocation) -> RuntimeOrigin {
|
||||
fn make_xcm_origin(location: Location) -> RuntimeOrigin {
|
||||
RuntimeOrigin::from(pallet_xcm_origin::Origin(location))
|
||||
}
|
||||
}
|
||||
@@ -260,11 +260,11 @@ pub fn new_test_ext(genesis_build: bool) -> sp_io::TestExternalities {
|
||||
|
||||
// Test helpers
|
||||
|
||||
pub fn make_xcm_origin(location: MultiLocation) -> RuntimeOrigin {
|
||||
pub fn make_xcm_origin(location: Location) -> RuntimeOrigin {
|
||||
pallet_xcm_origin::Origin(location).into()
|
||||
}
|
||||
|
||||
pub fn make_agent_id(location: MultiLocation) -> AgentId {
|
||||
pub fn make_agent_id(location: Location) -> AgentId {
|
||||
<Test as snowbridge_system::Config>::AgentIdOf::convert_location(&location)
|
||||
.expect("convert location")
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ use sp_runtime::{AccountId32, DispatchError::BadOrigin, TokenError};
|
||||
fn create_agent() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let origin_para_id = 2000;
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(origin_para_id)) };
|
||||
let agent_id = make_agent_id(origin_location);
|
||||
let origin_location = Location::new(1, [Parachain(origin_para_id)]);
|
||||
let agent_id = make_agent_id(origin_location.clone());
|
||||
let sovereign_account = sibling_sovereign_account::<Test>(origin_para_id.into());
|
||||
|
||||
// fund sovereign account of origin
|
||||
@@ -30,7 +30,7 @@ fn create_agent() {
|
||||
#[test]
|
||||
fn test_agent_for_here() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let origin_location = MultiLocation::here();
|
||||
let origin_location = Location::here();
|
||||
let agent_id = make_agent_id(origin_location);
|
||||
assert_eq!(
|
||||
agent_id,
|
||||
@@ -42,7 +42,7 @@ fn test_agent_for_here() {
|
||||
#[test]
|
||||
fn create_agent_fails_on_funds_unavailable() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(2000)) };
|
||||
let origin_location = Location::new(1, [Parachain(2000)]);
|
||||
let origin = make_xcm_origin(origin_location);
|
||||
// Reset balance of sovereign_account to zero so to trigger the FundsUnavailable error
|
||||
let sovereign_account = sibling_sovereign_account::<Test>(2000.into());
|
||||
@@ -56,19 +56,16 @@ fn create_agent_bad_origin() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
// relay chain location not allowed
|
||||
assert_noop!(
|
||||
EthereumSystem::create_agent(make_xcm_origin(MultiLocation {
|
||||
parents: 1,
|
||||
interior: Here,
|
||||
})),
|
||||
EthereumSystem::create_agent(make_xcm_origin(Location::new(1, [],))),
|
||||
BadOrigin,
|
||||
);
|
||||
|
||||
// local account location not allowed
|
||||
assert_noop!(
|
||||
EthereumSystem::create_agent(make_xcm_origin(MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(Junction::AccountId32 { network: None, id: [67u8; 32] }),
|
||||
})),
|
||||
EthereumSystem::create_agent(make_xcm_origin(Location::new(
|
||||
0,
|
||||
[Junction::AccountId32 { network: None, id: [67u8; 32] }],
|
||||
))),
|
||||
BadOrigin,
|
||||
);
|
||||
|
||||
@@ -243,7 +240,7 @@ fn set_token_transfer_fees_invalid() {
|
||||
fn create_channel() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let origin_para_id = 2000;
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(origin_para_id)) };
|
||||
let origin_location = Location::new(1, [Parachain(origin_para_id)]);
|
||||
let sovereign_account = sibling_sovereign_account::<Test>(origin_para_id.into());
|
||||
let origin = make_xcm_origin(origin_location);
|
||||
|
||||
@@ -259,7 +256,7 @@ fn create_channel() {
|
||||
fn create_channel_fail_already_exists() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let origin_para_id = 2000;
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(origin_para_id)) };
|
||||
let origin_location = Location::new(1, [Parachain(origin_para_id)]);
|
||||
let sovereign_account = sibling_sovereign_account::<Test>(origin_para_id.into());
|
||||
let origin = make_xcm_origin(origin_location);
|
||||
|
||||
@@ -282,7 +279,7 @@ fn create_channel_bad_origin() {
|
||||
// relay chain location not allowed
|
||||
assert_noop!(
|
||||
EthereumSystem::create_channel(
|
||||
make_xcm_origin(MultiLocation { parents: 1, interior: Here }),
|
||||
make_xcm_origin(Location::new(1, [])),
|
||||
OperatingMode::Normal,
|
||||
),
|
||||
BadOrigin,
|
||||
@@ -291,13 +288,10 @@ fn create_channel_bad_origin() {
|
||||
// child of sibling location not allowed
|
||||
assert_noop!(
|
||||
EthereumSystem::create_channel(
|
||||
make_xcm_origin(MultiLocation {
|
||||
parents: 1,
|
||||
interior: X2(
|
||||
Parachain(2000),
|
||||
Junction::AccountId32 { network: None, id: [67u8; 32] }
|
||||
),
|
||||
}),
|
||||
make_xcm_origin(Location::new(
|
||||
1,
|
||||
[Parachain(2000), Junction::AccountId32 { network: None, id: [67u8; 32] }],
|
||||
)),
|
||||
OperatingMode::Normal,
|
||||
),
|
||||
BadOrigin,
|
||||
@@ -306,10 +300,10 @@ fn create_channel_bad_origin() {
|
||||
// local account location not allowed
|
||||
assert_noop!(
|
||||
EthereumSystem::create_channel(
|
||||
make_xcm_origin(MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(Junction::AccountId32 { network: None, id: [67u8; 32] }),
|
||||
}),
|
||||
make_xcm_origin(Location::new(
|
||||
0,
|
||||
[Junction::AccountId32 { network: None, id: [67u8; 32] }],
|
||||
)),
|
||||
OperatingMode::Normal,
|
||||
),
|
||||
BadOrigin,
|
||||
@@ -333,7 +327,7 @@ fn create_channel_bad_origin() {
|
||||
fn update_channel() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let origin_para_id = 2000;
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(origin_para_id)) };
|
||||
let origin_location = Location::new(1, [Parachain(origin_para_id)]);
|
||||
let sovereign_account = sibling_sovereign_account::<Test>(origin_para_id.into());
|
||||
let origin = make_xcm_origin(origin_location);
|
||||
|
||||
@@ -359,23 +353,17 @@ fn update_channel_bad_origin() {
|
||||
|
||||
// relay chain location not allowed
|
||||
assert_noop!(
|
||||
EthereumSystem::update_channel(
|
||||
make_xcm_origin(MultiLocation { parents: 1, interior: Here }),
|
||||
mode,
|
||||
),
|
||||
EthereumSystem::update_channel(make_xcm_origin(Location::new(1, [])), mode,),
|
||||
BadOrigin,
|
||||
);
|
||||
|
||||
// child of sibling location not allowed
|
||||
assert_noop!(
|
||||
EthereumSystem::update_channel(
|
||||
make_xcm_origin(MultiLocation {
|
||||
parents: 1,
|
||||
interior: X2(
|
||||
Parachain(2000),
|
||||
Junction::AccountId32 { network: None, id: [67u8; 32] }
|
||||
),
|
||||
}),
|
||||
make_xcm_origin(Location::new(
|
||||
1,
|
||||
[Parachain(2000), Junction::AccountId32 { network: None, id: [67u8; 32] }],
|
||||
)),
|
||||
mode,
|
||||
),
|
||||
BadOrigin,
|
||||
@@ -384,10 +372,10 @@ fn update_channel_bad_origin() {
|
||||
// local account location not allowed
|
||||
assert_noop!(
|
||||
EthereumSystem::update_channel(
|
||||
make_xcm_origin(MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(Junction::AccountId32 { network: None, id: [67u8; 32] }),
|
||||
}),
|
||||
make_xcm_origin(Location::new(
|
||||
0,
|
||||
[Junction::AccountId32 { network: None, id: [67u8; 32] }],
|
||||
)),
|
||||
mode,
|
||||
),
|
||||
BadOrigin,
|
||||
@@ -407,7 +395,7 @@ fn update_channel_bad_origin() {
|
||||
#[test]
|
||||
fn update_channel_fails_not_exist() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(2000)) };
|
||||
let origin_location = Location::new(1, [Parachain(2000)]);
|
||||
let origin = make_xcm_origin(origin_location);
|
||||
|
||||
// Now try to update it
|
||||
@@ -422,7 +410,7 @@ fn update_channel_fails_not_exist() {
|
||||
fn force_update_channel() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let origin_para_id = 2000;
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(origin_para_id)) };
|
||||
let origin_location = Location::new(1, [Parachain(origin_para_id)]);
|
||||
let sovereign_account = sibling_sovereign_account::<Test>(origin_para_id.into());
|
||||
let origin = make_xcm_origin(origin_location);
|
||||
|
||||
@@ -468,8 +456,8 @@ fn force_update_channel_bad_origin() {
|
||||
#[test]
|
||||
fn transfer_native_from_agent() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(2000)) };
|
||||
let origin = make_xcm_origin(origin_location);
|
||||
let origin_location = Location::new(1, [Parachain(2000)]);
|
||||
let origin = make_xcm_origin(origin_location.clone());
|
||||
let recipient: H160 = [27u8; 20].into();
|
||||
let amount = 103435;
|
||||
|
||||
@@ -477,7 +465,7 @@ fn transfer_native_from_agent() {
|
||||
assert_ok!(EthereumSystem::create_agent(origin.clone()));
|
||||
assert_ok!(EthereumSystem::create_channel(origin, OperatingMode::Normal));
|
||||
|
||||
let origin = make_xcm_origin(origin_location);
|
||||
let origin = make_xcm_origin(origin_location.clone());
|
||||
assert_ok!(EthereumSystem::transfer_native_from_agent(origin, recipient, amount),);
|
||||
|
||||
System::assert_last_event(RuntimeEvent::EthereumSystem(
|
||||
@@ -494,13 +482,13 @@ fn transfer_native_from_agent() {
|
||||
fn force_transfer_native_from_agent() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let origin = RuntimeOrigin::root();
|
||||
let location = MultiLocation { parents: 1, interior: X1(Parachain(2000)) };
|
||||
let versioned_location: Box<VersionedMultiLocation> = Box::new(location.into());
|
||||
let location = Location::new(1, [Parachain(2000)]);
|
||||
let versioned_location: Box<VersionedLocation> = Box::new(location.clone().into());
|
||||
let recipient: H160 = [27u8; 20].into();
|
||||
let amount = 103435;
|
||||
|
||||
// First create the agent
|
||||
Agents::<Test>::insert(make_agent_id(location), ());
|
||||
Agents::<Test>::insert(make_agent_id(location.clone()), ());
|
||||
|
||||
assert_ok!(EthereumSystem::force_transfer_native_from_agent(
|
||||
origin,
|
||||
@@ -530,13 +518,10 @@ fn force_transfer_native_from_agent_bad_origin() {
|
||||
EthereumSystem::force_transfer_native_from_agent(
|
||||
RuntimeOrigin::signed([14; 32].into()),
|
||||
Box::new(
|
||||
MultiLocation {
|
||||
parents: 1,
|
||||
interior: X2(
|
||||
Parachain(2000),
|
||||
Junction::AccountId32 { network: None, id: [67u8; 32] }
|
||||
),
|
||||
}
|
||||
Location::new(
|
||||
1,
|
||||
[Parachain(2000), Junction::AccountId32 { network: None, id: [67u8; 32] }],
|
||||
)
|
||||
.into()
|
||||
),
|
||||
recipient,
|
||||
@@ -571,8 +556,8 @@ fn check_sibling_sovereign_account() {
|
||||
fn charge_fee_for_create_agent() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let para_id: u32 = TestParaId::get();
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(para_id)) };
|
||||
let origin = make_xcm_origin(origin_location);
|
||||
let origin_location = Location::new(1, [Parachain(para_id)]);
|
||||
let origin = make_xcm_origin(origin_location.clone());
|
||||
let sovereign_account = sibling_sovereign_account::<Test>(para_id.into());
|
||||
let (_, agent_id) = ensure_sibling::<Test>(&origin_location).unwrap();
|
||||
|
||||
@@ -605,10 +590,10 @@ fn charge_fee_for_create_agent() {
|
||||
fn charge_fee_for_transfer_native_from_agent() {
|
||||
new_test_ext(true).execute_with(|| {
|
||||
let para_id: u32 = TestParaId::get();
|
||||
let origin_location = MultiLocation { parents: 1, interior: X1(Parachain(para_id)) };
|
||||
let origin_location = Location::new(1, [Parachain(para_id)]);
|
||||
let recipient: H160 = [27u8; 20].into();
|
||||
let amount = 103435;
|
||||
let origin = make_xcm_origin(origin_location);
|
||||
let origin = make_xcm_origin(origin_location.clone());
|
||||
let (_, agent_id) = ensure_sibling::<Test>(&origin_location).unwrap();
|
||||
|
||||
let sovereign_account = sibling_sovereign_account::<Test>(para_id.into());
|
||||
|
||||
@@ -28,11 +28,7 @@ use sp_core::H256;
|
||||
use sp_io::hashing::keccak_256;
|
||||
use sp_runtime::{traits::AccountIdConversion, RuntimeDebug};
|
||||
use sp_std::prelude::*;
|
||||
use xcm::prelude::{
|
||||
Junction::Parachain,
|
||||
Junctions::{Here, X1},
|
||||
MultiLocation,
|
||||
};
|
||||
use xcm::prelude::{Junction::Parachain, Location};
|
||||
use xcm_builder::{DescribeAllTerminal, DescribeFamily, DescribeLocation, HashedDescription};
|
||||
|
||||
/// The ID of an agent contract
|
||||
@@ -53,9 +49,9 @@ pub fn sibling_sovereign_account_raw(para_id: ParaId) -> [u8; 32] {
|
||||
}
|
||||
|
||||
pub struct AllowSiblingsOnly;
|
||||
impl Contains<MultiLocation> for AllowSiblingsOnly {
|
||||
fn contains(location: &MultiLocation) -> bool {
|
||||
matches!(location, MultiLocation { parents: 1, interior: X1(Parachain(_)) })
|
||||
impl Contains<Location> for AllowSiblingsOnly {
|
||||
fn contains(location: &Location) -> bool {
|
||||
matches!(location.unpack(), (1, [Parachain(_)]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,14 +157,14 @@ pub const SECONDARY_GOVERNANCE_CHANNEL: ChannelId =
|
||||
|
||||
pub struct DescribeHere;
|
||||
impl DescribeLocation for DescribeHere {
|
||||
fn describe_location(l: &MultiLocation) -> Option<Vec<u8>> {
|
||||
match (l.parents, l.interior) {
|
||||
(0, Here) => Some(Vec::<u8>::new().encode()),
|
||||
fn describe_location(l: &Location) -> Option<Vec<u8>> {
|
||||
match l.unpack() {
|
||||
(0, []) => Some(Vec::<u8>::new().encode()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an AgentId from a MultiLocation. An AgentId is a unique mapping to a Agent contract on
|
||||
/// Ethereum which acts as the sovereign account for the MultiLocation.
|
||||
/// Creates an AgentId from a Location. An AgentId is a unique mapping to a Agent contract on
|
||||
/// Ethereum which acts as the sovereign account for the Location.
|
||||
pub type AgentIdOf = HashedDescription<H256, (DescribeHere, DescribeFamily<DescribeAllTerminal>)>;
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
mod tests {
|
||||
use frame_support::traits::Contains;
|
||||
use snowbridge_core::AllowSiblingsOnly;
|
||||
use xcm::prelude::{Junction::Parachain, Junctions::X1, MultiLocation};
|
||||
use xcm::prelude::{Junction::Parachain, Location};
|
||||
|
||||
#[test]
|
||||
fn allow_siblings_predicate_only_allows_siblings() {
|
||||
let sibling = MultiLocation::new(1, X1(Parachain(1000)));
|
||||
let child = MultiLocation::new(0, X1(Parachain(1000)));
|
||||
let sibling = Location::new(1, [Parachain(1000)]);
|
||||
let child = Location::new(0, [Parachain(1000)]);
|
||||
assert!(AllowSiblingsOnly::contains(&sibling), "Sibling returns true.");
|
||||
assert!(!AllowSiblingsOnly::contains(&child), "Child returns false.");
|
||||
}
|
||||
|
||||
@@ -161,13 +161,13 @@ where
|
||||
{
|
||||
fn convert_register_token(chain_id: u64, token: H160, fee: u128) -> (Xcm<()>, Balance) {
|
||||
let network = Ethereum { chain_id };
|
||||
let xcm_fee: MultiAsset = (MultiLocation::parent(), fee).into();
|
||||
let deposit: MultiAsset = (MultiLocation::parent(), CreateAssetDeposit::get()).into();
|
||||
let xcm_fee: Asset = (Location::parent(), fee).into();
|
||||
let deposit: Asset = (Location::parent(), CreateAssetDeposit::get()).into();
|
||||
|
||||
let total_amount = fee + CreateAssetDeposit::get();
|
||||
let total: MultiAsset = (MultiLocation::parent(), total_amount).into();
|
||||
let total: Asset = (Location::parent(), total_amount).into();
|
||||
|
||||
let bridge_location: MultiLocation = (Parent, Parent, GlobalConsensus(network)).into();
|
||||
let bridge_location: Location = (Parent, Parent, GlobalConsensus(network)).into();
|
||||
|
||||
let owner = GlobalConsensusEthereumConvertsFor::<[u8; 32]>::from_chain_id(&chain_id);
|
||||
let asset_id = Self::convert_token_address(network, token);
|
||||
@@ -182,7 +182,7 @@ where
|
||||
// Fund the snowbridge sovereign with the required deposit for creation.
|
||||
DepositAsset { assets: Definite(deposit.into()), beneficiary: bridge_location },
|
||||
// Only our inbound-queue pallet is allowed to invoke `UniversalOrigin`
|
||||
DescendOrigin(X1(PalletInstance(inbound_queue_pallet_index))),
|
||||
DescendOrigin(PalletInstance(inbound_queue_pallet_index).into()),
|
||||
// Change origin to the bridge.
|
||||
UniversalOrigin(GlobalConsensus(network)),
|
||||
// Call create_asset on foreign assets pallet.
|
||||
@@ -216,40 +216,37 @@ where
|
||||
asset_hub_fee: u128,
|
||||
) -> (Xcm<()>, Balance) {
|
||||
let network = Ethereum { chain_id };
|
||||
let asset_hub_fee_asset: MultiAsset = (MultiLocation::parent(), asset_hub_fee).into();
|
||||
let asset: MultiAsset = (Self::convert_token_address(network, token), amount).into();
|
||||
let asset_hub_fee_asset: Asset = (Location::parent(), asset_hub_fee).into();
|
||||
let asset: Asset = (Self::convert_token_address(network, token), amount).into();
|
||||
|
||||
let (dest_para_id, beneficiary, dest_para_fee) = match destination {
|
||||
// Final destination is a 32-byte account on AssetHub
|
||||
Destination::AccountId32 { id } => (
|
||||
None,
|
||||
MultiLocation { parents: 0, interior: X1(AccountId32 { network: None, id }) },
|
||||
0,
|
||||
),
|
||||
Destination::AccountId32 { id } =>
|
||||
(None, Location::new(0, [AccountId32 { network: None, id }]), 0),
|
||||
// Final destination is a 32-byte account on a sibling of AssetHub
|
||||
Destination::ForeignAccountId32 { para_id, id, fee } => (
|
||||
Some(para_id),
|
||||
MultiLocation { parents: 0, interior: X1(AccountId32 { network: None, id }) },
|
||||
Location::new(0, [AccountId32 { network: None, id }]),
|
||||
// Total fee needs to cover execution on AssetHub and Sibling
|
||||
fee,
|
||||
),
|
||||
// Final destination is a 20-byte account on a sibling of AssetHub
|
||||
Destination::ForeignAccountId20 { para_id, id, fee } => (
|
||||
Some(para_id),
|
||||
MultiLocation { parents: 0, interior: X1(AccountKey20 { network: None, key: id }) },
|
||||
Location::new(0, [AccountKey20 { network: None, key: id }]),
|
||||
// Total fee needs to cover execution on AssetHub and Sibling
|
||||
fee,
|
||||
),
|
||||
};
|
||||
|
||||
let total_fees = asset_hub_fee.saturating_add(dest_para_fee);
|
||||
let total_fee_asset: MultiAsset = (MultiLocation::parent(), total_fees).into();
|
||||
let total_fee_asset: Asset = (Location::parent(), total_fees).into();
|
||||
let inbound_queue_pallet_index = InboundQueuePalletInstance::get();
|
||||
|
||||
let mut instructions = vec![
|
||||
ReceiveTeleportedAsset(total_fee_asset.into()),
|
||||
BuyExecution { fees: asset_hub_fee_asset, weight_limit: Unlimited },
|
||||
DescendOrigin(X1(PalletInstance(inbound_queue_pallet_index))),
|
||||
DescendOrigin(PalletInstance(inbound_queue_pallet_index).into()),
|
||||
UniversalOrigin(GlobalConsensus(network)),
|
||||
ReserveAssetDeposited(asset.clone().into()),
|
||||
ClearOrigin,
|
||||
@@ -257,14 +254,13 @@ where
|
||||
|
||||
match dest_para_id {
|
||||
Some(dest_para_id) => {
|
||||
let dest_para_fee_asset: MultiAsset =
|
||||
(MultiLocation::parent(), dest_para_fee).into();
|
||||
let dest_para_fee_asset: Asset = (Location::parent(), dest_para_fee).into();
|
||||
|
||||
instructions.extend(vec![
|
||||
// Perform a deposit reserve to send to destination chain.
|
||||
DepositReserveAsset {
|
||||
assets: Definite(vec![dest_para_fee_asset.clone(), asset.clone()].into()),
|
||||
dest: MultiLocation { parents: 1, interior: X1(Parachain(dest_para_id)) },
|
||||
dest: Location::new(1, [Parachain(dest_para_id)]),
|
||||
xcm: vec![
|
||||
// Buy execution on target.
|
||||
BuyExecution { fees: dest_para_fee_asset, weight_limit: Unlimited },
|
||||
@@ -286,15 +282,12 @@ where
|
||||
(instructions.into(), total_fees.into())
|
||||
}
|
||||
|
||||
// Convert ERC20 token address to a Multilocation that can be understood by Assets Hub.
|
||||
fn convert_token_address(network: NetworkId, token: H160) -> MultiLocation {
|
||||
MultiLocation {
|
||||
parents: 2,
|
||||
interior: X2(
|
||||
GlobalConsensus(network),
|
||||
AccountKey20 { network: None, key: token.into() },
|
||||
),
|
||||
}
|
||||
// Convert ERC20 token address to a location that can be understood by Assets Hub.
|
||||
fn convert_token_address(network: NetworkId, token: H160) -> Location {
|
||||
Location::new(
|
||||
2,
|
||||
[GlobalConsensus(network), AccountKey20 { network: None, key: token.into() }],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,12 +296,11 @@ impl<AccountId> ConvertLocation<AccountId> for GlobalConsensusEthereumConvertsFo
|
||||
where
|
||||
AccountId: From<[u8; 32]> + Clone,
|
||||
{
|
||||
fn convert_location(location: &MultiLocation) -> Option<AccountId> {
|
||||
if let MultiLocation { interior: X1(GlobalConsensus(Ethereum { chain_id })), .. } = location
|
||||
{
|
||||
Some(Self::from_chain_id(chain_id).into())
|
||||
} else {
|
||||
None
|
||||
fn convert_location(location: &Location) -> Option<AccountId> {
|
||||
match location.unpack() {
|
||||
(_, [GlobalConsensus(Ethereum { chain_id })]) =>
|
||||
Some(Self::from_chain_id(chain_id).into()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use super::GlobalConsensusEthereumConvertsFor;
|
||||
use crate::inbound::CallIndex;
|
||||
use frame_support::parameter_types;
|
||||
use hex_literal::hex;
|
||||
use xcm::v3::prelude::*;
|
||||
use xcm::v4::prelude::*;
|
||||
use xcm_executor::traits::ConvertLocation;
|
||||
|
||||
const NETWORK: NetworkId = Ethereum { chain_id: 11155111 };
|
||||
@@ -20,7 +20,7 @@ parameter_types! {
|
||||
fn test_contract_location_with_network_converts_successfully() {
|
||||
let expected_account: [u8; 32] =
|
||||
hex!("ce796ae65569a670d0c1cc1ac12515a3ce21b5fbf729d63d7b289baad070139d");
|
||||
let contract_location = MultiLocation { parents: 2, interior: X1(GlobalConsensus(NETWORK)) };
|
||||
let contract_location = Location::new(2, [GlobalConsensus(NETWORK)]);
|
||||
|
||||
let account =
|
||||
GlobalConsensusEthereumConvertsFor::<[u8; 32]>::convert_location(&contract_location)
|
||||
@@ -31,8 +31,7 @@ fn test_contract_location_with_network_converts_successfully() {
|
||||
|
||||
#[test]
|
||||
fn test_contract_location_with_incorrect_location_fails_convert() {
|
||||
let contract_location =
|
||||
MultiLocation { parents: 2, interior: X2(GlobalConsensus(Polkadot), Parachain(1000)) };
|
||||
let contract_location = Location::new(2, [GlobalConsensus(Polkadot), Parachain(1000)]);
|
||||
|
||||
assert_eq!(
|
||||
GlobalConsensusEthereumConvertsFor::<[u8; 32]>::convert_location(&contract_location),
|
||||
|
||||
@@ -16,7 +16,7 @@ use snowbridge_core::{
|
||||
};
|
||||
use sp_core::{H160, H256};
|
||||
use sp_std::{iter::Peekable, marker::PhantomData, prelude::*};
|
||||
use xcm::v3::prelude::*;
|
||||
use xcm::v4::prelude::*;
|
||||
use xcm_executor::traits::{ConvertLocation, ExportXcm};
|
||||
|
||||
pub struct EthereumBlobExporter<
|
||||
@@ -29,7 +29,7 @@ pub struct EthereumBlobExporter<
|
||||
impl<UniversalLocation, EthereumNetwork, OutboundQueue, AgentHashedDescription> ExportXcm
|
||||
for EthereumBlobExporter<UniversalLocation, EthereumNetwork, OutboundQueue, AgentHashedDescription>
|
||||
where
|
||||
UniversalLocation: Get<InteriorMultiLocation>,
|
||||
UniversalLocation: Get<InteriorLocation>,
|
||||
EthereumNetwork: Get<NetworkId>,
|
||||
OutboundQueue: SendMessage<Balance = u128>,
|
||||
AgentHashedDescription: ConvertLocation<H256>,
|
||||
@@ -39,8 +39,8 @@ where
|
||||
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<()>>,
|
||||
) -> SendResult<Self::Ticket> {
|
||||
let expected_network = EthereumNetwork::get();
|
||||
@@ -74,8 +74,8 @@ where
|
||||
return Err(SendError::NotApplicable)
|
||||
}
|
||||
|
||||
let para_id = match local_sub {
|
||||
X1(Parachain(para_id)) => para_id,
|
||||
let para_id = match local_sub.as_slice() {
|
||||
[Parachain(para_id)] => *para_id,
|
||||
_ => {
|
||||
log::error!(target: "xcm::ethereum_blob_exporter", "could not get parachain id from universal source '{local_sub:?}'.");
|
||||
return Err(SendError::MissingArgument)
|
||||
@@ -93,7 +93,7 @@ where
|
||||
SendError::Unroutable
|
||||
})?;
|
||||
|
||||
let source_location: MultiLocation = MultiLocation { parents: 1, interior: local_sub };
|
||||
let source_location = Location::new(1, local_sub.clone());
|
||||
let agent_id = match AgentHashedDescription::convert_location(&source_location) {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
@@ -116,8 +116,8 @@ where
|
||||
SendError::Unroutable
|
||||
})?;
|
||||
|
||||
// convert fee to MultiAsset
|
||||
let fee = MultiAsset::from((MultiLocation::parent(), fee.total())).into();
|
||||
// convert fee to Asset
|
||||
let fee = Asset::from((Location::parent(), fee.total())).into();
|
||||
|
||||
Ok(((ticket.encode(), message_id), fee))
|
||||
}
|
||||
@@ -216,8 +216,8 @@ impl<'a, Call> XcmConverter<'a, Call> {
|
||||
|
||||
// assert that the beneficiary is AccountKey20.
|
||||
let recipient = match_expression!(
|
||||
beneficiary,
|
||||
MultiLocation { parents: 0, interior: X1(AccountKey20 { network, key }) }
|
||||
beneficiary.unpack(),
|
||||
(0, [AccountKey20 { network, key }])
|
||||
if self.network_matches(network),
|
||||
H160(*key)
|
||||
)
|
||||
@@ -245,14 +245,15 @@ impl<'a, Call> XcmConverter<'a, Call> {
|
||||
}
|
||||
}
|
||||
|
||||
let (token, amount) = match_expression!(
|
||||
reserve_asset,
|
||||
MultiAsset {
|
||||
id: Concrete(MultiLocation { parents: 0, interior: X1(AccountKey20 { network , key })}),
|
||||
fun: Fungible(amount)
|
||||
} if self.network_matches(network),
|
||||
(H160(*key), *amount)
|
||||
)
|
||||
let (token, amount) = match reserve_asset {
|
||||
Asset { id: AssetId(inner_location), fun: Fungible(amount) } =>
|
||||
match inner_location.unpack() {
|
||||
(0, [AccountKey20 { network, key }]) if self.network_matches(network) =>
|
||||
Some((H160(*key), *amount)),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
.ok_or(AssetResolutionFailed)?;
|
||||
|
||||
// transfer amount must be greater than 0.
|
||||
|
||||
@@ -11,7 +11,7 @@ use super::*;
|
||||
parameter_types! {
|
||||
const MaxMessageSize: u32 = u32::MAX;
|
||||
const RelayNetwork: NetworkId = Polkadot;
|
||||
const UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(RelayNetwork::get()), Parachain(1013));
|
||||
UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get()), Parachain(1013)].into();
|
||||
const BridgedNetwork: NetworkId = Ethereum{ chain_id: 1 };
|
||||
const NonBridgedNetwork: NetworkId = Ethereum{ chain_id: 2 };
|
||||
}
|
||||
@@ -61,8 +61,8 @@ impl SendMessageFeeProvider for MockErrOutboundQueue {
|
||||
fn exporter_validate_with_unknown_network_yields_not_applicable() {
|
||||
let network = Ethereum { chain_id: 1337 };
|
||||
let channel: u32 = 0;
|
||||
let mut universal_source: Option<InteriorMultiLocation> = None;
|
||||
let mut destination: Option<InteriorMultiLocation> = None;
|
||||
let mut universal_source: Option<InteriorLocation> = None;
|
||||
let mut destination: Option<InteriorLocation> = None;
|
||||
let mut message: Option<Xcm<()>> = None;
|
||||
|
||||
let result = EthereumBlobExporter::<
|
||||
@@ -80,8 +80,8 @@ fn exporter_validate_with_unknown_network_yields_not_applicable() {
|
||||
fn exporter_validate_with_invalid_destination_yields_missing_argument() {
|
||||
let network = BridgedNetwork::get();
|
||||
let channel: u32 = 0;
|
||||
let mut universal_source: Option<InteriorMultiLocation> = None;
|
||||
let mut destination: Option<InteriorMultiLocation> = None;
|
||||
let mut universal_source: Option<InteriorLocation> = None;
|
||||
let mut destination: Option<InteriorLocation> = None;
|
||||
let mut message: Option<Xcm<()>> = None;
|
||||
|
||||
let result = EthereumBlobExporter::<
|
||||
@@ -99,10 +99,11 @@ fn exporter_validate_with_invalid_destination_yields_missing_argument() {
|
||||
fn exporter_validate_with_x8_destination_yields_not_applicable() {
|
||||
let network = BridgedNetwork::get();
|
||||
let channel: u32 = 0;
|
||||
let mut universal_source: Option<InteriorMultiLocation> = None;
|
||||
let mut destination: Option<InteriorMultiLocation> = Some(X8(
|
||||
OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild,
|
||||
));
|
||||
let mut universal_source: Option<InteriorLocation> = None;
|
||||
let mut destination: Option<InteriorLocation> = Some(
|
||||
[OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild]
|
||||
.into(),
|
||||
);
|
||||
let mut message: Option<Xcm<()>> = None;
|
||||
|
||||
let result = EthereumBlobExporter::<
|
||||
@@ -120,8 +121,8 @@ fn exporter_validate_with_x8_destination_yields_not_applicable() {
|
||||
fn exporter_validate_without_universal_source_yields_missing_argument() {
|
||||
let network = BridgedNetwork::get();
|
||||
let channel: u32 = 0;
|
||||
let mut universal_source: Option<InteriorMultiLocation> = None;
|
||||
let mut destination: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut universal_source: Option<InteriorLocation> = None;
|
||||
let mut destination: Option<InteriorLocation> = Here.into();
|
||||
let mut message: Option<Xcm<()>> = None;
|
||||
|
||||
let result = EthereumBlobExporter::<
|
||||
@@ -139,8 +140,8 @@ fn exporter_validate_without_universal_source_yields_missing_argument() {
|
||||
fn exporter_validate_without_global_universal_location_yields_unroutable() {
|
||||
let network = BridgedNetwork::get();
|
||||
let channel: u32 = 0;
|
||||
let mut universal_source: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut destination: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut universal_source: Option<InteriorLocation> = Here.into();
|
||||
let mut destination: Option<InteriorLocation> = Here.into();
|
||||
let mut message: Option<Xcm<()>> = None;
|
||||
|
||||
let result = EthereumBlobExporter::<
|
||||
@@ -158,8 +159,8 @@ fn exporter_validate_without_global_universal_location_yields_unroutable() {
|
||||
fn exporter_validate_without_global_bridge_location_yields_not_applicable() {
|
||||
let network = NonBridgedNetwork::get();
|
||||
let channel: u32 = 0;
|
||||
let mut universal_source: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut destination: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut universal_source: Option<InteriorLocation> = Here.into();
|
||||
let mut destination: Option<InteriorLocation> = Here.into();
|
||||
let mut message: Option<Xcm<()>> = None;
|
||||
|
||||
let result = EthereumBlobExporter::<
|
||||
@@ -177,9 +178,9 @@ fn exporter_validate_without_global_bridge_location_yields_not_applicable() {
|
||||
fn exporter_validate_with_remote_universal_source_yields_not_applicable() {
|
||||
let network = BridgedNetwork::get();
|
||||
let channel: u32 = 0;
|
||||
let mut universal_source: Option<InteriorMultiLocation> =
|
||||
Some(X2(GlobalConsensus(Kusama), Parachain(1000)));
|
||||
let mut destination: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut universal_source: Option<InteriorLocation> =
|
||||
Some([GlobalConsensus(Kusama), Parachain(1000)].into());
|
||||
let mut destination: Option<InteriorLocation> = Here.into();
|
||||
let mut message: Option<Xcm<()>> = None;
|
||||
|
||||
let result = EthereumBlobExporter::<
|
||||
@@ -197,8 +198,8 @@ fn exporter_validate_with_remote_universal_source_yields_not_applicable() {
|
||||
fn exporter_validate_without_para_id_in_source_yields_missing_argument() {
|
||||
let network = BridgedNetwork::get();
|
||||
let channel: u32 = 0;
|
||||
let mut universal_source: Option<InteriorMultiLocation> = Some(X1(GlobalConsensus(Polkadot)));
|
||||
let mut destination: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut universal_source: Option<InteriorLocation> = Some(GlobalConsensus(Polkadot).into());
|
||||
let mut destination: Option<InteriorLocation> = Here.into();
|
||||
let mut message: Option<Xcm<()>> = None;
|
||||
|
||||
let result = EthereumBlobExporter::<
|
||||
@@ -216,9 +217,9 @@ fn exporter_validate_without_para_id_in_source_yields_missing_argument() {
|
||||
fn exporter_validate_complex_para_id_in_source_yields_missing_argument() {
|
||||
let network = BridgedNetwork::get();
|
||||
let channel: u32 = 0;
|
||||
let mut universal_source: Option<InteriorMultiLocation> =
|
||||
Some(X3(GlobalConsensus(Polkadot), Parachain(1000), PalletInstance(12)));
|
||||
let mut destination: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut universal_source: Option<InteriorLocation> =
|
||||
Some([GlobalConsensus(Polkadot), Parachain(1000), PalletInstance(12)].into());
|
||||
let mut destination: Option<InteriorLocation> = Here.into();
|
||||
let mut message: Option<Xcm<()>> = None;
|
||||
|
||||
let result = EthereumBlobExporter::<
|
||||
@@ -236,9 +237,9 @@ fn exporter_validate_complex_para_id_in_source_yields_missing_argument() {
|
||||
fn exporter_validate_without_xcm_message_yields_missing_argument() {
|
||||
let network = BridgedNetwork::get();
|
||||
let channel: u32 = 0;
|
||||
let mut universal_source: Option<InteriorMultiLocation> =
|
||||
Some(X2(GlobalConsensus(Polkadot), Parachain(1000)));
|
||||
let mut destination: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut universal_source: Option<InteriorLocation> =
|
||||
Some([GlobalConsensus(Polkadot), Parachain(1000)].into());
|
||||
let mut destination: Option<InteriorLocation> = Here.into();
|
||||
let mut message: Option<Xcm<()>> = None;
|
||||
|
||||
let result = EthereumBlobExporter::<
|
||||
@@ -255,23 +256,23 @@ fn exporter_validate_without_xcm_message_yields_missing_argument() {
|
||||
#[test]
|
||||
fn exporter_validate_with_max_target_fee_yields_unroutable() {
|
||||
let network = BridgedNetwork::get();
|
||||
let mut destination: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut destination: Option<InteriorLocation> = Here.into();
|
||||
|
||||
let mut universal_source: Option<InteriorMultiLocation> =
|
||||
Some(X2(GlobalConsensus(Polkadot), Parachain(1000)));
|
||||
let mut universal_source: Option<InteriorLocation> =
|
||||
Some([GlobalConsensus(Polkadot), Parachain(1000)].into());
|
||||
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let channel: u32 = 0;
|
||||
let fee = MultiAsset { id: Concrete(Here.into()), fun: Fungible(1000) };
|
||||
let fees: MultiAssets = vec![fee.clone()].into();
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let fee = Asset { id: AssetId(Here.into()), fun: Fungible(1000) };
|
||||
let fees: Assets = vec![fee.clone()].into();
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId(AccountKey20 { network: None, key: token_address }.into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let mut message: Option<Xcm<()>> = Some(
|
||||
vec![
|
||||
@@ -280,7 +281,7 @@ fn exporter_validate_with_max_target_fee_yields_unroutable() {
|
||||
WithdrawAsset(assets),
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: Some(network), key: beneficiary_address })
|
||||
beneficiary: AccountKey20 { network: Some(network), key: beneficiary_address }
|
||||
.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
@@ -303,14 +304,14 @@ fn exporter_validate_with_max_target_fee_yields_unroutable() {
|
||||
#[test]
|
||||
fn exporter_validate_with_unparsable_xcm_yields_unroutable() {
|
||||
let network = BridgedNetwork::get();
|
||||
let mut destination: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut destination: Option<InteriorLocation> = Here.into();
|
||||
|
||||
let mut universal_source: Option<InteriorMultiLocation> =
|
||||
Some(X2(GlobalConsensus(Polkadot), Parachain(1000)));
|
||||
let mut universal_source: Option<InteriorLocation> =
|
||||
Some([GlobalConsensus(Polkadot), Parachain(1000)].into());
|
||||
|
||||
let channel: u32 = 0;
|
||||
let fee = MultiAsset { id: Concrete(Here.into()), fun: Fungible(1000) };
|
||||
let fees: MultiAssets = vec![fee.clone()].into();
|
||||
let fee = Asset { id: AssetId(Here.into()), fun: Fungible(1000) };
|
||||
let fees: Assets = vec![fee.clone()].into();
|
||||
|
||||
let mut message: Option<Xcm<()>> =
|
||||
Some(vec![WithdrawAsset(fees), BuyExecution { fees: fee, weight_limit: Unlimited }].into());
|
||||
@@ -330,22 +331,22 @@ fn exporter_validate_with_unparsable_xcm_yields_unroutable() {
|
||||
#[test]
|
||||
fn exporter_validate_xcm_success_case_1() {
|
||||
let network = BridgedNetwork::get();
|
||||
let mut destination: Option<InteriorMultiLocation> = Here.into();
|
||||
let mut destination: Option<InteriorLocation> = Here.into();
|
||||
|
||||
let mut universal_source: Option<InteriorMultiLocation> =
|
||||
Some(X2(GlobalConsensus(Polkadot), Parachain(1000)));
|
||||
let mut universal_source: Option<InteriorLocation> =
|
||||
Some([GlobalConsensus(Polkadot), Parachain(1000)].into());
|
||||
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let channel: u32 = 0;
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId([AccountKey20 { network: None, key: token_address }].into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let fee = assets.clone().get(0).unwrap().clone();
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let mut message: Option<Xcm<()>> = Some(
|
||||
vec![
|
||||
@@ -354,7 +355,7 @@ fn exporter_validate_xcm_success_case_1() {
|
||||
BuyExecution { fees: fee, weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -391,12 +392,12 @@ fn xcm_converter_convert_success() {
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId([AccountKey20 { network: None, key: token_address }].into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -404,7 +405,7 @@ fn xcm_converter_convert_success() {
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -426,18 +427,18 @@ fn xcm_converter_convert_without_buy_execution_yields_success() {
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId([AccountKey20 { network: None, key: token_address }].into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -459,12 +460,12 @@ fn xcm_converter_convert_with_wildcard_all_asset_filter_succeeds() {
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId([AccountKey20 { network: None, key: token_address }].into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = Wild(All);
|
||||
let filter: AssetFilter = Wild(All);
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -472,7 +473,7 @@ fn xcm_converter_convert_with_wildcard_all_asset_filter_succeeds() {
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -494,13 +495,12 @@ fn xcm_converter_convert_with_fees_less_than_reserve_yields_success() {
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let asset_location = X1(AccountKey20 { network: None, key: token_address }).into();
|
||||
let fee_asset = MultiAsset { id: Concrete(asset_location), fun: Fungible(500) };
|
||||
let asset_location: Location = [AccountKey20 { network: None, key: token_address }].into();
|
||||
let fee_asset = Asset { id: AssetId(asset_location.clone()), fun: Fungible(500) };
|
||||
|
||||
let assets: MultiAssets =
|
||||
vec![MultiAsset { id: Concrete(asset_location), fun: Fungible(1000) }].into();
|
||||
let assets: Assets = vec![Asset { id: AssetId(asset_location), fun: Fungible(1000) }].into();
|
||||
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -508,7 +508,7 @@ fn xcm_converter_convert_with_fees_less_than_reserve_yields_success() {
|
||||
BuyExecution { fees: fee_asset, weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -530,19 +530,19 @@ fn xcm_converter_convert_without_set_topic_yields_set_topic_expected() {
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId([AccountKey20 { network: None, key: token_address }].into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
ClearTopic,
|
||||
]
|
||||
@@ -557,8 +557,8 @@ fn xcm_converter_convert_with_partial_message_yields_unexpected_end_of_xcm() {
|
||||
let network = BridgedNetwork::get();
|
||||
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId([AccountKey20 { network: None, key: token_address }].into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
@@ -576,16 +576,13 @@ fn xcm_converter_with_different_fee_asset_fails() {
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let asset_location = X1(AccountKey20 { network: None, key: token_address }).into();
|
||||
let fee_asset = MultiAsset {
|
||||
id: Concrete(MultiLocation { parents: 0, interior: Here }),
|
||||
fun: Fungible(1000),
|
||||
};
|
||||
let asset_location = [AccountKey20 { network: None, key: token_address }].into();
|
||||
let fee_asset =
|
||||
Asset { id: AssetId(Location { parents: 0, interior: Here }), fun: Fungible(1000) };
|
||||
|
||||
let assets: MultiAssets =
|
||||
vec![MultiAsset { id: Concrete(asset_location), fun: Fungible(1000) }].into();
|
||||
let assets: Assets = vec![Asset { id: AssetId(asset_location), fun: Fungible(1000) }].into();
|
||||
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -593,7 +590,7 @@ fn xcm_converter_with_different_fee_asset_fails() {
|
||||
BuyExecution { fees: fee_asset, weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -610,13 +607,12 @@ fn xcm_converter_with_fees_greater_than_reserve_fails() {
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let asset_location = X1(AccountKey20 { network: None, key: token_address }).into();
|
||||
let fee_asset = MultiAsset { id: Concrete(asset_location), fun: Fungible(1001) };
|
||||
let asset_location: Location = [AccountKey20 { network: None, key: token_address }].into();
|
||||
let fee_asset = Asset { id: AssetId(asset_location.clone()), fun: Fungible(1001) };
|
||||
|
||||
let assets: MultiAssets =
|
||||
vec![MultiAsset { id: Concrete(asset_location), fun: Fungible(1000) }].into();
|
||||
let assets: Assets = vec![Asset { id: AssetId(asset_location), fun: Fungible(1000) }].into();
|
||||
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -624,7 +620,7 @@ fn xcm_converter_with_fees_greater_than_reserve_fails() {
|
||||
BuyExecution { fees: fee_asset, weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -653,12 +649,12 @@ fn xcm_converter_convert_with_extra_instructions_yields_end_of_xcm_message_expec
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId([AccountKey20 { network: None, key: token_address }].into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -666,7 +662,7 @@ fn xcm_converter_convert_with_extra_instructions_yields_end_of_xcm_message_expec
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
ClearError,
|
||||
@@ -685,19 +681,19 @@ fn xcm_converter_convert_without_withdraw_asset_yields_withdraw_expected() {
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId([AccountKey20 { network: None, key: token_address }].into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
ClearOrigin,
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -714,8 +710,8 @@ fn xcm_converter_convert_without_withdraw_asset_yields_deposit_expected() {
|
||||
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId(AccountKey20 { network: None, key: token_address }.into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
@@ -741,11 +737,11 @@ fn xcm_converter_convert_without_assets_yields_no_reserve_assets() {
|
||||
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![].into();
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let assets: Assets = vec![].into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let fee = MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let fee = Asset {
|
||||
id: AssetId(AccountKey20 { network: None, key: token_address }.into()),
|
||||
fun: Fungible(1000),
|
||||
};
|
||||
|
||||
@@ -755,7 +751,7 @@ fn xcm_converter_convert_without_assets_yields_no_reserve_assets() {
|
||||
BuyExecution { fees: fee, weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -774,18 +770,18 @@ fn xcm_converter_convert_with_two_assets_yields_too_many_assets() {
|
||||
let token_address_2: [u8; 20] = hex!("1100000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![
|
||||
MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address_1 }).into()),
|
||||
let assets: Assets = vec![
|
||||
Asset {
|
||||
id: AssetId(AccountKey20 { network: None, key: token_address_1 }.into()),
|
||||
fun: Fungible(1000),
|
||||
},
|
||||
MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address_2 }).into()),
|
||||
Asset {
|
||||
id: AssetId(AccountKey20 { network: None, key: token_address_2 }.into()),
|
||||
fun: Fungible(500),
|
||||
},
|
||||
]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = assets.clone().into();
|
||||
let filter: AssetFilter = assets.clone().into();
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -793,7 +789,7 @@ fn xcm_converter_convert_with_two_assets_yields_too_many_assets() {
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -811,12 +807,12 @@ fn xcm_converter_convert_without_consuming_filter_yields_filter_does_not_consume
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId(AccountKey20 { network: None, key: token_address }.into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = Wild(WildMultiAsset::AllCounted(0));
|
||||
let filter: AssetFilter = Wild(WildAsset::AllCounted(0));
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -824,7 +820,7 @@ fn xcm_converter_convert_without_consuming_filter_yields_filter_does_not_consume
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -842,12 +838,12 @@ fn xcm_converter_convert_with_zero_amount_asset_yields_zero_asset_transfer() {
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId(AccountKey20 { network: None, key: token_address }.into()),
|
||||
fun: Fungible(0),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = Wild(WildMultiAsset::AllCounted(1));
|
||||
let filter: AssetFilter = Wild(WildAsset::AllCounted(1));
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -855,7 +851,7 @@ fn xcm_converter_convert_with_zero_amount_asset_yields_zero_asset_transfer() {
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -872,12 +868,12 @@ fn xcm_converter_convert_non_ethereum_asset_yields_asset_resolution_failed() {
|
||||
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X3(GlobalConsensus(Polkadot), Parachain(1000), GeneralIndex(0)).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId([GlobalConsensus(Polkadot), Parachain(1000), GeneralIndex(0)].into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = Wild(WildMultiAsset::AllCounted(1));
|
||||
let filter: AssetFilter = Wild(WildAsset::AllCounted(1));
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -885,7 +881,7 @@ fn xcm_converter_convert_non_ethereum_asset_yields_asset_resolution_failed() {
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -903,14 +899,14 @@ fn xcm_converter_convert_non_ethereum_chain_asset_yields_asset_resolution_failed
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(
|
||||
X1(AccountKey20 { network: Some(Ethereum { chain_id: 2 }), key: token_address }).into(),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId(
|
||||
AccountKey20 { network: Some(Ethereum { chain_id: 2 }), key: token_address }.into(),
|
||||
),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = Wild(WildMultiAsset::AllCounted(1));
|
||||
let filter: AssetFilter = Wild(WildAsset::AllCounted(1));
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -918,7 +914,7 @@ fn xcm_converter_convert_non_ethereum_chain_asset_yields_asset_resolution_failed
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -936,14 +932,14 @@ fn xcm_converter_convert_non_ethereum_chain_yields_asset_resolution_failed() {
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(
|
||||
X1(AccountKey20 { network: Some(NonBridgedNetwork::get()), key: token_address }).into(),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId(
|
||||
[AccountKey20 { network: Some(NonBridgedNetwork::get()), key: token_address }].into(),
|
||||
),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = Wild(WildMultiAsset::AllCounted(1));
|
||||
let filter: AssetFilter = Wild(WildAsset::AllCounted(1));
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -951,7 +947,7 @@ fn xcm_converter_convert_non_ethereum_chain_yields_asset_resolution_failed() {
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 { network: None, key: beneficiary_address }).into(),
|
||||
beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]
|
||||
@@ -971,23 +967,23 @@ fn xcm_converter_convert_with_non_ethereum_beneficiary_yields_beneficiary_resolu
|
||||
let beneficiary_address: [u8; 32] =
|
||||
hex!("2000000000000000000000000000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId(AccountKey20 { network: None, key: token_address }.into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = Wild(WildMultiAsset::AllCounted(1));
|
||||
let filter: AssetFilter = Wild(WildAsset::AllCounted(1));
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
ClearOrigin,
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X3(
|
||||
beneficiary: [
|
||||
GlobalConsensus(Polkadot),
|
||||
Parachain(1000),
|
||||
AccountId32 { network: Some(Polkadot), id: beneficiary_address },
|
||||
)
|
||||
]
|
||||
.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
@@ -1007,12 +1003,12 @@ fn xcm_converter_convert_with_non_ethereum_chain_beneficiary_yields_beneficiary_
|
||||
let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000");
|
||||
let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000");
|
||||
|
||||
let assets: MultiAssets = vec![MultiAsset {
|
||||
id: Concrete(X1(AccountKey20 { network: None, key: token_address }).into()),
|
||||
let assets: Assets = vec![Asset {
|
||||
id: AssetId(AccountKey20 { network: None, key: token_address }.into()),
|
||||
fun: Fungible(1000),
|
||||
}]
|
||||
.into();
|
||||
let filter: MultiAssetFilter = Wild(WildMultiAsset::AllCounted(1));
|
||||
let filter: AssetFilter = Wild(WildAsset::AllCounted(1));
|
||||
|
||||
let message: Xcm<()> = vec![
|
||||
WithdrawAsset(assets.clone()),
|
||||
@@ -1020,10 +1016,10 @@ fn xcm_converter_convert_with_non_ethereum_chain_beneficiary_yields_beneficiary_
|
||||
BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: filter,
|
||||
beneficiary: X1(AccountKey20 {
|
||||
beneficiary: AccountKey20 {
|
||||
network: Some(Ethereum { chain_id: 2 }),
|
||||
key: beneficiary_address,
|
||||
})
|
||||
}
|
||||
.into(),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
@@ -1037,14 +1033,13 @@ fn xcm_converter_convert_with_non_ethereum_chain_beneficiary_yields_beneficiary_
|
||||
|
||||
#[test]
|
||||
fn test_describe_asset_hub() {
|
||||
let legacy_location: MultiLocation =
|
||||
MultiLocation { parents: 0, interior: X1(Parachain(1000)) };
|
||||
let legacy_location: Location = Location::new(0, [Parachain(1000)]);
|
||||
let legacy_agent_id = AgentIdOf::convert_location(&legacy_location).unwrap();
|
||||
assert_eq!(
|
||||
legacy_agent_id,
|
||||
hex!("72456f48efed08af20e5b317abf8648ac66e86bb90a411d9b0b713f7364b75b4").into()
|
||||
);
|
||||
let location: MultiLocation = MultiLocation { parents: 1, interior: X1(Parachain(1000)) };
|
||||
let location: Location = Location::new(1, [Parachain(1000)]);
|
||||
let agent_id = AgentIdOf::convert_location(&location).unwrap();
|
||||
assert_eq!(
|
||||
agent_id,
|
||||
@@ -1054,7 +1049,7 @@ fn test_describe_asset_hub() {
|
||||
|
||||
#[test]
|
||||
fn test_describe_here() {
|
||||
let location: MultiLocation = MultiLocation { parents: 0, interior: Here };
|
||||
let location: Location = Location::new(0, []);
|
||||
let agent_id = AgentIdOf::convert_location(&location).unwrap();
|
||||
assert_eq!(
|
||||
agent_id,
|
||||
|
||||
@@ -46,43 +46,38 @@ impl<Balance, AccountId, FeeAssetLocation, EthereumNetwork, AssetTransactor, Fee
|
||||
> where
|
||||
Balance: BaseArithmetic + Unsigned + Copy + From<u128> + Into<u128>,
|
||||
AccountId: Clone + Into<[u8; 32]> + From<[u8; 32]>,
|
||||
FeeAssetLocation: Get<MultiLocation>,
|
||||
FeeAssetLocation: Get<Location>,
|
||||
EthereumNetwork: Get<NetworkId>,
|
||||
AssetTransactor: TransactAsset,
|
||||
FeeProvider: SendMessageFeeProvider<Balance = Balance>,
|
||||
{
|
||||
fn handle_fee(
|
||||
fees: MultiAssets,
|
||||
context: Option<&XcmContext>,
|
||||
reason: FeeReason,
|
||||
) -> MultiAssets {
|
||||
fn handle_fee(fees: Assets, context: Option<&XcmContext>, reason: FeeReason) -> Assets {
|
||||
let token_location = FeeAssetLocation::get();
|
||||
|
||||
// Check the reason to see if this export is for snowbridge.
|
||||
if !matches!(
|
||||
reason,
|
||||
FeeReason::Export { network: bridged_network, destination }
|
||||
if bridged_network == EthereumNetwork::get() && destination == Here
|
||||
FeeReason::Export { network: bridged_network, ref destination }
|
||||
if bridged_network == EthereumNetwork::get() && destination == &Here
|
||||
) {
|
||||
return fees
|
||||
}
|
||||
|
||||
// Get the parachain sovereign from the `context`.
|
||||
let para_sovereign = if let Some(XcmContext {
|
||||
origin: Some(MultiLocation { parents: 1, interior }),
|
||||
..
|
||||
}) = context
|
||||
{
|
||||
if let Some(Parachain(sibling_para_id)) = interior.first() {
|
||||
let account: AccountId =
|
||||
sibling_sovereign_account_raw((*sibling_para_id).into()).into();
|
||||
account
|
||||
let para_sovereign =
|
||||
if let Some(XcmContext { origin: Some(Location { parents: 1, interior }), .. }) =
|
||||
context
|
||||
{
|
||||
if let Some(Parachain(sibling_para_id)) = interior.first() {
|
||||
let account: AccountId =
|
||||
sibling_sovereign_account_raw((*sibling_para_id).into()).into();
|
||||
account
|
||||
} else {
|
||||
return fees
|
||||
}
|
||||
} else {
|
||||
return fees
|
||||
}
|
||||
} else {
|
||||
return fees
|
||||
};
|
||||
};
|
||||
|
||||
// Get the total fee offered by export message.
|
||||
let maybe_total_supplied_fee: Option<(usize, Balance)> = fees
|
||||
@@ -90,8 +85,8 @@ impl<Balance, AccountId, FeeAssetLocation, EthereumNetwork, AssetTransactor, Fee
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(index, asset)| {
|
||||
if let MultiAsset { id: Concrete(location), fun: Fungible(amount) } = asset {
|
||||
if *location == token_location {
|
||||
if let Asset { id: location, fun: Fungible(amount) } = asset {
|
||||
if location.0 == token_location {
|
||||
return Some((index, (*amount).into()))
|
||||
}
|
||||
}
|
||||
@@ -104,7 +99,7 @@ impl<Balance, AccountId, FeeAssetLocation, EthereumNetwork, AssetTransactor, Fee
|
||||
if remote_fee > (0u128).into() {
|
||||
// Refund remote component of fee to physical origin
|
||||
deposit_or_burn_fee::<AssetTransactor, _>(
|
||||
MultiAsset { id: Concrete(token_location), fun: Fungible(remote_fee.into()) }
|
||||
Asset { id: AssetId(token_location.clone()), fun: Fungible(remote_fee.into()) }
|
||||
.into(),
|
||||
context,
|
||||
para_sovereign,
|
||||
@@ -112,8 +107,8 @@ impl<Balance, AccountId, FeeAssetLocation, EthereumNetwork, AssetTransactor, Fee
|
||||
// Return remaining fee to the next fee handler in the chain.
|
||||
let mut modified_fees = fees.inner().clone();
|
||||
modified_fees.remove(fee_index);
|
||||
modified_fees.push(MultiAsset {
|
||||
id: Concrete(token_location),
|
||||
modified_fees.push(Asset {
|
||||
id: AssetId(token_location),
|
||||
fun: Fungible((total_fee - remote_fee).into()),
|
||||
});
|
||||
return modified_fees.into()
|
||||
|
||||
@@ -49,38 +49,36 @@ where
|
||||
+ snowbridge_pallet_outbound_queue::Config,
|
||||
XcmConfig: xcm_executor::Config,
|
||||
{
|
||||
let assethub_parachain_location = MultiLocation::new(1, Parachain(assethub_parachain_id));
|
||||
let asset = MultiAsset {
|
||||
id: Concrete(MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(AccountKey20 { network: None, key: weth_contract_address.into() }),
|
||||
}),
|
||||
let assethub_parachain_location = Location::new(1, Parachain(assethub_parachain_id));
|
||||
let asset = Asset {
|
||||
id: AssetId(Location::new(
|
||||
0,
|
||||
[AccountKey20 { network: None, key: weth_contract_address.into() }],
|
||||
)),
|
||||
fun: Fungible(1000000000),
|
||||
};
|
||||
let assets = vec![asset.clone()];
|
||||
|
||||
let inner_xcm = Xcm(vec![
|
||||
WithdrawAsset(MultiAssets::from(assets.clone())),
|
||||
WithdrawAsset(Assets::from(assets.clone())),
|
||||
ClearOrigin,
|
||||
BuyExecution { fees: asset, weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: Wild(All),
|
||||
beneficiary: MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(AccountKey20 { network: None, key: destination_address.into() }),
|
||||
},
|
||||
beneficiary: Location::new(
|
||||
0,
|
||||
[AccountKey20 { network: None, key: destination_address.into() }],
|
||||
),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]);
|
||||
|
||||
let fee = MultiAsset {
|
||||
id: Concrete(MultiLocation { parents: 1, interior: Here }),
|
||||
fun: Fungible(fee_amount),
|
||||
};
|
||||
let fee =
|
||||
Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(fee_amount) };
|
||||
|
||||
// prepare transfer token message
|
||||
let xcm = Xcm(vec![
|
||||
WithdrawAsset(MultiAssets::from(vec![fee.clone()])),
|
||||
WithdrawAsset(Assets::from(vec![fee.clone()])),
|
||||
BuyExecution { fees: fee, weight_limit: Unlimited },
|
||||
ExportMessage {
|
||||
network: Ethereum { chain_id: 11155111 },
|
||||
@@ -90,12 +88,13 @@ where
|
||||
]);
|
||||
|
||||
// execute XCM
|
||||
let hash = xcm.using_encoded(sp_io::hashing::blake2_256);
|
||||
XcmExecutor::<XcmConfig>::execute_xcm(
|
||||
let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
|
||||
XcmExecutor::<XcmConfig>::prepare_and_execute(
|
||||
assethub_parachain_location,
|
||||
xcm,
|
||||
hash,
|
||||
&mut hash,
|
||||
RuntimeHelper::<Runtime>::xcm_max_weight(XcmReceivedFrom::Sibling),
|
||||
Weight::zero(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -176,7 +175,7 @@ pub fn send_unpaid_transfer_token_message<Runtime, XcmConfig>(
|
||||
XcmConfig: xcm_executor::Config,
|
||||
ValidatorIdOf<Runtime>: From<AccountIdOf<Runtime>>,
|
||||
{
|
||||
let assethub_parachain_location = MultiLocation::new(1, Parachain(assethub_parachain_id));
|
||||
let assethub_parachain_location = Location::new(1, Parachain(assethub_parachain_id));
|
||||
|
||||
ExtBuilder::<Runtime>::default()
|
||||
.with_collators(collator_session_key.collators())
|
||||
@@ -194,28 +193,25 @@ pub fn send_unpaid_transfer_token_message<Runtime, XcmConfig>(
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let asset = MultiAsset {
|
||||
id: Concrete(MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(AccountKey20 { network: None, key: weth_contract_address.into() }),
|
||||
}),
|
||||
let asset = Asset {
|
||||
id: AssetId(Location::new(
|
||||
0,
|
||||
[AccountKey20 { network: None, key: weth_contract_address.into() }],
|
||||
)),
|
||||
fun: Fungible(1000000000),
|
||||
};
|
||||
let assets = vec![asset.clone()];
|
||||
|
||||
let inner_xcm = Xcm(vec![
|
||||
WithdrawAsset(MultiAssets::from(assets.clone())),
|
||||
WithdrawAsset(Assets::from(assets.clone())),
|
||||
ClearOrigin,
|
||||
BuyExecution { fees: asset, weight_limit: Unlimited },
|
||||
DepositAsset {
|
||||
assets: Wild(AllCounted(1)),
|
||||
beneficiary: MultiLocation {
|
||||
parents: 0,
|
||||
interior: X1(AccountKey20 {
|
||||
network: None,
|
||||
key: destination_contract.into(),
|
||||
}),
|
||||
},
|
||||
beneficiary: Location::new(
|
||||
0,
|
||||
[AccountKey20 { network: None, key: destination_contract.into() }],
|
||||
),
|
||||
},
|
||||
SetTopic([0; 32]),
|
||||
]);
|
||||
@@ -231,12 +227,13 @@ pub fn send_unpaid_transfer_token_message<Runtime, XcmConfig>(
|
||||
]);
|
||||
|
||||
// execute XCM
|
||||
let hash = xcm.using_encoded(sp_io::hashing::blake2_256);
|
||||
let outcome = XcmExecutor::<XcmConfig>::execute_xcm(
|
||||
let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
|
||||
let outcome = XcmExecutor::<XcmConfig>::prepare_and_execute(
|
||||
assethub_parachain_location,
|
||||
xcm,
|
||||
hash,
|
||||
&mut hash,
|
||||
RuntimeHelper::<Runtime>::xcm_max_weight(XcmReceivedFrom::Sibling),
|
||||
Weight::zero(),
|
||||
);
|
||||
// check error is barrier
|
||||
assert_err!(outcome.ensure_complete(), Barrier);
|
||||
|
||||
Reference in New Issue
Block a user