Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions runtime/kusama/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = SovereignAccountOf;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
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 @@ -417,6 +417,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = SovereignAccountOf;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
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 @@ -384,6 +384,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = LocationConverter;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
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 MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
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 @@ -300,6 +300,8 @@ impl pallet_xcm::Config for Runtime {
type TrustedLockers = ();
type SovereignAccountOf = LocationConverter;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down
46 changes: 36 additions & 10 deletions xcm/pallet-xcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,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 consumers a single remote lock may have.
type MaxRemoteLockConsumers: Get<u32>;

/// The ID type for local consumers of remote locks.
type RemoteLockConsumerIdentifier: Parameter + Member + MaxEncodedLen + Ord + Copy;

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

Expand Down Expand Up @@ -445,7 +451,7 @@ pub mod pallet {
FeesNotMet,
/// A remote lock with the corresponding data could not be found.
LockNotFound,
/// The unlock operation cannot succeed because there are still users of the lock.
/// The unlock operation cannot succeed because there are still consumers of the lock.
InUse,
}

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

#[derive(Clone, Encode, Decode, Eq, PartialEq, Ord, PartialOrd, TypeInfo, MaxEncodedLen)]
pub struct RemoteLockedFungibleRecord {
#[scale_info(skip_type_params(MaxConsumers))]
pub struct RemoteLockedFungibleRecord<ConsumerIdentifier, MaxConsumers: Get<u32>> {
/// Total amount of the asset held by the remote lock.
pub amount: u128,
/// The owner of the locked asset.
pub owner: VersionedMultiLocation,
/// The location which holds the original lock.
pub locker: VersionedMultiLocation,
pub users: u32,
/// Local consumers of the remote lock with a consumer identifier and the amount
/// of fungible asset every consumer holds.
/// Every consumer can hold up to total amount of the remote lock.
pub consumers: BoundedVec<(ConsumerIdentifier, u128), MaxConsumers>,
}

impl<LockId, MaxConsumers: Get<u32>> RemoteLockedFungibleRecord<LockId, MaxConsumers> {
/// Amount of the remote lock in use by consumers.
/// Returns `None` if the remote lock has no consumers.
pub fn amount_held(&self) -> Option<u128> {
self.consumers.iter().max_by(|x, y| x.1.cmp(&y.1)).map(|max| max.1)
}
}

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

Expand Down Expand Up @@ -1693,11 +1714,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.amount_held().map_or(true, |h| new_amount >= h), 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 @@ -1757,11 +1779,12 @@ 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, consumers: 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);
record.users = old.users;
record.consumers = old.consumers;
record.amount = record.amount.max(old.amount);
}
RemoteLockedFungibles::<T>::insert(&key, record);
Expand All @@ -1788,8 +1811,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.amount_held().map_or(true, |h| record.amount.saturating_sub(amount) >= h),
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 MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
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 MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
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 MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
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 MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
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 MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
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 MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
type WeightInfo = pallet_xcm::TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
Expand Down