Skip to content

Commit 6c9b22a

Browse files
committed
chore: Apply AHM patch for Interlay
1 parent ca05423 commit 6c9b22a

File tree

5 files changed

+456
-20
lines changed

5 files changed

+456
-20
lines changed

xtokens/src/lib.rs

Lines changed: 126 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,18 @@ use xcm_executor::traits::WeightBounds;
5454

5555
pub use module::*;
5656
use orml_traits::{
57-
location::{Parse, Reserve},
57+
location::Reserve,
5858
xcm_transfer::{Transferred, XtokensWeightInfo},
5959
GetByKey, XcmTransfer,
6060
};
6161

62+
use codec::DecodeWithMemTracking;
63+
6264
mod mock;
6365
mod tests;
6466

67+
pub const ASSET_HUB_ID: u32 = 1_000;
68+
6569
enum TransferKind {
6670
/// Transfer self reserve asset.
6771
SelfReserveAsset,
@@ -72,6 +76,29 @@ enum TransferKind {
7276
}
7377
use TransferKind::*;
7478

79+
#[derive(
80+
scale_info::TypeInfo,
81+
Default,
82+
Encode,
83+
Decode,
84+
Clone,
85+
Copy,
86+
Eq,
87+
PartialEq,
88+
Debug,
89+
MaxEncodedLen,
90+
DecodeWithMemTracking,
91+
)]
92+
pub enum MigrationPhase {
93+
/// Not started
94+
#[default]
95+
NotStarted,
96+
/// Started
97+
InProgress,
98+
/// Completed
99+
Completed,
100+
}
101+
75102
#[frame_support::pallet]
76103
pub mod module {
77104
use super::*;
@@ -131,8 +158,14 @@ pub mod module {
131158
/// The way to retreave the reserve of a MultiAsset. This can be
132159
/// configured to accept absolute or relative paths for self tokens
133160
type ReserveProvider: Reserve;
161+
162+
/// The origin that can change the migration phase
163+
type MigrationPhaseUpdateOrigin: EnsureOrigin<Self::RuntimeOrigin>;
134164
}
135165

166+
#[pallet::storage]
167+
pub type MigrationStatus<T: Config> = StorageValue<_, MigrationPhase, ValueQuery>;
168+
136169
#[pallet::event]
137170
#[pallet::generate_deposit(fn deposit_event)]
138171
pub enum Event<T: Config> {
@@ -143,6 +176,8 @@ pub mod module {
143176
fee: MultiAsset,
144177
dest: MultiLocation,
145178
},
179+
/// The AH migration phase has changed
180+
MigrationPhaseChanged { migration_phase: MigrationPhase },
146181
}
147182

148183
#[pallet::error]
@@ -388,6 +423,21 @@ pub mod module {
388423

389424
Self::do_transfer_multiassets(who, assets.clone(), fee.clone(), dest, dest_weight_limit).map(|_| ())
390425
}
426+
427+
/// Must be called by `[T::MigrationPhaseUpdateOrigin]`.
428+
/// Changes the AH migration status, which will have impact on how
429+
/// reserves are computed from this pallet extrinsics.
430+
#[pallet::call_index(6)]
431+
#[pallet::weight(frame_support::weights::Weight::from_parts(10000, 0))]
432+
pub fn set_migration_phase(origin: OriginFor<T>, migration_phase: MigrationPhase) -> DispatchResult {
433+
T::MigrationPhaseUpdateOrigin::ensure_origin(origin)?;
434+
435+
MigrationStatus::<T>::set(migration_phase);
436+
437+
Self::deposit_event(Event::<T>::MigrationPhaseChanged { migration_phase });
438+
439+
Ok(())
440+
}
391441
}
392442

