5

Hello the following code snippet is giving me headaches:

mod items;
pub use super::*;
pub use crate::roles::items::*;
pub type BalanceOf<T> = <<T as pallet::Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
pub type Contributors<T> = Vec<AccountIdOf<T>>;
pub type HouseIndex = u32;
pub type Bool = bool;



#[derive(Debug, PartialEq, Encode, Decode)]
pub struct Investor<T,U>{
    pub account_id:T,
    pub nft:U,
}
impl<T,U> Investor<T,U>{
    pub fn new(acc: T,nft:U)-> Self{
        Investor{
            account_id: acc,
            nft: nft,
        }        
    }

}

impl<T:pallet::Config+frame_system::Config,U> Investor<T,U>{
    
    pub fn contribute(origin:OriginFor<T>,acc:AccountIdOf<T> ,value:BalanceOf<T>) -> DispatchResult{
        let c1=Contribution::new(&acc,&value);
        let _who = ensure_signed(origin)?;
        let _now = <frame_system::Pallet<T>>::block_number();
        if ContributionsLog::<T>::contains_key(c1.account){
            ContributionsLog::<T>::mutate(c1.account, |val|{
                *val += *c1.amount;
            })
        } else {
            ContributionsLog::<T>::insert(&acc,value);
            ContAccounts::<T>::mutate(|val|{
                val.push(acc);
            })
        }
        
        //function taking contribution storage and amount as inputs here
        Ok(().into())


    }
}

this code is located in a mod.rs file it looks good to me, until I try to use the contribute method in my lib.rs:

impl<T: Config> Pallet<T> {
  
  #[pallet::weight(10_000 + T::DbWeight::get().writes(1))]
  pub fn do_something(origin: OriginFor<T>, something: u32, acc:AccountIdOf<T> ,rent:BalanceOf<T>,cd:CID,prop:Properties,start:Option<BlockNumberOf<T>>,end:Option<BlockNumberOf<T>>) -> DispatchResult 
  { 
     let who = ensure_signed(origin)?;
     let dev=Investor::new(&acc,something);
     Investor::<T::AccountId,u32>::contribute(who,dev.account_id,rent);
    
     <Something<T>>::put(dev.nft+something);

     Self::deposit_event(Event::SomethingStored(something, who));
     Ok(())
  }

this then give me the following error:

error[E0599]: the function or associated item `contribute` exists for struct `roles::Investor<<T as frame_system::Config>::AccountId, u32>`, but its trait bounds were not satisfied
   --> pallets/template/src/lib.rs:144:40
    |
144 |          Investor::<T::AccountId,u32>::contribute(who,dev.account_id,rent);
    |                                        ^^^^^^^^^^ function or associated item cannot be called on `roles::Investor<<T as frame_system::Config>::AccountId, u32>` due to unsatisfied trait bounds
    |
   ::: pallets/template/src/roles/mod.rs:14:1
    |
14  | pub struct Investor<T,U>{
    | ------------------------ function or associated item `contribute` not found for this
    |
    = note: the following trait bounds were not satisfied:
            `<T as frame_system::Config>::AccountId: pallet::Config`
            `<T as frame_system::Config>::AccountId: frame_system::Config`

trying to implement investor as below didn't solve the problem either:

    impl<T:frame_system::Config+pallet::Config,U> Investor<T,U>{
    pub fn new(acc: T,nft:U)-> Self{
        Investor{
            account_id: acc,
            nft: nft,
        }        
    }

  }

Any advice? Please?

link to the repo/lib.rs: https://github.com/Fair-Squares/fair-squares/blob/structure_template/pallets/template/src/lib.rs Kazu

1
  • Take advantage of cargo fmt in order to make your code more easily readable.
    – Shawn Tabrizi
    Mar 18, 2022 at 2:20

3 Answers 3

5

You are really mixing up what the generic types mean to you.

In one case, you have T represent the AccountId directly, and in the other case you have it represent your Config.

Here is a minimal sample which uses most of the same code as what you want and compiles:

#![cfg_attr(not(feature = "std"), no_std)]

pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
    use frame_support::{pallet_prelude::*, traits::Currency};
    use frame_system::pallet_prelude::*;

    type BalanceOf<T> =
        <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
    type AccountIdOf<T> = <T as frame_system::Config>::AccountId;

    #[pallet::config]
    pub trait Config: frame_system::Config {
        type Currency: Currency<Self::AccountId>;
    }

    #[pallet::pallet]
    #[pallet::generate_store(pub(super) trait Store)]
    pub struct Pallet<T>(_);

    #[pallet::call]
    impl<T: Config> Pallet<T> {
        #[pallet::weight(10_000 + T::DbWeight::get().writes(1))]
        pub fn do_something(
            origin: OriginFor<T>,
            something: u32,
            acc: AccountIdOf<T>,
            rent: BalanceOf<T>,
        ) -> DispatchResult {
            let who = ensure_signed(origin.clone())?;
            let dev = Investor::<T, u32>::new(acc, something);
            Investor::<T, u32>::contribute(origin, dev.account_id, rent)?;

            // Do something

            Ok(())
        }
    }

    #[derive(Debug, PartialEq, Encode, Decode)]
    pub struct Investor<T: Config, U> {
        pub account_id: AccountIdOf<T>,
        pub nft: U,
    }

    impl<T: Config, U> Investor<T, U> {
        pub fn new(acc: AccountIdOf<T>, nft: U) -> Self {
            Investor { account_id: acc, nft }
        }

        pub fn contribute(
            origin: OriginFor<T>,
            acc: AccountIdOf<T>,
            value: BalanceOf<T>,
        ) -> DispatchResult {
            // Do something

            Ok(())
        }
    }
}

Note in this case, T always represents T: Config, and AccountId is always called with AccountIdOf<T>.

1
  • Thank you!! it worked! the main problem was as you pointed, the inconsistency of what I had in T. but another take away is the trait bound(?) when making the struct. I'm using Steve Klabnik book, and I don't remember seeing something similar (missed it maybe...). You're a Rust Wizard !!!! Mar 18, 2022 at 8:20
0

Rewrite your struct so that it's not generic over T:

For example:

#[derive(Debug, PartialEq, Encode, Decode)]
pub struct Investor<AccountId, U>{
    pub account_id: AccountId,
    pub nft: U,
}

and then apply the changes to the other parts of your code.

2
  • Sorry, but I will implement additional functions which use different types so: I need it to be generic. I am also trying to understand the source of the problem, and not avoiding it if possible. Mar 17, 2022 at 14:09
  • @KazunobuNdong looks like Shawn explained the solution and you managed to fix the issue =) I corrected the code snippet - my bad! Mar 18, 2022 at 11:05
-1

To create a runtime you need to call construct_runtime! macro that will create your pallet type, but you also have to configure the pallets so in this case you will need a pub trait Config: frame_system::Config {pub trait Config: frame_system::Config {, have a look at how the nicks pallet is done for example:

https://docs.substrate.io/tutorials/v3/add-a-pallet/

1

Your Answer

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

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