Skip to content

Commit 27bfc47

Browse files
committed
add MigrationPhase
1 parent c02a0ba commit 27bfc47

File tree

6 files changed

+152
-86
lines changed

6 files changed

+152
-86
lines changed

traits/src/location.rs

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,13 @@
11
use sp_core::{bounded::BoundedVec, ConstU32};
22
use xcm::v5::prelude::*;
33

4-
pub trait Parse {
5-
/// Returns the "chain" location part. It could be parent, sibling
6-
/// parachain, or child parachain.
7-
fn chain_part(&self) -> Option<Location>;
8-
/// Returns "non-chain" location part.
9-
fn non_chain_part(&self) -> Option<Location>;
10-
}
11-
12-
fn is_chain_junction(junction: Option<&Junction>) -> bool {
13-
matches!(junction, Some(Parachain(_)))
14-
}
15-
16-
impl Parse for Location {
17-
fn chain_part(&self) -> Option<Location> {
18-
match (self.parents, self.first_interior()) {
19-
// sibling parachain
20-
(1, Some(Parachain(id))) => Some(Location::new(1, [Parachain(*id)])),
21-
// parent
22-
(1, _) => Some(Location::parent()),
23-
// children parachain
24-
(0, Some(Parachain(id))) => Some(Location::new(0, [Parachain(*id)])),
25-
_ => None,
26-
}
27-
}
28-
29-
fn non_chain_part(&self) -> Option<Location> {
30-
let mut junctions = self.interior().clone();
31-
while is_chain_junction(junctions.first()) {
32-
let _ = junctions.take_first();
33-
}
34-
35-
if junctions != Here {
36-
Some(Location::new(0, junctions))
37-
} else {
38-
None
39-
}
40-
}
41-
}
4+
pub const ASSET_HUB_ID: u32 = 1000;
425

436
pub trait Reserve {
447
/// Returns assets reserve location.
458
fn reserve(asset: &Asset) -> Option<Location>;
469
}
4710

48-
// Provide reserve in absolute path view
49-
pub struct AbsoluteReserveProvider;
50-
51-
impl Reserve for AbsoluteReserveProvider {
52-
fn reserve(asset: &Asset) -> Option<Location> {
53-
let AssetId(location) = &asset.id;
54-
location.chain_part()
55-
}
56-
}
57-
58-
// Provide reserve in relative path view
59-
// Self tokens are represeneted as Here
60-
pub struct RelativeReserveProvider;
61-
62-
impl Reserve for RelativeReserveProvider {
63-
fn reserve(asset: &Asset) -> Option<Location> {
64-
let AssetId(location) = &asset.id;
65-
if location.parents == 0 && !is_chain_junction(location.first_interior()) {
66-
Some(Location::here())
67-
} else {
68-
location.chain_part()
69-
}
70-
}
71-
}
72-
7311
pub trait RelativeLocations {
7412
fn sibling_parachain_general_key(para_id: u32, general_key: BoundedVec<u8, ConstU32<32>>) -> Location;
7513
}

xtokens/src/lib.rs

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use xcm_executor::traits::WeightBounds;
5353

5454
pub use module::*;
5555
use orml_traits::{
56-
location::{Parse, Reserve},
56+
location::{Reserve, ASSET_HUB_ID},
5757
xcm_transfer::{Transferred, XtokensWeightInfo},
5858
GetByKey, RateLimiter, XcmTransfer,
5959
};
@@ -71,6 +71,19 @@ enum TransferKind {
7171
}
7272
use TransferKind::*;
7373