393443
impl<T: Config> Pallet<T> {
@@ -548,7 +598,7 @@ pub mod module {
548598
if fee_reserve != non_fee_reserve {
549599
// Current only support `ToReserve` with relay-chain asset as fee. other case
550600
// like `NonReserve` or `SelfReserve` with relay-chain fee is not support.
551-
ensure!(non_fee_reserve == dest.chain_part(), Error::<T>::InvalidAsset);
601+
ensure!(non_fee_reserve == Self::chain_part(&dest), Error::<T>::InvalidAsset);
552602

553603
let reserve_location = non_fee_reserve.ok_or(Error::<T>::AssetHasNoReserve)?;
554604
let min_xcm_fee = T::MinXcmFee::get(&reserve_location).ok_or(Error::<T>::MinXcmFeeNotDefined)?;
@@ -573,7 +623,7 @@ pub mod module {
573623

574624
let mut override_recipient = T::SelfLocation::get();
575625
if override_recipient == MultiLocation::here() {
576-
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)?;
577627
let ancestry = T::UniversalLocation::get();
578628
let _ = override_recipient
579629
.reanchor(&dest_chain_part, ancestry)
@@ -798,7 +848,7 @@ pub mod module {
798848

799849
/// Ensure has the `dest` has chain part and recipient part.
800850
fn ensure_valid_dest(dest: &MultiLocation) -> Result<(MultiLocation, MultiLocation), DispatchError> {
801-
if let (Some(dest), Some(recipient)) = (dest.chain_part(), dest.non_chain_part()) {
851+
if let (Some(dest), Some(recipient)) = (Self::chain_part(&dest), Self::non_chain_part(&dest)) {
802852
Ok((dest, recipient))
803853
} else {
804854
Err(Error::<T>::InvalidDest.into())
@@ -844,6 +894,41 @@ pub mod module {
844894
let asset = assets.get(reserve_idx);
845895
asset.and_then(T::ReserveProvider::reserve)
846896
}
897+
898+
/// Returns the "chain" location part. It could be parent, sibling
899+
/// parachain, or child parachain.
900+
pub fn chain_part(location: &MultiLocation) -> Option<MultiLocation> {
901+
match (location.parents, location.first_interior()) {
902+
// sibling parachain
903+
(1, Some(Parachain(id))) => Some(MultiLocation::new(1, Parachain(*id))),
904+
// parent
905+
(1, _) => match MigrationStatus::<T>::get() {
906+
// RelayChain
907+
MigrationPhase::NotStarted => Some(MultiLocation::parent()),
908+
// Disable transfer when migration is in progress
909+
MigrationPhase::InProgress => None,
910+
// AssetHub
911+
MigrationPhase::Completed => Some(MultiLocation::new(1, Parachain(ASSET_HUB_ID))),
912+
},
913+
// children parachain
914+
(0, Some(Parachain(id))) => Some(MultiLocation::new(0, Parachain(*id))),
915+
_ => None,
916+
}
917+
}
918+
919+
/// Returns "non-chain" location part.
920+
pub fn non_chain_part(location: &MultiLocation) -> Option<MultiLocation> {
921+
let mut junctions = location.interior().clone();
922+
while is_chain_junction(junctions.first()) {
923+
let _ = junctions.take_first();
924+
}
925+
926+
if junctions != Here {
927+
Some(MultiLocation::new(0, junctions))
928+
} else {
929+
None
930+
}
931+
}
847932
}
848933

849934
pub struct XtokensWeight<T>(PhantomData<T>);
@@ -1039,3 +1124,40 @@ fn subtract_fee(asset: &MultiAsset, amount: u128) -> MultiAsset {
10391124
id: asset.id,
10401125
}
10411126
}
1127+
1128+
fn is_chain_junction(junction: Option<&Junction>) -> bool {
1129+
matches!(junction, Some(Parachain(_)))
1130+
}
1131+
1132+
// Provide reserve in absolute path view
1133+
pub struct AbsoluteReserveProviderMigrationPhase<T>(PhantomData<T>);
1134+
1135+
impl<T: Config> Reserve for AbsoluteReserveProviderMigrationPhase<T> {
1136+
fn reserve(asset: &MultiAsset) -> Option<MultiLocation> {
1137+
let location = if let AssetId::Concrete(location) = &asset.id {
1138+
location
1139+
} else {
1140+
return None;
1141+
};
1142+
Pallet::<T>::chain_part(location)
1143+
}
1144+
}
1145+
1146+
// Provide reserve in relative path view
1147+
// Self tokens are represeneted as Here
1148+
pub struct RelativeReserveProviderMigrationPhase<T>(PhantomData<T>);
1149+
1150+
impl<T: Config> Reserve for RelativeReserveProviderMigrationPhase<T> {
1151+
fn reserve(asset: &MultiAsset) -> Option<MultiLocation> {
1152+
let location = if let AssetId::Concrete(location) = &asset.id {
1153+
location
1154+
} else {
1155+
return None;
1156+
};
1157+
if location.parents == 0 && !is_chain_junction(location.first_interior()) {
1158+
Some(MultiLocation::here())
1159+
} else {
1160+
Pallet::<T>::chain_part(location)
1161+
}
1162+
}
1163+
}

xtokens/src/mock/para.rs

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

46
use frame_support::{
@@ -26,7 +28,7 @@ use xcm_builder::{
2628
use xcm_executor::{Config, XcmExecutor};
2729

2830
use crate::mock::AllTokensAreCreatedEqualToWeight;
29-
use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key};
31+
use orml_traits::parameter_type_with_key;
3032
use orml_xcm_support::{IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset};
3133

3234
pub type AccountId = AccountId32;
@@ -150,7 +152,7 @@ impl Config for XcmConfig {
150152
type XcmSender = XcmRouter;
151153
type AssetTransactor = LocalAssetTransactor;
152154
type OriginConverter = XcmOriginToCallOrigin;
153-
type IsReserve = MultiNativeAsset<AbsoluteReserveProvider>;
155+
type IsReserve = MultiNativeAsset<AbsoluteReserveProviderMigrationPhase<Runtime>>;
154156
type IsTeleporter = NativeAsset;
155157
type UniversalLocation = UniversalLocation;
156158
type Barrier = Barrier;
@@ -289,7 +291,8 @@ impl orml_xtokens::Config for Runtime {
289291
type BaseXcmWeight = BaseXcmWeight;
290292
type UniversalLocation = UniversalLocation;
291293
type MaxAssetsForTransfer = MaxAssetsForTransfer;
292-
type ReserveProvider = AbsoluteReserveProvider;
294+
type ReserveProvider = AbsoluteReserveProviderMigrationPhase<Runtime>;
295+
type MigrationPhaseUpdateOrigin = EnsureRoot<AccountId>;
293296
}
294297

295298
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::{
@@ -26,10 +29,7 @@ use xcm_builder::{
2629
use xcm_executor::{Config, XcmExecutor};
2730

2831
use crate::mock::AllTokensAreCreatedEqualToWeight;
29-
use orml_traits::{
30-
location::{AbsoluteReserveProvider, RelativeReserveProvider},
31-
parameter_type_with_key,
32-
};
32+
use orml_traits::parameter_type_with_key;
3333
use orml_xcm_support::{IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset};
3434

3535
pub type AccountId = AccountId32;
@@ -153,7 +153,7 @@ impl Config for XcmConfig {
153153
type XcmSender = XcmRouter;
154154
type AssetTransactor = LocalAssetTransactor;
155155
type OriginConverter = XcmOriginToCallOrigin;
156-
type IsReserve = MultiNativeAsset<AbsoluteReserveProvider>;
156+
type IsReserve = MultiNativeAsset<AbsoluteReserveProviderMigrationPhase<Runtime>>;
157157
type IsTeleporter = ();
158158
type UniversalLocation = UniversalLocation;
159159
type Barrier = Barrier;
@@ -412,7 +412,8 @@ impl orml_xtokens::Config for Runtime {
412412
type BaseXcmWeight = BaseXcmWeight;
413413
type UniversalLocation = UniversalLocation;
414414
type MaxAssetsForTransfer = MaxAssetsForTransfer;
415-
type ReserveProvider = RelativeReserveProvider;
415+
type ReserveProvider = RelativeReserveProviderMigrationPhase<Runtime>;
416+
type MigrationPhaseUpdateOrigin = EnsureRoot<AccountId>;
416417
}
417418

418419
impl orml_xcm::Config for Runtime {

xtokens/src/mock/para_teleport.rs

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

46
use frame_support::{
@@ -27,7 +29,7 @@ use xcm_executor::{Config, XcmExecutor};
2729

2830
use crate::mock::teleport_currency_adapter::MultiTeleportCurrencyAdapter;
2931
use crate::mock::AllTokensAreCreatedEqualToWeight;
30-
use orml_traits::{location::AbsoluteReserveProvider, parameter_type_with_key};
32+
use orml_traits::parameter_type_with_key;
3133
use orml_xcm_support::{DisabledParachainFee, IsNativeConcrete, MultiNativeAsset};
3234

3335
pub type AccountId = AccountId32;
@@ -151,7 +153,7 @@ impl Config for XcmConfig {
151153
type XcmSender = XcmRouter;
152154
type AssetTransactor = LocalAssetTransactor;
153155
type OriginConverter = XcmOriginToCallOrigin;
154-
type IsReserve = MultiNativeAsset<AbsoluteReserveProvider>;
156+
type IsReserve = MultiNativeAsset<AbsoluteReserveProviderMigrationPhase<Runtime>>;
155157
type IsTeleporter = NativeAsset;
156158
type UniversalLocation = UniversalLocation;
157159
type Barrier = Barrier;
@@ -280,7 +282,8 @@ impl orml_xtokens::Config for Runtime {
280282
type BaseXcmWeight = BaseXcmWeight;
281283
type UniversalLocation = UniversalLocation;
282284
type MaxAssetsForTransfer = MaxAssetsForTransfer;
283-
type ReserveProvider = AbsoluteReserveProvider;
285+
type ReserveProvider = AbsoluteReserveProviderMigrationPhase<Runtime>;
286+
type MigrationPhaseUpdateOrigin = EnsureRoot<AccountId>;
284287
}
285288

286289
impl orml_xcm::Config for Runtime {

0 commit comments

Comments
 (0)