rmrk-substrate
rmrk-substrate copied to clipboard
Allow to configure who can mint nft
Summary
In many of the network there will be the need to control who exactly can mint the nft. Currently, anyone can do so. It might be more convinent to allow the runtime to configure this.
Proposed changes
Current
Inside calls like mint_nft_directly_to_nft
, create_collection
and so we have
ensure_signed(origin)?;
Proposed
Change to custom origin verifier
T::ProducerOrigin::ensure_origin(origin)?;
where T::ProducerOrigin
will be
Config: frame_system::Config {
// -- snip
type ProducerOrigin: EnsureOrigin<Self::Origin, Success = Self::AccountId>;
}
If so, I am willing to work on this.
I think it makes sense. @HashWarlock wdyt?
If so. I am willinng to raise a PR. I mean work has already been done.
Currently, anyone can do so. It might be more convinent to allow the runtime to configure this.
I am not entirely sure what you mean by this. Currently, only the collection_issuer
is able to mint nfts.
// Collection must exist and sender must be issuer of collection
if let Some(collection_issuer) =
pallet_uniques::Pallet::<T>::collection_owner(collection_id)
{
ensure!(collection_issuer == sender, Error::<T>::NoPermission);
// -- snip
What would we exactly gain by using a custom origin? Sorry if I didn't understand you correctly.
Correct. My point is to control who can be the collection_issuer
.
For this we take a type type Creators: EnsureOrigin<Self::Origin, Success = Self::AccountId>
.
And current behaviour would be achieved by:
impl pallet_rmrk_core::Config for Runtime {
type Creators = EnsureSigned
}
Then all signed origin can create collection ( & in turn nft inside it )
And if we want it to be controlled we do something like:
impl pallet_rmrk_core::Config for Runtime {
type Creators = OneOfOrigin<[Account1, Account2, Account3]>
}
Then only Account1
, Account2
and Account3
can create collection ( & in turn nft under it )
Ok, it makes sense to me now, thanks for the explanation.
With the Uniques pallet, we can set the team with function set_team
. This function allows us to set
-
issuer
: Issuer of NFTs for a given Collection -
admin
: Admin can thaw, force transfer and burn NFTs of a given Collection -
freezer
: Freezer to freeze NFTs for a given Collection
We could leverage this existing functionality to set the issuer
account for a Collection then ensure the mint functions check if sender
is the Collection's issuer
Example:
set_team
in pallet_uniques
& must be called by the Collection's owner
:
#[pallet::weight(T::WeightInfo::set_team())]
pub fn set_team(
origin: OriginFor<T>,
collection: T::CollectionId,
issuer: AccountIdLookupOf<T>,
admin: AccountIdLookupOf<T>,
freezer: AccountIdLookupOf<T>,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
let issuer = T::Lookup::lookup(issuer)?;
let admin = T::Lookup::lookup(admin)?;
let freezer = T::Lookup::lookup(freezer)?;
Collection::<T, I>::try_mutate(collection, |maybe_details| {
let details = maybe_details.as_mut().ok_or(Error::<T, I>::UnknownCollection)?;
ensure!(origin == details.owner, Error::<T, I>::NoPermission);
details.issuer = issuer.clone();
details.admin = admin.clone();
details.freezer = freezer.clone();
Self::deposit_event(Event::TeamChanged { collection, issuer, admin, freezer });
Ok(())
})
}
By default, these accounts are assigned to the Collection owner
when a Collection is created. Having upstream uniques manage this account permissions logic can allow us to have the function change_collection_issuer
in pallet_rmrk_core
to remove the call to pallet_uniques::transfer_ownership
and instead call pallet_uniques::set_team
to change the issuer
account. We can update permission checks to check our internal function for Collections called issuer
to return the CollectionInfo
field issuer
from the Collections
storage.
This can remove the need for adding a trait & won't require storage migrations downstream.