74+
#[derive(
75+
scale_info::TypeInfo, Default, Encode, Decode, Clone, Eq, PartialEq, Debug, MaxEncodedLen, DecodeWithMemTracking,
76+
)]
77+
pub enum MigrationPhase {
78+
/// Not started
79+
#[default]
80+
NotStarted,
81+
/// Started
82+
InProgress,
83+
/// Completed
84+
Completed,
85+
}
86+
7487
#[frame_support::pallet]
7588
pub mod module {
7689
use super::*;
@@ -135,8 +148,14 @@ pub mod module {
135148
/// The id of the RateLimiter.
136149
#[pallet::constant]
137150
type RateLimiterId: Get<<Self::RateLimiter as RateLimiter>::RateLimiterId>;
151+
152+
/// The origin that can change the migration phase.
153+
type MigrationPhaseUpdateOrigin: EnsureOrigin<Self::RuntimeOrigin>;
138154
}
139155

156+
#[pallet::storage]
157+
pub type MigrationStatus<T: Config> = StorageValue<_, MigrationPhase, ValueQuery>;
158+
140159
#[pallet::event]
141160
#[pallet::generate_deposit(fn deposit_event)]
142161
pub enum Event<T: Config> {
@@ -147,6 +166,8 @@ pub mod module {
147166
fee: Asset,
148167
dest: Location,
149168
},
169+
/// Migration phase changed.
170+
MigrationPhaseChanged { migration_phase: MigrationPhase },
150171
}
151172

152173
#[pallet::error]
@@ -394,6 +415,18 @@ pub mod module {
394415

395416
Self::do_transfer_assets(who, assets.clone(), fee.clone(), dest, dest_weight_limit).map(|_| ())
396417
}
418+
419+
#[pallet::call_index(6)]
420+
#[pallet::weight(frame_support::weights::Weight::from_parts(10000, 0))]
421+
pub fn set_migration_phase(origin: OriginFor<T>, migration_phase: MigrationPhase) -> DispatchResult {
422+
T::MigrationPhaseUpdateOrigin::ensure_origin(origin)?;
423+
424+
MigrationStatus::<T>::set(migration_phase.clone());
425+
426+
Self::deposit_event(Event::<T>::MigrationPhaseChanged { migration_phase });
427+
428+
Ok(())
429+
}
397430
}
398431

