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

[NFTs] Add minting price to the pre-signed mint object #14242

Merged
merged 2 commits into from
May 29, 2023
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
3 changes: 2 additions & 1 deletion frame/nfts/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -828,14 +828,15 @@ benchmarks_instance_pallet! {
metadata: metadata.clone(),
only_account: None,
deadline: One::one(),
mint_price: Some(DepositBalanceOf::<T, I>::min_value()),
};
let message = Encode::encode(&mint_data);
let signature = MultiSignature::Sr25519(sr25519_sign(0.into(), &caller_public, &message).unwrap());

let target: T::AccountId = account("target", 0, SEED);
T::Currency::make_free_balance_be(&target, DepositBalanceOf::<T, I>::max_value());
frame_system::Pallet::<T>::set_block_number(One::one());
}: _(SystemOrigin::Signed(target.clone()), mint_data, signature.into(), caller)
}: _(SystemOrigin::Signed(target.clone()), Box::new(mint_data), signature.into(), caller)
verify {
let metadata: BoundedVec<_, _> = metadata.try_into().unwrap();
assert_last_event::<T, I>(Event::ItemMetadataSet { collection, item, data: metadata }.into());
Expand Down
25 changes: 21 additions & 4 deletions frame/nfts/src/features/create_delete_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// limitations under the License.

use crate::*;
use frame_support::pallet_prelude::*;
use frame_support::{pallet_prelude::*, traits::ExistenceRequirement};

impl<T: Config<I>, I: 'static> Pallet<T, I> {
pub fn do_mint(
Expand Down Expand Up @@ -91,8 +91,15 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
mint_data: PreSignedMintOf<T, I>,
signer: T::AccountId,
) -> DispatchResult {
let PreSignedMint { collection, item, attributes, metadata, deadline, only_account } =
mint_data;
let PreSignedMint {
collection,
item,
attributes,
metadata,
deadline,
only_account,
mint_price,
} = mint_data;
let metadata = Self::construct_metadata(metadata)?;

ensure!(
Expand All @@ -118,7 +125,17 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
Some(mint_to.clone()),
mint_to.clone(),
item_config,
|_, _| Ok(()),
|collection_details, _| {
if let Some(price) = mint_price {
T::Currency::transfer(
&mint_to,
&collection_details.owner,
price,
ExistenceRequirement::KeepAlive,
)?;
}
Ok(())
},
)?;
let admin_account = Self::find_account_by_role(&collection, CollectionRole::Admin);
if let Some(admin_account) = admin_account {
Expand Down
4 changes: 2 additions & 2 deletions frame/nfts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1835,13 +1835,13 @@ pub mod pallet {
#[pallet::weight(T::WeightInfo::mint_pre_signed(mint_data.attributes.len() as u32))]
pub fn mint_pre_signed(
origin: OriginFor<T>,
mint_data: PreSignedMintOf<T, I>,
mint_data: Box<PreSignedMintOf<T, I>>,
signature: T::OffchainSignature,
signer: T::AccountId,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
Self::validate_signature(&Encode::encode(&mint_data), &signature, &signer)?;
Self::do_mint_pre_signed(origin, mint_data, signer)
Self::do_mint_pre_signed(origin, *mint_data, signer)
}

/// Set attributes for an item by providing the pre-signed approval.
Expand Down
27 changes: 16 additions & 11 deletions frame/nfts/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3146,13 +3146,14 @@ fn validate_signature() {
let user_1_pair = sp_core::sr25519::Pair::from_string("//Alice", None).unwrap();
let user_1_signer = MultiSigner::Sr25519(user_1_pair.public());
let user_1 = user_1_signer.clone().into_account();
let mint_data: PreSignedMint<u32, u32, AccountId, u32> = PreSignedMint {
let mint_data: PreSignedMint<u32, u32, AccountId, u32, u64> = PreSignedMint {
collection: 0,
item: 0,
attributes: vec![],
metadata: vec![],
only_account: None,
deadline: 100000,
mint_price: None,
};
let encoded_data = Encode::encode(&mint_data);
let signature = MultiSignature::Sr25519(user_1_pair.sign(&encoded_data));
Expand Down Expand Up @@ -3182,6 +3183,7 @@ fn pre_signed_mints_should_work() {
metadata: vec![0, 1],
only_account: None,
deadline: 10000000,
mint_price: Some(10),
};
let message = Encode::encode(&mint_data);
let signature = MultiSignature::Sr25519(user_1_pair.sign(&message));
Expand All @@ -3198,7 +3200,7 @@ fn pre_signed_mints_should_work() {

assert_ok!(Nfts::mint_pre_signed(
RuntimeOrigin::signed(user_2.clone()),
mint_data.clone(),
Box::new(mint_data.clone()),
signature.clone(),
user_1.clone(),
));
Expand Down Expand Up @@ -3228,21 +3230,21 @@ fn pre_signed_mints_should_work() {
assert_eq!(deposit.account, Some(user_2.clone()));
assert_eq!(deposit.amount, 3);

assert_eq!(Balances::free_balance(&user_0), 100 - 2); // 2 - collection deposit
assert_eq!(Balances::free_balance(&user_2), 100 - 1 - 3 - 6); // 1 - item deposit, 3 - metadata, 6 - attributes
assert_eq!(Balances::free_balance(&user_0), 100 - 2 + 10); // 2 - collection deposit, 10 - mint price
assert_eq!(Balances::free_balance(&user_2), 100 - 1 - 3 - 6 - 10); // 1 - item deposit, 3 - metadata, 6 - attributes, 10 - mint price

assert_noop!(
Nfts::mint_pre_signed(
RuntimeOrigin::signed(user_2.clone()),
mint_data,
Box::new(mint_data),
signature.clone(),
user_1.clone(),
),
Error::<Test>::AlreadyExists
);

assert_ok!(Nfts::burn(RuntimeOrigin::signed(user_2.clone()), 0, 0));
assert_eq!(Balances::free_balance(&user_2), 100 - 6);
assert_eq!(Balances::free_balance(&user_2), 100 - 6 - 10);

// validate the `only_account` field
let mint_data = PreSignedMint {
Expand All @@ -3252,13 +3254,14 @@ fn pre_signed_mints_should_work() {
metadata: vec![],
only_account: Some(account(2)),
deadline: 10000000,
mint_price: None,
};

// can't mint with the wrong signature
assert_noop!(
Nfts::mint_pre_signed(
RuntimeOrigin::signed(user_2.clone()),
mint_data.clone(),
Box::new(mint_data.clone()),
signature.clone(),
user_1.clone(),
),
Expand All @@ -3271,7 +3274,7 @@ fn pre_signed_mints_should_work() {
assert_noop!(
Nfts::mint_pre_signed(
RuntimeOrigin::signed(user_3),
mint_data.clone(),
Box::new(mint_data.clone()),
signature.clone(),
user_1.clone(),
),
Expand All @@ -3283,7 +3286,7 @@ fn pre_signed_mints_should_work() {
assert_noop!(
Nfts::mint_pre_signed(
RuntimeOrigin::signed(user_2.clone()),
mint_data,
Box::new(mint_data),
signature,
user_1.clone(),
),
Expand All @@ -3299,14 +3302,15 @@ fn pre_signed_mints_should_work() {
metadata: vec![],
only_account: Some(account(2)),
deadline: 10000000,
mint_price: None,
};
let message = Encode::encode(&mint_data);
let signature = MultiSignature::Sr25519(user_1_pair.sign(&message));

assert_noop!(
Nfts::mint_pre_signed(
RuntimeOrigin::signed(user_2.clone()),
mint_data,
Box::new(mint_data),
signature,
user_1.clone(),
),
Expand All @@ -3321,13 +3325,14 @@ fn pre_signed_mints_should_work() {
metadata: vec![0, 1],
only_account: None,
deadline: 10000000,
mint_price: None,
};
let message = Encode::encode(&mint_data);
let signature = MultiSignature::Sr25519(user_1_pair.sign(&message));
assert_noop!(
Nfts::mint_pre_signed(
RuntimeOrigin::signed(user_2),
mint_data,
Box::new(mint_data),
signature,
user_1.clone(),
),
Expand Down
5 changes: 4 additions & 1 deletion frame/nfts/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub(super) type PreSignedMintOf<T, I = ()> = PreSignedMint<
<T as Config<I>>::ItemId,
<T as SystemConfig>::AccountId,
<T as SystemConfig>::BlockNumber,
BalanceOf<T, I>,
>;
pub(super) type PreSignedAttributesOf<T, I = ()> = PreSignedAttributes<
<T as Config<I>>::CollectionId,
Expand Down Expand Up @@ -506,7 +507,7 @@ impl CollectionRoles {
impl_codec_bitflags!(CollectionRoles, u8, CollectionRole);

#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct PreSignedMint<CollectionId, ItemId, AccountId, Deadline> {
pub struct PreSignedMint<CollectionId, ItemId, AccountId, Deadline, Balance> {
/// A collection of the item to be minted.
pub(super) collection: CollectionId,
/// Item's ID.
Expand All @@ -519,6 +520,8 @@ pub struct PreSignedMint<CollectionId, ItemId, AccountId, Deadline> {
pub(super) only_account: Option<AccountId>,
/// A deadline for the signature.
pub(super) deadline: Deadline,
/// An optional price the claimer would need to pay for the mint.
pub(super) mint_price: Option<Balance>,
}

#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
Expand Down