2

I wonder if there is some tutorial or help available for adding pre-defined pallets to a runtime (like Balance, Utility, Treasury).

There is a very good resource on substrate site here. But it only tells you the how part, it does not cover the why part of the puzzle. I really looking for a detailed explanation that explains each and every step in detail with the reasoning that why we are performing that specific task. Specially the types definition that we configure for a specific pallet.

2 Answers 2

3

Just to add an example:

let's add the pallet-assets to the substrate-node-template.

  • First, we add the dependency and the feature in the runtime/Cargo.toml file

The dependency is required for obtaining the pallet-assets source code. As for the std/no_std feature, have a look at this post.

  • Second, we specify the configuration for pallet-assets in our runtime/src/lib.rs

In other words, we are implementing the functionality for assets in our chain but we have to configure the pallet's types. These types, known as associated types (for pallet-assets: Balances, AssetId, etc), implement certain traits e.g.:

type Currency: ReservableCurrencySelf::AccountId;

The Currency type is declared which will be used in this pallet and it implements (or has to implement) the ReservableCurrencySelf::AccountId trait. So we need to specify what Currency is in our runtime and it has to implement the ReservableCurrencySelf::AccountId trait. If we look how pallet-assets is configured in statemint:

type Currency = Balances;

where Balances is coming from pallet-balances. Pallet-balances needs to implement the ReservableCurrencySelf::AccountId trait which is the case as you can see here.

These first two steps are required for any pallet you want to add to your runtime. However, for some pallets there are some additional steps required e.g. for pallet_assets the genesis configuration. This allows to define the genesis configuration for the pallet (ref) which needs to be done in node/src/chain_spec.rs like here.

P.S. What is helping me a lot with understanding substrate code is literally following the code (I use rust-analyzer) and see where this function/variable/trait/type is coming from.

3
  • I am really thankful for your detailed explanation. Can you please help me/ point me to some resource for setting up genesis_config for a pallet as well. Since some of the pallets like pallet_treasury and pallet_collective needs some changes in the genesis config too. But I am not very sure, how to grab these changes exactly. Jan 18 at 11:17
  • Maybe make a different question about it so that other people in the future can find it and learn from it as well :)! Jan 18 at 11:25
  • Oky. I will. Thank you very much Jan 18 at 14:06
1

I really looking for a detailed explanation that explains each and every step in detail with the reasoning that why we are performing that specific task.

This is generally not possible, given the number of pallets that substrate FRAME gives you, but there are a few things that can help you understand how it works. While it can be a bit intimidating to see the complexity, most pallet configurations boil down to implementing the Config trait from the pallet that you're trying to include in your Runtime. The whole point of pallets is to provide you with a modular way of integrating logic into your Runtime.

Coming back to implementing Config for Runtime, the way you get a feel for it is by checking out the reference implementation in the substrate repo, which is a good source of knowledge. You can look at how they've implemented a type, and then make modifications to it to add your customization. Then you should look at the trait bounds for the various associated types that you're required to add. Mostly you will have a Get<T> bound for parameters that require a const, and you can generate a Get<_> impl for T by using the helpful parameter_types! macro. Another way, if you're just dealing with numbers is to use one of the Const___ types like ConstU128<13> that defines a Get impl for the number 13.

Trait bounds tell you what's required for the pallet to work. Not just custom types, but pallets themselves can implement a trait, one such example is the balances pallet which implements Currency:

impl<T: Config<I>, I: 'static> Currency<<T as Config>::AccountId> for Pallet<T, I>

4
  • Thanks @ab-neo for the detailed explanation. Let me check the implementation of these pallets in different reference implementation. Jan 16 at 16:55
  • Can you please quote an example where treasury pallet is implemented Jan 17 at 10:32
  • Thanks for the help. I am learning a lot from these resources. Is there general guide available that explain the bit and pieces of the different macros related to adding a pallet t the runtime like parameter_types!() etc Jan 17 at 12:46

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.