2

I'm trying to have my pallet compile a pallet call based on the feature that is set, for example if I have two function calls feature_one() and feature_two(), it works fine with feature_one but when I add the second method with the #[cfg(feature= "feature2")] macro it gives me the following error:

      error[E0599]: no function or associated item named `feature_two` found for struct `pallet::Pallet` in the current scope

    function or associated item not found in `pallet::Pallet<T>`
    help: there is an associated function with a similar name: `feature_one`

this is the pallet code:

        #![cfg_attr(not(feature = "std"), no_std)]
        #[cfg(test)]
        mod tests;
        pub use pallet::*;
        #[frame_support::pallet]
        pub mod pallet {
            use frame_system::pallet_prelude::*;
            pub use sp_runtime::traits::Extrinsic;
            #[pallet::pallet]
            #[pallet::generate_store(pub(super) trait Store)]
            pub struct Pallet<T>(_);
        
            #[pallet::config]
            pub trait Config: frame_system::Config {
                type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
            }
            #[pallet::event]
            #[pallet::generate_deposit(pub(super) fn deposit_event)]
            pub enum Event<T: Config> {
                /// An Event has been validated
                CustomEvent { event_id: T::Hash },
            }
            #[pallet::error]
            pub enum Error<T> {
                AlreadySymbitted,
            }
       #[pallet::storage]
        pub(super) type MyStorage<T: Config> = StorageMap<_, Blake2_128Concat, T::Hash, T::BlockNumber>;
    
    
            #[pallet::call]
            impl<T: Config> Pallet<T> {
                #[cfg(feature= "feature1")]
                #[pallet::weight(0)]
                pub fn feature_one(_origin: OriginFor<T>, event_id: T::Hash) -> DispatchResult {
                } 
    
               #[cfg(feature= "feature2")]
               #[pallet::weight(0)]
                pub fn feature_two(_origin: OriginFor<T>, event_id: T::Hash) -> DispatchResult {
            
            }
    
        }
3
  • FYI #[cfg(feature= "feature1")] is supported in the construct_runtime! macro these days.
    – Squirrel
    Commented Mar 27, 2023 at 12:49
  • @Squirrel how can i use it? are there any examples? does it solve my problem? any links?
    – dadzerlaze
    Commented Mar 27, 2023 at 12:57
  • This was the PR that added the functionality: github.com/paritytech/substrate/pull/11818
    – Squirrel
    Commented Apr 18, 2023 at 17:54

1 Answer 1

3

There are a few ways to solve this.

You can do like this, with one feature flag for both alternatives.

#[pallet::call]
impl<T: Config> Pallet<T> {
  #[pallet::call_index(0)]
  #[pallet::weight(0)]
  fn f() {
    Self::ff();
  }
}

impl<T: Config> Pallet<T> {
  #[cfg(not(feature = "g"))]
  fn ff() {}

  #[cfg(feature = "g")]
  fn ff() {}
}

or use two independent flags to include a stub when unused:

#[pallet::call]
impl<T: Config> Pallet<T> {
  #[pallet::call_index(0)]
  #[pallet::weight(0)]
  fn f() {
     Self::ff();
  }

  #[pallet::call_index(1)]
  #[pallet::weight(0)]
  fn g() {
     Self::gg();
  }
}

impl<T: Config> Pallet<T> {
  #[cfg(feature = "f")]
  fn ff() {}
  #[cfg(not(feature = "f"))]
  fn ff() { return not enable }

  #[cfg(feature = "g")]
  fn gg() {}
  #[cfg(not(feature = "g"))]
  fn gg() { return not enable }
}

or simply hide the struct behind a feature flag:

#[pallet::call_index(0)]
#[pallet::weight(0)]
fn f(.., params: Params) {
   Self::ff(params);
}

#[cfg(feature = "f")]
struct Params {
  f: u8
}

#[cfg(feature = "g")]
struct Params {
  g: u16
}
13
  • what if feature_two() have diffrent paramters than feature one, in this case it wouldn't work in the first solution? and does it work that way? whats wrong with my implementation?
    – dadzerlaze
    Commented Mar 27, 2023 at 13:09
  • 1_, 2_ From the code in your question, I saw they are the same. It depends on the code, maybe you can leave the optional field empty. e.g. always passing an empty vec to it. 3_ #[pallet] not support cfg yet.
    – AurevoirXavier
    Commented Mar 27, 2023 at 13:10
  • yeah true, but what if they are not the same, i forgot to add that sorry
    – dadzerlaze
    Commented Mar 27, 2023 at 13:11
  • Updated my answer.
    – AurevoirXavier
    Commented Mar 27, 2023 at 13:15
  • 1
    Imagine, schedule(0x1000000) means feature_f(xxx). After the runtime upgrade, it was changed to feature_g(xxx). It will try to decode the 0x1000000 into a different call. We don't know what would happen.
    – AurevoirXavier
    Commented Mar 27, 2023 at 14:09

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.