Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

XCM remote lock consumers #6947

Merged
merged 10 commits into from
May 5, 2023
2 changes: 2 additions & 0 deletions runtime/kusama/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = SovereignAccountOf;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockUsers = ConstU32<0>;
type RemoteLockIdentifier = ();
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down
2 changes: 2 additions & 0 deletions runtime/polkadot/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = SovereignAccountOf;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockUsers = ConstU32<0>;
type RemoteLockIdentifier = ();
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down
2 changes: 2 additions & 0 deletions runtime/rococo/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = LocationConverter;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockUsers = ConstU32<0>;
type RemoteLockIdentifier = ();
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down
2 changes: 2 additions & 0 deletions runtime/test-runtime/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ impl pallet_xcm::Config for crate::Runtime {
type TrustedLockers = ();
type SovereignAccountOf = ();
type MaxLockers = frame_support::traits::ConstU32<8>;
type MaxRemoteLockUsers = frame_support::traits::ConstU32<0>;
type RemoteLockIdentifier = ();
type WeightInfo = pallet_xcm::TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down
2 changes: 2 additions & 0 deletions runtime/westend/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = LocationConverter;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockUsers = ConstU32<0>;
type RemoteLockIdentifier = ();
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down
36 changes: 28 additions & 8 deletions xcm/pallet-xcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,12 @@ pub mod pallet {
/// The maximum number of local XCM locks that a single account may have.
type MaxLockers: Get<u32>;

/// The maximum number of users a single remote lock may have.
type MaxRemoteLockUsers: Get<u32>;

/// The ID type for remote lock users.
type RemoteLockIdentifier: Parameter + Member + MaxEncodedLen + Ord + Copy;
muharem marked this conversation as resolved.
Show resolved Hide resolved

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;

Expand Down Expand Up @@ -582,11 +588,20 @@ pub mod pallet {
StorageValue<_, VersionMigrationStage, OptionQuery>;

#[derive(Clone, Encode, Decode, Eq, PartialEq, Ord, PartialOrd, TypeInfo, MaxEncodedLen)]
pub struct RemoteLockedFungibleRecord {
#[scale_info(skip_type_params(MaxUsers))]
pub struct RemoteLockedFungibleRecord<RemoteLockIdentifier, MaxUsers: Get<u32>> {
pub amount: u128,
pub owner: VersionedMultiLocation,
pub locker: VersionedMultiLocation,
pub users: u32,
pub users: BoundedVec<(RemoteLockIdentifier, u128), MaxUsers>,
muharem marked this conversation as resolved.
Show resolved Hide resolved
}

impl<LockId, MaxUsers: Get<u32>> RemoteLockedFungibleRecord<LockId, MaxUsers> {
/// Amount of the remote lock in use by users.
/// Returns zero if the remote lock has no users.
pub fn amount_held(&self) -> u128 {
muharem marked this conversation as resolved.
Show resolved Hide resolved
self.users.iter().max_by(|x, y| x.1.cmp(&y.1)).map_or(0, |max| max.1)
}
}

/// Fungible assets which we know are locked on a remote chain.
Expand All @@ -598,7 +613,7 @@ pub mod pallet {
NMapKey<Blake2_128Concat, T::AccountId>,
NMapKey<Blake2_128Concat, VersionedAssetId>,
),
RemoteLockedFungibleRecord,
RemoteLockedFungibleRecord<T::RemoteLockIdentifier, T::MaxRemoteLockUsers>,
OptionQuery,
>;

Expand Down Expand Up @@ -1667,11 +1682,12 @@ impl<T: Config> xcm_executor::traits::Enact for ReduceTicket<T> {
use xcm_executor::traits::LockError::UnexpectedState;
let mut record = RemoteLockedFungibles::<T>::get(&self.key).ok_or(UnexpectedState)?;
ensure!(self.locker == record.locker && self.owner == record.owner, UnexpectedState);
ensure!(record.users == 0, UnexpectedState);
record.amount = record.amount.checked_sub(self.amount).ok_or(UnexpectedState)?;
if record.amount == 0 {
let new_amount = record.amount.checked_sub(self.amount).ok_or(UnexpectedState)?;
ensure!(record.users.len() == 0 || new_amount >= record.amount_held(), UnexpectedState);
if new_amount == 0 {
RemoteLockedFungibles::<T>::remove(&self.key);
} else {
record.amount = new_amount;
RemoteLockedFungibles::<T>::insert(&self.key, &record);
}
Ok(())
Expand Down Expand Up @@ -1731,7 +1747,8 @@ impl<T: Config> xcm_executor::traits::AssetLock for Pallet<T> {
let owner = owner.into();
let id: VersionedAssetId = asset.id.into();
let key = (XCM_VERSION, account, id);
let mut record = RemoteLockedFungibleRecord { amount, owner, locker, users: 0 };
let mut record =
RemoteLockedFungibleRecord { amount, owner, locker, users: BoundedVec::default() };
if let Some(old) = RemoteLockedFungibles::<T>::get(&key) {
// Make sure that the new record wouldn't clobber any old data.
ensure!(old.locker == record.locker && old.owner == record.owner, WouldClobber);
Expand Down Expand Up @@ -1762,8 +1779,11 @@ impl<T: Config> xcm_executor::traits::AssetLock for Pallet<T> {
let record = RemoteLockedFungibles::<T>::get(&key).ok_or(NotLocked)?;
// Make sure that the record contains what we expect and there's enough to unlock.
ensure!(locker == record.locker && owner == record.owner, WouldClobber);
ensure!(record.users == 0, InUse);
ensure!(record.amount >= amount, NotEnoughLocked);
ensure!(
record.users.len() == 0 || record.amount.saturating_sub(amount) >= record.amount_held(),
InUse
);
Ok(ReduceTicket { key, amount, locker, owner })
}
}
Expand Down
2 changes: 2 additions & 0 deletions xcm/pallet-xcm/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,8 @@ impl pallet_xcm::Config for Test {
type Currency = Balances;
type CurrencyMatcher = IsConcrete<RelayLocation>;
type MaxLockers = frame_support::traits::ConstU32<8>;
type MaxRemoteLockUsers = frame_support::traits::ConstU32<0>;
type RemoteLockIdentifier = ();
type WeightInfo = TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down
2 changes: 2 additions & 0 deletions xcm/xcm-builder/tests/mock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ impl pallet_xcm::Config for Runtime {
type Currency = Balances;
type CurrencyMatcher = IsConcrete<KsmLocation>;
type MaxLockers = frame_support::traits::ConstU32<8>;
type MaxRemoteLockUsers = frame_support::traits::ConstU32<0>;
type RemoteLockIdentifier = ();
type WeightInfo = pallet_xcm::TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down
2 changes: 2 additions & 0 deletions xcm/xcm-simulator/example/src/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockUsers = ConstU32<0>;
type RemoteLockIdentifier = ();
type WeightInfo = pallet_xcm::TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down
2 changes: 2 additions & 0 deletions xcm/xcm-simulator/example/src/relay_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockUsers = ConstU32<0>;
type RemoteLockIdentifier = ();
type WeightInfo = pallet_xcm::TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down
2 changes: 2 additions & 0 deletions xcm/xcm-simulator/fuzzer/src/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = frame_support::traits::ConstU32<8>;
type MaxRemoteLockUsers = frame_support::traits::ConstU32<0>;
type RemoteLockIdentifier = ();
type WeightInfo = pallet_xcm::TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down
2 changes: 2 additions & 0 deletions xcm/xcm-simulator/fuzzer/src/relay_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = SovereignAccountOf;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockUsers = ConstU32<0>;
type RemoteLockIdentifier = ();
type WeightInfo = pallet_xcm::TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down