399432
impl<T: Config> Pallet<T> {
@@ -565,7 +598,7 @@ pub mod module {
565598
if asset_len > 1 && fee_reserve != non_fee_reserve {
566599
// Current only support `ToReserve` with relay-chain asset as fee. other case
567600
// like `NonReserve` or `SelfReserve` with relay-chain fee is not support.
568-
ensure!(non_fee_reserve == dest.chain_part(), Error::<T>::InvalidAsset);
601+
ensure!(non_fee_reserve == Self::chain_part(&dest), Error::<T>::InvalidAsset);
569602

570603
let reserve_location = non_fee_reserve.clone().ok_or(Error::<T>::AssetHasNoReserve)?;
571604
let min_xcm_fee = T::MinXcmFee::get(&reserve_location).ok_or(Error::<T>::MinXcmFeeNotDefined)?;
@@ -590,7 +623,7 @@ pub mod module {
590623

591624
let mut override_recipient = T::SelfLocation::get();
592625
if override_recipient == Location::here() {
593-
let dest_chain_part = dest.chain_part().ok_or(Error::<T>::InvalidDest)?;
626+
let dest_chain_part = Self::chain_part(&dest).ok_or(Error::<T>::InvalidDest)?;
594627
let ancestry = T::UniversalLocation::get();
595628
let _ = override_recipient
596629
.reanchor(&dest_chain_part, &ancestry)
@@ -817,7 +850,7 @@ pub mod module {
817850

818851
/// Ensure has the `dest` has chain part and recipient part.
819852
fn ensure_valid_dest(dest: &Location) -> Result<(Location, Location), DispatchError> {
820-
if let (Some(dest), Some(recipient)) = (dest.chain_part(), dest.non_chain_part()) {
853+
if let (Some(dest), Some(recipient)) = (Self::chain_part(&dest), Self::non_chain_part(&dest)) {
821854
Ok((dest, recipient))
822855
} else {
823856
Err(Error::<T>::InvalidDest.into())
@@ -863,6 +896,41 @@ pub mod module {
863896
let asset = assets.get(reserve_idx);
864897
asset.and_then(T::ReserveProvider::reserve)
865898
}
899+
900+
/// Returns the "chain" location part. It could be parent, sibling
901+
/// parachain, or child parachain.
902+
pub fn chain_part(location: &Location) -> Option<Location> {
903+
match (location.parents, location.first_interior()) {
904+
// sibling parachain
905+
(1, Some(Parachain(id))) => Some(Location::new(1, [Parachain(*id)])),
906+
// parent
907+
(1, _) => match MigrationStatus::<T>::get() {
908+
// RelayChain
909+
MigrationPhase::NotStarted => Some(Location::parent()),
910+
// Disable transfer when migration is in progress
911+
MigrationPhase::InProgress => None,
912+
// AssetHub
913+
MigrationPhase::Completed => Some(Location::new(1, [Parachain(ASSET_HUB_ID)])),
914+
},
915+
// children parachain
916+
(0, Some(Parachain(id))) => Some(Location::new(0, [Parachain(*id)])),
917+
_ => None,
918+
}
919+
}
920+
921+
/// Returns "non-chain" location part.
922+
pub fn non_chain_part(location: &Location) -> Option<Location> {
923+
let mut junctions = location.interior().clone();
924+
while is_chain_junction(junctions.first()) {
925+
let _ = junctions.take_first();
926+
}
927+
928+
if junctions != Here {
929+
Some(Location::new(0, junctions))
930+
} else {
931+
None
932+
}
933+
}
866934
}
867935

868936
pub struct XtokensWeight<T>(PhantomData<T>);
@@ -1066,3 +1134,32 @@ fn subtract_fee(asset: &Asset, amount: u128) -> Asset {
10661134
id: asset.id.clone(),
10671135
}
10681136
}
1137+
1138+
fn is_chain_junction(junction: Option<&Junction>) -> bool {
1139+
matches!(junction, Some(Parachain(_)))
1140+
}
1141+
1142+
// Provide reserve in absolute path view
1143+
pub struct AbsoluteReserveProviderMigrationPhase<T>(PhantomData<T>);
1144+
1145+
impl<T: Config> Reserve for AbsoluteReserveProviderMigrationPhase<T> {
1146+
fn reserve(asset: &Asset) -> Option<Location> {
1147+
let AssetId(location) = &asset.id;
1148+
Pallet::<T>::chain_part(location)
1149+
}
1150+
}
1151+
1152+
// Provide reserve in relative path view
1153+
// Self tokens are represeneted as Here
1154+
pub struct RelativeReserveProviderMigrationPhase<T>(PhantomData<T>);
1155+
1156+
impl<T: Config> Reserve for RelativeReserveProviderMigrationPhase<T> {
1157+
fn reserve(asset: &Asset) -> Option<Location> {
1158+
let AssetId(location) = &asset.id;
1159+
if location.parents == 0 && !is_chain_junction(location.first_interior()) {
1160+
Some(Location::here())
1161+
} else {
1162+
Pallet::<T>::chain_part(location)
1163+
}
1164+
}
1165+
}

xtokens/src/mock/para.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{
2-
AllowTopLevelPaidExecution, Amount, Balance, CurrencyId, CurrencyIdConvert, ParachainXcmRouter, RateLimiter,
3-
CHARLIE,
2+
AbsoluteReserveProviderMigrationPhase, AllowTopLevelPaidExecution, Amount, Balance, CurrencyId, CurrencyIdConvert,
3+
ParachainXcmRouter, RateLimiter, CHARLIE,
44
};
55
use crate as orml_xtokens;
66

@@ -26,10 +26,7 @@ use xcm_builder::{
2626
use xcm_executor::{Config, XcmExecutor};
2727

2828
use crate::mock::AllTokensAreCreatedEqualToWeight;
29-
use orml_traits::{
30-
location::{AbsoluteReserveProvider, Reserve},
31-
parameter_type_with_key, RateLimiterError,
32-
};
29+
use orml_traits::{location::Reserve, parameter_type_with_key, RateLimiterError};
3330
use orml_xcm_support::{IsNativeConcrete, MultiCurrencyAdapter};
3431

3532
pub type AccountId = AccountId32;
@@ -145,7 +142,7 @@ impl Config for XcmConfig {
145142
type XcmSender = XcmRouter;
146143
type AssetTransactor = LocalAssetTransactor;
147144
type OriginConverter = XcmOriginToCallOrigin;
148-
type IsReserve = MultiNativeAsset<AbsoluteReserveProvider>;
145+
type IsReserve = MultiNativeAsset<AbsoluteReserveProviderMigrationPhase<Runtime>>;
149146
type IsTeleporter = NativeAsset;
150147
type UniversalLocation = UniversalLocation;
151148
type Barrier = Barrier;
@@ -306,9 +303,10 @@ impl orml_xtokens::Config for Runtime {
306303
type BaseXcmWeight = BaseXcmWeight;
307304
type UniversalLocation = UniversalLocation;
308305
type MaxAssetsForTransfer = MaxAssetsForTransfer;
309-
type ReserveProvider = AbsoluteReserveProvider;
306+
type ReserveProvider = AbsoluteReserveProviderMigrationPhase<Runtime>;
310307
type RateLimiter = MockRateLimiter;
311308
type RateLimiterId = XtokensRateLimiterId;
309+
type MigrationPhaseUpdateOrigin = EnsureRoot<AccountId>;
312310
}
313311

314312
impl orml_xcm::Config for Runtime {

xtokens/src/mock/para_relative_view.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use super::{Amount, Balance, CurrencyId, CurrencyIdConvert, ParachainXcmRouter};
1+
use super::{
2+
AbsoluteReserveProviderMigrationPhase, Amount, Balance, CurrencyId, CurrencyIdConvert, ParachainXcmRouter,
3+
RelativeReserveProviderMigrationPhase,
4+
};
25
use crate as orml_xtokens;
36

47
use frame_support::{
@@ -22,10 +25,7 @@ use xcm_builder::{
2225
use xcm_executor::{Config, XcmExecutor};
2326

2427
use crate::mock::AllTokensAreCreatedEqualToWeight;
25-
use orml_traits::{
26-
location::{AbsoluteReserveProvider, RelativeReserveProvider, Reserve},
27-
parameter_type_with_key,
28-
};
28+
use orml_traits::{location::Reserve, parameter_type_with_key};
2929
use orml_xcm_support::{IsNativeConcrete, MultiCurrencyAdapter};
3030

3131
pub type AccountId = AccountId32;
@@ -141,7 +141,7 @@ impl Config for XcmConfig {
141141
type XcmSender = XcmRouter;
142142
type AssetTransactor = LocalAssetTransactor;
143143
type OriginConverter = XcmOriginToCallOrigin;
144-
type IsReserve = MultiNativeAsset<AbsoluteReserveProvider>;
144+
type IsReserve = MultiNativeAsset<AbsoluteReserveProviderMigrationPhase<Runtime>>;
145145
type IsTeleporter = ();
146146
type UniversalLocation = UniversalLocation;
147147
type Barrier = Barrier;
@@ -378,9 +378,10 @@ impl orml_xtokens::Config for Runtime {
378378
type BaseXcmWeight = BaseXcmWeight;
379379
type UniversalLocation = UniversalLocation;
380380
type MaxAssetsForTransfer = MaxAssetsForTransfer;
381-
type ReserveProvider = RelativeReserveProvider;
381+
type ReserveProvider = RelativeReserveProviderMigrationPhase<Runtime>;
382382
type RateLimiter = ();
383383
type RateLimiterId = ();
384+
type MigrationPhaseUpdateOrigin = EnsureRoot<AccountId>;
384385
}
385386

386387
impl orml_xcm::Config for Runtime {

xtokens/src/mock/para_teleport.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use super::{AllowTopLevelPaidExecution, Amount, Balance, CurrencyId, CurrencyIdConvert, ParachainXcmRouter};
1+
use super::{
2+
AbsoluteReserveProviderMigrationPhase, AllowTopLevelPaidExecution, Amount, Balance, CurrencyId, CurrencyIdConvert,
3+
ParachainXcmRouter,
4+
};
25
use crate as orml_xtokens;
36

47
use frame_support::{
@@ -22,7 +25,7 @@ use xcm_executor::{Config, XcmExecutor};
2225

2326
use crate::mock::teleport_currency_adapter::MultiTeleportCurrencyAdapter;
2427
use crate::mock::AllTokensAreCreatedEqualToWeight;
25-
use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key};
28+
use orml_traits::parameter_type_with_key;
2629
use orml_xcm_support::{DisabledParachainFee, IsNativeConcrete, MultiNativeAsset};
2730

2831
pub type AccountId = AccountId32;
@@ -119,7 +122,7 @@ impl Config for XcmConfig {
119122
type XcmSender = XcmRouter;
120123
type AssetTransactor = LocalAssetTransactor;
121124
type OriginConverter = XcmOriginToCallOrigin;
122-
type IsReserve = MultiNativeAsset<AbsoluteReserveProvider>;
125+
type IsReserve = MultiNativeAsset<AbsoluteReserveProviderMigrationPhase<Runtime>>;
123126
type IsTeleporter = NativeAsset;
124127
type UniversalLocation = UniversalLocation;
125128
type Barrier = Barrier;
@@ -226,9 +229,10 @@ impl orml_xtokens::Config for Runtime {
226229
type BaseXcmWeight = BaseXcmWeight;
227230
type UniversalLocation = UniversalLocation;
228231
type MaxAssetsForTransfer = MaxAssetsForTransfer;
229-
type ReserveProvider = AbsoluteReserveProvider;
232+
type ReserveProvider = AbsoluteReserveProviderMigrationPhase<Runtime>;
230233
type RateLimiter = ();
231234
type RateLimiterId = ();
235+
type MigrationPhaseUpdateOrigin = EnsureRoot<AccountId>;
232236
}
233237

234238
impl orml_xcm::Config for Runtime {

0 commit comments

Comments
 (0)