Skip to content

Commit

Permalink
feat: use asset-ops in pallet-nft+fractionalization, new xcm types
Browse files Browse the repository at this point in the history
  • Loading branch information
mrshiposha committed Jun 28, 2024
1 parent 5324c5b commit d949eb4
Show file tree
Hide file tree
Showing 14 changed files with 939 additions and 33 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ primitive-types = { features = ["codec", "num-traits", "scale-info"], workspace
rococo-runtime-constants = { workspace = true }
pallet-xcm = { workspace = true }
pallet-xcm-benchmarks = { optional = true, workspace = true }
pallet-xnft = { workspace = true }
polkadot-parachain-primitives = { workspace = true }
polkadot-runtime-common = { workspace = true }
xcm = { workspace = true }
Expand Down Expand Up @@ -132,6 +133,7 @@ runtime-benchmarks = [
"pallet-xcm-benchmarks/runtime-benchmarks",
"pallet-xcm-bridge-hub-router/runtime-benchmarks",
"pallet-xcm/runtime-benchmarks",
"pallet-xnft/runtime-benchmarks",
"parachains-common/runtime-benchmarks",
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
Expand Down Expand Up @@ -171,6 +173,7 @@ try-runtime = [
"pallet-utility/try-runtime",
"pallet-xcm-bridge-hub-router/try-runtime",
"pallet-xcm/try-runtime",
"pallet-xnft/try-runtime",
"parachain-info/try-runtime",
"polkadot-runtime-common/try-runtime",
"sp-runtime/try-runtime",
Expand Down Expand Up @@ -224,6 +227,7 @@ std = [
"pallet-xcm-benchmarks?/std",
"pallet-xcm-bridge-hub-router/std",
"pallet-xcm/std",
"pallet-xnft/std",
"parachain-info/std",
"parachains-common/std",
"polkadot-parachain-primitives/std",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,7 @@ construct_runtime!(
PolkadotXcm: pallet_xcm = 31,
CumulusXcm: cumulus_pallet_xcm = 32,
MessageQueue: pallet_message_queue = 34,
Xnft: pallet_xnft = 35,

// Handy utilities.
Utility: pallet_utility = 40,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@

use super::{
AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, BaseDeliveryFee,
CollatorSelection, FeeAssetId, ForeignAssets, ForeignAssetsInstance, ParachainInfo,
CollatorSelection, FeeAssetId, ForeignAssets, ForeignAssetsInstance, Nfts, ParachainInfo,
ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
ToWestendXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, Uniques, WeightToFee,
XcmpQueue,
XcmpQueue, Xnft,
};
use assets_common::{
matching::{FromNetwork, FromSiblingParachain, IsForeignConcreteAsset},
Expand All @@ -33,12 +33,15 @@ use frame_support::{
};
use frame_system::EnsureRoot;
use pallet_xcm::XcmPassthrough;
use pallet_xnft::{
ConcatIncrementableIdOnCreate, DerivativeIdParamsRegistry, DerivativeInstancesRegistry,
};
use parachains_common::{
xcm_config::{
AllSiblingSystemParachains, AssetFeeAsExistentialDepositMultiplier,
ConcreteAssetFromSystem, ParentRelayOrSiblingParachains, RelayOrOtherSystemParachains,
},
TREASURY_PALLET_ID,
CollectionId, ItemId, TREASURY_PALLET_ID,
};
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::xcm_sender::ExponentialPrice;
Expand All @@ -49,18 +52,22 @@ use testnet_parachains_constants::rococo::snowbridge::{
};
use xcm::latest::prelude::*;
use xcm_builder::{
unique_instances::UniqueInstancesAdapter, AccountId32Aliases, AllowExplicitUnpaidExecutionFrom,
AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, DenyThenTry,
DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor,
FungibleAdapter, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription,
IsConcrete, LocalMint, MatchInClassInstances, NetworkExportTableItem, NoChecking,
ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignPaidRemoteExporter, SovereignSignedViaLocation, StartsWith,
StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
XcmFeeToAccount,
unique_instances::{
DerivativeRegisterParams, EnsureNotDerivativeInstance, MatchDerivativeInstances,
MatchDerivativeRegisterParams, RegisterOnCreate, RestoreOnCreate, SimpleStash,
StashOnDestroy, UniqueInstancesAdapter, UniqueInstancesDepositAdapter, UniqueInstancesOps,
},
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily,
EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter,
GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, LocalMint,
MatchInClassInstances, NetworkExportTableItem, NoChecking, ParentAsSuperuser, ParentIsPreset,
RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignPaidRemoteExporter,
SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
XcmFeeManagerFromComponents, XcmFeeToAccount,
};
use xcm_executor::XcmExecutor;

Expand All @@ -83,6 +90,8 @@ parameter_types! {
PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
pub UniquesPalletLocation: Location =
PalletInstance(<Uniques as PalletInfoAccess>::index() as u8).into();
pub NftsPalletLocation: Location =
PalletInstance(<Nfts as PalletInfoAccess>::index() as u8).into();
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
pub const GovernanceLocation: Location = Location::parent();
pub StakingPot: AccountId = CollatorSelection::account_id();
Expand Down Expand Up @@ -157,6 +166,40 @@ pub type UniquesTransactor = UniqueInstancesAdapter<
Uniques,
>;

/// Matcher for converting `ClassId`/`InstanceId` into a nfts asset.
pub type NftsConvertedConcreteId = assets_common::NftsConvertedConcreteId<NftsPalletLocation>;

type NftsStash = SimpleStash<TreasuryAccount, Nfts>;

type ParamsRegitry = DerivativeIdParamsRegistry<Xnft>;
type DerivativeNftsRegitry = DerivativeInstancesRegistry<Xnft>;

/// Matches NFTs minted on this chain
/// and which do not correspond to any foreign NFT.
///
/// See the [`EnsureNotDerivativeInstance`] documentation
/// for why we need to match such NFTs carefully.
type MatchAssetHubOriginalInstances = EnsureNotDerivativeInstance<
DerivativeNftsRegitry,
MatchInClassInstances<NftsConvertedConcreteId>,
>;

// Means for transacting nft assets.
type NftsTransactor = UniqueInstancesAdapter<
AccountId,
LocationToAccountId,
(MatchAssetHubOriginalInstances, MatchDerivativeInstances<DerivativeNftsRegitry>),
UniqueInstancesOps<RestoreOnCreate<NftsStash>, Nfts, StashOnDestroy<NftsStash>>,
>;

type NftDerivativesRegistrar = UniqueInstancesDepositAdapter<
AccountId,
LocationToAccountId,
DerivativeRegisterParams<CollectionId>,
MatchDerivativeRegisterParams<ParamsRegitry>,
RegisterOnCreate<DerivativeNftsRegitry, ConcatIncrementableIdOnCreate<Xnft, Nfts>>,
>;

/// `AssetId`/`Balance` converter for `ForeignAssets`.
pub type ForeignAssetsConvertedConcreteId = assets_common::ForeignAssetsConvertedConcreteId<
(
Expand Down Expand Up @@ -217,6 +260,8 @@ pub type AssetTransactors = (
ForeignFungiblesTransactor,
PoolFungiblesTransactor,
UniquesTransactor,
NftsTransactor,
NftDerivativesRegistrar,
);

/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
Expand Down Expand Up @@ -484,6 +529,13 @@ impl cumulus_pallet_xcm::Config for Runtime {
type XcmExecutor = XcmExecutor<XcmConfig>;
}

impl pallet_xnft::Config for Runtime {
type RuntimeEvent = RuntimeEvent;

type DerivativeIdParams = CollectionId;
type DerivativeId = (CollectionId, ItemId);
}

pub type ForeignCreatorsSovereignAccountOf = (
SiblingParachainConvertsVia<Sibling, AccountId>,
AccountId32Aliases<RelayNetwork, AccountId>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

use super::{
AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, BaseDeliveryFee,
CollatorSelection, FeeAssetId, ForeignAssets, ForeignAssetsInstance, ParachainInfo,
CollatorSelection, FeeAssetId, ForeignAssets, ForeignAssetsInstance, Nfts, ParachainInfo,
ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
ToRococoXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, Uniques, WeightToFee,
XcmpQueue,
Expand Down Expand Up @@ -45,13 +45,16 @@ use polkadot_runtime_common::xcm_sender::ExponentialPrice;
use sp_runtime::traits::{AccountIdConversion, ConvertInto};
use xcm::latest::prelude::*;
use xcm_builder::{
unique_instances::UniqueInstancesAdapter, AccountId32Aliases, AllowExplicitUnpaidExecutionFrom,
AllowHrmpNotificationsFromRelayChain, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, DenyThenTry, DescribeFamily,
DescribePalletTerminal, EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter,
FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete,
LocalMint, MatchInClassInstances, NetworkExportTableItem, NoChecking, ParentAsSuperuser,
ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
unique_instances::{
RestoreOnCreate, SimpleStash, StashOnDestroy, UniqueInstancesAdapter, UniqueInstancesOps,
},
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
DenyReserveTransferToRelayChain, DenyThenTry, DescribeFamily, DescribePalletTerminal,
EnsureXcmOrigin, FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter,
GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, LocalMint,
MatchInClassInstances, NetworkExportTableItem, NoChecking, ParentAsSuperuser, ParentIsPreset,
RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, StartsWith,
StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
Expand All @@ -78,9 +81,12 @@ parameter_types! {
PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
pub UniquesPalletLocation: Location =
PalletInstance(<Uniques as PalletInfoAccess>::index() as u8).into();
pub NftsPalletLocation: Location =
PalletInstance(<Nfts as PalletInfoAccess>::index() as u8).into();
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
pub StakingPot: AccountId = CollatorSelection::account_id();
pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
pub TreasuryLocation: Location = AccountId32 { network: RelayNetwork::get(), id: TreasuryAccount::get().into() }.into();
pub RelayTreasuryLocation: Location = (Parent, PalletInstance(westend_runtime_constants::TREASURY_PALLET_ID)).into();
}

Expand Down Expand Up @@ -149,6 +155,19 @@ pub type UniquesTransactor = UniqueInstancesAdapter<
Uniques,
>;

/// Matcher for converting `ClassId`/`InstanceId` into a nfts asset.
pub type NftsConvertedConcreteId = assets_common::NftsConvertedConcreteId<NftsPalletLocation>;

type NftsStash = SimpleStash<TreasuryAccount, Nfts>;

// Means for transacting nft assets.
type NftsTransactor = UniqueInstancesAdapter<
AccountId,
LocationToAccountId,
MatchInClassInstances<NftsConvertedConcreteId>,
UniqueInstancesOps<RestoreOnCreate<NftsStash>, Nfts, StashOnDestroy<NftsStash>>,
>;

/// `AssetId`/`Balance` converter for `ForeignAssets`.
pub type ForeignAssetsConvertedConcreteId = assets_common::ForeignAssetsConvertedConcreteId<
(
Expand Down Expand Up @@ -209,6 +228,7 @@ pub type AssetTransactors = (
ForeignFungiblesTransactor,
PoolFungiblesTransactor,
UniquesTransactor,
NftsTransactor,
);

/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
Expand Down
11 changes: 11 additions & 0 deletions cumulus/parachains/runtimes/assets/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ pub type UniquesConvertedConcreteId<UniquesPalletLocation> = MatchedConvertedCon
TryConvertInto,
>;

/// [`MatchedConvertedConcreteId`] converter dedicated for `Nfts`
pub type NftsConvertedConcreteId<NftsPalletLocation> = MatchedConvertedConcreteId<
CollectionId,
ItemId,
// The asset starts with the nfts pallet. The `CollectionId` of the asset is specified as a
// junction within the pallet itself.
StartsWith<NftsPalletLocation>,
CollectionIdForUniquesConvert<NftsPalletLocation>,
TryConvertInto,
>;

/// [`MatchedConvertedConcreteId`] converter dedicated for `TrustBackedAssets`,
/// it is a similar implementation to `TrustBackedAssetsConvertedConcreteId`,
/// but it converts `AssetId` to `xcm::v*::Location` type instead of `AssetIdForTrustBackedAssets =
Expand Down
23 changes: 13 additions & 10 deletions substrate/frame/nft-fractionalization/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ pub mod pallet {
Create, Destroy, Inspect, Mutate,
},
tokens::{
nonfungibles_v2::{Inspect as NonFungiblesInspect, Transfer},
asset_ops::{
common_asset_kinds::Instance,
common_strategies::{CanTransfer, JustDo, Ownership},
AssetDefinition, InspectMetadata, Transfer, UpdateMetadata,
},
AssetId, Balance as AssetBalance,
Fortitude::Polite,
Precision::{BestEffort, Exact},
Expand Down Expand Up @@ -127,11 +131,10 @@ pub mod pallet {
+ MetadataDeposit<DepositOf<Self>>;

/// Registry for minted NFTs.
type Nfts: NonFungiblesInspect<
Self::AccountId,
ItemId = Self::NftId,
CollectionId = Self::NftCollectionId,
> + Transfer<Self::AccountId>;
type Nfts: AssetDefinition<Instance, Id = (Self::NftCollectionId, Self::NftId)>
+ InspectMetadata<Instance, Ownership<Self::AccountId>>
+ UpdateMetadata<Instance, CanTransfer>
+ Transfer<Instance, JustDo<Self::AccountId>>;

/// The pallet's id, used for deriving its sovereign account ID.
#[pallet::constant]
Expand Down Expand Up @@ -241,7 +244,7 @@ pub mod pallet {
let beneficiary = T::Lookup::lookup(beneficiary)?;

let nft_owner =
T::Nfts::owner(&nft_collection_id, &nft_id).ok_or(Error::<T>::NftNotFound)?;
T::Nfts::inspect_metadata(&(nft_collection_id, nft_id), Ownership::default())?;
ensure!(nft_owner == who, Error::<T>::NoPermission);

let pallet_account = Self::get_pallet_account();
Expand Down Expand Up @@ -340,7 +343,7 @@ pub mod pallet {

/// Prevent further transferring of NFT.
fn do_lock_nft(nft_collection_id: T::NftCollectionId, nft_id: T::NftId) -> DispatchResult {
T::Nfts::disable_transfer(&nft_collection_id, &nft_id)
T::Nfts::update_metadata(&(nft_collection_id, nft_id), CanTransfer::default(), false)
}

/// Remove the transfer lock and transfer the NFT to the account returning the tokens.
Expand All @@ -349,8 +352,8 @@ pub mod pallet {
nft_id: T::NftId,
account: &T::AccountId,
) -> DispatchResult {
T::Nfts::enable_transfer(&nft_collection_id, &nft_id)?;
T::Nfts::transfer(&nft_collection_id, &nft_id, account)
T::Nfts::update_metadata(&(nft_collection_id, nft_id), CanTransfer::default(), true)?;
T::Nfts::transfer(&(nft_collection_id, nft_id), JustDo(account.clone()))
}

/// Create the new asset.
Expand Down
27 changes: 27 additions & 0 deletions substrate/frame/nfts/src/features/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,33 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
Ok(())
}

pub(crate) fn do_update_attribute(
maybe_check_origin: Option<T::AccountId>,
collection: T::CollectionId,
maybe_item: Option<T::ItemId>,
namespace: AttributeNamespace<T::AccountId>,
key: BoundedVec<u8, T::KeyLimit>,
update: Option<BoundedVec<u8, T::ValueLimit>>,
) -> DispatchResult {
match (maybe_check_origin, update) {
(Some(origin), Some(value)) => {
let depositor = match namespace {
AttributeNamespace::CollectionOwner => Self::collection_owner(collection)
.ok_or(Error::<T, I>::UnknownCollection)?,
_ => origin.clone(),
};

Self::do_set_attribute(
origin, collection, maybe_item, namespace, key, value, depositor,
)
},
(None, Some(value)) =>
Self::do_force_set_attribute(None, collection, maybe_item, namespace, key, value),
(maybe_check_origin, None) =>
Self::do_clear_attribute(maybe_check_origin, collection, maybe_item, namespace, key),
}
}

/// Sets multiple attributes for an item or a collection.
///
/// This function checks the pre-signed data is valid and updates the attributes of an item or
Expand Down
Loading

0 comments on commit d949eb4

Please sign in to comment.