1

In a custom pallet I wrote an entry point that's supposed to be called by root. The purpose of the function is to create a collection with specific metadata at the NFTs pallet. I am using dummy data in this post, in reality the metadata is much more than this.

The idea is that no gas fee will be charged, however I am not accomplishing that with this code. Tests fail, because the pallet's account (which is used as the owner of the collection) has no funds.

Is there a way to ensure this function can be called without gas fees? If there is a better way to reach my goal then I'm also open to that. What matters is that the collections used by this pallet get created with specific metadata.

        #[pallet::call_index(0)]
        #[pallet::weight(T::WeightInfo::do_something())]
        pub fn create_collections(origin: OriginFor<T>, admin: Option<T::AccountId>) -> DispatchResultWithPostInfo {
            // Check that the extrinsic was signed by root.
            ensure_root(origin)?;           

            let account_id = Self::account_id();
            let admin = admin.unwrap_or(account_id.clone());

            //== Experience credentials ==//
            // Create collection
            T::Nfts::create_collection_with_id(
                T::ExperienceNFTCollectionId::get(), 
                &account_id, 
                &admin,
                &CollectionConfig {
                    settings: CollectionSettings::from_disabled(
                        CollectionSetting::TransferableItems | CollectionSetting::UnlockedMetadata
                    ),
                    max_supply: None,
                    mint_settings: MintSettings::default(),
                })?;

            // Set collection metadata.
            T::Nfts::set_collection_metadata(None, &T::ExperienceNFTCollectionId::get(), &[0,1])?;
            
            Ok(Pays::No.into())
        }

3 Answers 3

0

You can refer to this post how we can implement gasless/feeless transaction? and you can also try the following code it might help you.

        #[pallet::call_index(0)]
        #[pallet::weight(Pays::No)]
        pub fn create_collections(origin: OriginFor<T>, admin: Option<T::AccountId>) -> DispatchResultWithPostInfo {
            // Check that the extrinsic was signed by root.
            ensure_root(origin)?;           

            let account_id = Self::account_id();
            let admin = admin.unwrap_or(account_id.clone());

            //== Experience credentials ==//
            // Create collection
            T::Nfts::create_collection_with_id(
                T::ExperienceNFTCollectionId::get(), 
                &account_id, 
                &admin,
                &CollectionConfig {
                    settings: CollectionSettings::from_disabled(
                        CollectionSetting::TransferableItems | CollectionSetting::UnlockedMetadata
                    ),
                    max_supply: None,
                    mint_settings: MintSettings::default(),
                })?;

            // Set collection metadata.
            T::Nfts::set_collection_metadata(None, &T::ExperienceNFTCollectionId::get(), &[0,1])?;
            
            Ok(())
        }
1
  • It results in the following error: error[E0277]: the trait bound frame_support::dispatch::Pays: WeighData<()> is not satisfied --> pallets/credentials/src/lib.rs:242:12 | 242 | #[pallet::call] | ^^^^ the trait WeighData<()> is not implemented for frame_support::dispatch::Pays FYI: First it gave a similar error about the admin argument, so I removed that completely, since it better to have that in Config anyway. Dec 21, 2023 at 8:53
0

Apart from the two ways mentioned in how we can implement gasless/feeless transaction?, we can use the following

  1. Return Pays::No: An example can be seen here. Note that this still requires the account to hold enough tokens to pay the fees, as the underlying implementation causes the fee to be charged and then, refunded within the scope of its execution.
  2. Use feeless_if syntax as introduced here: This does not require the account to hold any tokens, as long as the condition specified is met.
0

If you implement the feeles_if solution, check the following discussions:

Basically, you can't submit a feeless transaction using a nonexistent account with the current implementation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.