Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Builders-substrate-adding built in module article #22

Merged
merged 28 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2beadd4
pages index
augustocollado Aug 16, 2023
a89f63d
article
augustocollado Aug 16, 2023
5444552
Merge branch 'main' into augustocollado/builders-basic-substrate
augustocollado Aug 17, 2023
7a5bc8c
Merge branch 'main' into augustocollado/builders-basic-substrate
augustocollado Aug 17, 2023
d1a9ea0
removed content
augustocollado Aug 18, 2023
881e035
layout article
augustocollado Aug 18, 2023
03bc029
substrate wip
augustocollado Aug 23, 2023
9338abc
Merge branch 'main' into augustocollado/builders-basic-substrate
augustocollado Aug 29, 2023
5c1d024
minor changes
augustocollado Aug 29, 2023
8895c9c
builders-substrate-adding built in
augustocollado Aug 29, 2023
d92db7a
added commented entry
augustocollado Aug 29, 2023
83b6bd7
remove unused image
augustocollado Aug 29, 2023
db1ab47
Apply suggestions from code review
augustocollado Aug 30, 2023
87ccd69
More context to the std features
augustocollado Aug 31, 2023
37a10dd
PR feedback
augustocollado Sep 1, 2023
3203c25
grammar
augustocollado Sep 1, 2023
484c88a
CHanges for clarity
augustocollado Sep 4, 2023
2d62d51
Apply suggestions from code review
augustocollado Sep 4, 2023
b99cb81
Grammar checks
augustocollado Sep 4, 2023
881696c
Horizontal scrollbar for toml
augustocollado Sep 4, 2023
d9cdd30
HOrizontal scrollbar
augustocollado Sep 4, 2023
ff63906
Update builders/build/substrate/adding-built-in-pallet.md
augustocollado Sep 5, 2023
e6ae7f3
Merge branch 'main' into augustocollado/builders-basic-substrate
augustocollado Sep 6, 2023
18ff44f
Lines
augustocollado Sep 6, 2023
9b3a49d
Built-in
augustocollado Sep 6, 2023
5aa8a5b
Apply suggestions from code review
augustocollado Sep 8, 2023
8c4c4d8
fix _blank
augustocollado Sep 8, 2023
f575310
grammar correction
augustocollado Sep 8, 2023
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
54 changes: 54 additions & 0 deletions .snippets/code/basic-substrate/built-in-pallet-configuration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
parameter_types! {
// The amount of funds that must be reserved for an asset
pub const AssetDeposit: Balance = 100;
// The amount of funds that must be reserved when creating
// a new transfer approval
pub const ApprovalDeposit: Balance = 1;
// The basic amount of funds that must be reserved when adding metadata
// to your asset
pub const MetadataDepositBase: Balance = 10;
// The additional funds that must be reserved for the number of bytes
// you store in your metadata
pub const MetadataDepositPerByte: Balance = 1;

augustocollado marked this conversation as resolved.
Show resolved Hide resolved
// Maximum lenght for the asset symbol and friendly name
pub const StringLimit: u32 = 50;
}

// Implementing the Assets config trait for the runtime
impl pallet_assets::Config for Runtime {
type RuntimeEvent = RuntimeEvent;

// Stores the balances in an unsigned integer of 128bits
type Balance = u128;
// The id of an asset can be defined as an unsigned integer of 64 bits
type AssetId = u64;
// Uses module Balances as mechanism for currency operations
type Currency = Balances;

// Configure the module by referencing the previously
// defined constants

augustocollado marked this conversation as resolved.
Show resolved Hide resolved
type AssetDeposit = AssetDeposit;
type MetadataDepositBase = MetadataDepositBase;
type MetadataDepositPerByte = MetadataDepositPerByte;
type ApprovalDeposit = ApprovalDeposit;
type StringLimit = StringLimit;

// More configuration

augustocollado marked this conversation as resolved.
Show resolved Hide resolved
type AssetIdParameter = u64;
// Defines the allowed origins to create assets
type CreateOrigin =
frame_support::traits::AsEnsureOriginWithArg<frame_system::EnsureSigned<AccountId>>;
// Root can create assets
type ForceOrigin = EnsureRoot<AccountId>;
type AssetAccountDeposit = frame_support::traits::ConstU128<1>;
type Freezer = ();
type Extra = ();
type WeightInfo = pallet_assets::weights::SubstrateWeight<Runtime>;
type RemoveItemsLimit = frame_support::traits::ConstU32<1000>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = ();
type CallbackHandle = ();
}
2 changes: 1 addition & 1 deletion builders/build/.pages
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ hide: false
nav:
- index.md
- 'Prerequisites': 'prerequisites.md'
# - 'Basic Substrate': 'substrate.md'
- substrate
# - 'Templates': 'templates.md'
# - 'Modifying your ContainerChain': 'modifying.md'
# - 'Test Locally': 'test.md'
Expand Down
6 changes: 6 additions & 0 deletions builders/build/substrate/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
title: Basic Substrate
hide: false
nav:
- index.md
- 'Adding a Built-in Module': 'adding-built-in-pallet.md'
# - 'Adding a Custom-Made Module': 'adding-custom-made-pallet.md'
201 changes: 201 additions & 0 deletions builders/build/substrate/adding-built-in-pallet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
---
title: Adding Built-in Substrate Modules
description: Substrate is a modular blockchain framework that includes many ready-to-use modules covering a wide range of common functionalities to include in your runtime.
---

# Adding a Built-In Module {: #adding-builtin-module }
augustocollado marked this conversation as resolved.
Show resolved Hide resolved

## Introduction {: #introduction }

Substrate is a powerful and modular software development framework included in the Polkadot SDKs for building blockchains. It provides a comprehensive set of tools and libraries that abstract complex blockchain functionalities, allowing developers to focus on building innovative features and applications by focusing on the runtime, which contains the core logic and the rules of the state transition for the use case.

What sets Substrate apart is its modular architecture, which enables the seamless integration of pre-built modules and the creation of custom ones, facilitating the development of blockchain protocols.

If the use case requires only EVM (Ethereum virtual machine) compatibility, then the provided template included in the [Tanssi repository](https://github.com/moondance-labs/tanssi#container-chain-templates){target=_blank} will meet the requirements and need no additional changes, but teams willing to build a Substrate Appchain will need to add and compose the built-in modules and the custom-made ones into the runtime, compile and generate the chain specification, and, finally, deploy through the Tanssi protocol to evolve into a live ContainerChain.
augustocollado marked this conversation as resolved.
Show resolved Hide resolved

In this article, the necessary steps involved when adding a built-in module are covered.
augustocollado marked this conversation as resolved.
Show resolved Hide resolved

## Adding a Built-in Module to the Runtime {: #adding-a-built-in-module }

As introduced in the [modularity](/learn/framework/modules) article, the Substrate framework already includes many built-in modules addressing a wide range of functionalities, ready to be used in your runtime.

Modules are meant to provide the functionality needed in very different use cases such as DeFi, NFTs, or any other, and, therefore, they are basic building blocks that are inherently abstract and can be configured according to the specific needs of the Appchain.

To add a module, the following steps are necessary:

1. Make the dependency available within the project by declaring it in [Cargo](https://doc.rust-lang.org/cargo/){target=_blank}, the Rust language package manager
2. Make the standard (`std`) features of the module available to the compiler
3. Configure the module
4. Add the module to the runtime
5. Add the default configuration to the chain specification

In the following example, the very popular Substrate module `pallet-assets` will be added to the runtime of the provided EVM template, found in the [Tanssi repository](https://github.com/moondance-labs/tanssi){target=_blank}, specifically in the folder `container-chains/templates/frontier/`.
augustocollado marked this conversation as resolved.
Show resolved Hide resolved

### Declare the Dependency {: #declare-dependency }

Every package contains a manifest file named `Cargo.toml` stating, among other things, all the dependencies the package relies on, and the ContainerChain runtime is no exception.

To declare the dependency and make it available to the runtime, open the `Cargo.toml` file located in the folder `runtime` with a text editor and add the module, referencing the code in the official repository of the Polkadot SDK:
augustocollado marked this conversation as resolved.
Show resolved Hide resolved

```toml
[dependencies]
...
pallet-assets = {
git = "https://github.com/paritytech/polkadot-sdk",
branch = "master",
default-features = false
}
...
```

### Make the Standard Features Available to the Compiler {: #standard-features }

In Cargo, the “features” flags provide a mechanism to tell the compiler to include or leave out certain portions of code, which is a useful mechanism to optimize compile time, minimize binary file sizes, or disable certain behavior (for example, not including unit testing or benchmarking functionality in the runtime intended for production).

To compile the standard features for the Assets module within the runtime, the same `Cargo.toml` file in the `runtime` folder must be edited, enabling the flag. Everything listed in this section will ensure that it is available to the compiler when building the runtime binary, which is ultimately the file containing all the information to run your ContainerChain initially.

```toml
[features]
default = [
"std",
]
std = [
...,
"pallet-assets/std",
...
]
```
### Configure the Module {: #configure-the-module }

With the dependency declared in the project, the module can now be configured and added to the runtime. To do so, you need to edit the `lib.rs` file that is located at:

```text
*/runtime/src/lib.rs
```

The configuration of new modules requires implementing a configuration `trait` for the module (in this example, for Assets) in the runtime, expressed in Rust as follows:

```rust
// Implements pallet_assets::Config trait in the runtime
impl pallet_assets::Config for Runtime { ... }
```

[Traits](https://doc.rust-lang.org/book/ch10-02-traits.html){target=_blank} are a way of defining shared behavior in Rust, and in this case, they allow a new runtime to benefit from the functionality the Assets module provides only by implementing its configuration trait and parameters.

Some of the parameters the trait needs to define might be constant values, in which case, they have to be defined and enclosed within the macro `parameter_types!`, which helps us to reduce the development effort by expanding the code and converting each of the constants into the correct struct type with functions that allow the runtime to read its type and values in a standardized way.

The following code snippet shows an example of the constant definitions to be used in the configuration of the module:

```rust
parameter_types! {
augustocollado marked this conversation as resolved.
Show resolved Hide resolved
// The amount of funds that must be reserved for an asset
pub const AssetDeposit: Balance = 100;
// The amount of funds that must be reserved when creating
// a new transfer approval
pub const ApprovalDeposit: Balance = 1;
// The basic amount of funds that must be reserved when adding metadata
// to your asset
pub const MetadataDepositBase: Balance = 10;
// The additional funds that must be reserved for the number of bytes
// you store in your metadata
pub const MetadataDepositPerByte: Balance = 1;

// Maximum lenght for the asset symbol and friendly name
pub const StringLimit: u32 = 50;
}
```

It is important to note that every built-in module has a different purpose, and, therefore, each of them has different needs in terms of the parameters that must be configured. The following code snippet implements the trait and configures the module Assets, using types and the constants defined previously in the `parameter_types!` macro:

```rust
// Implementing the Assets config trait for the runtime
impl pallet_assets::Config for Runtime {

// Stores the balances in an unsigned integer of 128bits
type Balance = u128;
// The id of an asset can be defined as an unsigned integer of 64 bits
type AssetId = u64;
// Uses module Balances as mechanism for currency operations
type Currency = Balances;

// Configure the module by referencing the previously
// defined constants

type AssetDeposit = AssetDeposit;
type MetadataDepositBase = MetadataDepositBase;
type MetadataDepositPerByte = MetadataDepositPerByte;
type ApprovalDeposit = ApprovalDeposit;
type StringLimit = StringLimit;

// More configuration
...
}
```

??? code "View the complete script"

```rust
--8<-- 'code/basic-substrate/built-in-pallet-configuration.rs'
```

The complete configuration of the module contains more parameters, to view a detailed description of each of them, refer to the [official config trait for the Assets module documentation](https://paritytech.github.io/substrate/master/pallet_assets/pallet/trait.Config.html){target=_blank}.

### Add the Module to the Runtime {: #add-module-to-runtime }

In the same `lib.rs` file referenced in the previous section, there is a segment enclosed in the macro `construct_runtime!()`. This is where the pallet must be added to be included in the runtime. Since the example is based on the EVM template, the runtime is already configured to include many modules, including the modules for system support, the modules to add the Ethereum compatibility layer, the modules to support the Tanssi protocol, balances, and now also Assets:

```rust
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
// System support stuff.
System: frame_system = 0,
ParachainSystem: cumulus_pallet_parachain_system = 1,
Timestamp: pallet_timestamp = 2,
ParachainInfo: parachain_info = 3,
Sudo: pallet_sudo = 4,
Utility: pallet_utility = 5,
...
Balances: pallet_balances = 10,
// Assets module is added here
Assets: pallet_assets = 11,
augustocollado marked this conversation as resolved.
Show resolved Hide resolved
...
}
```

### Configure the Module in the Chain Specification {: #configure-chain-specs }

Finally, add the configuration in the chain specification for the genesis state in the file `chain_spec.rs` located at:

```text
*/node/src/chain_spec.rs
```

The function `testnet_genesis`, presented in the following code snippet, defines the initial state for the modules included in the runtime (such as initial funded accounts, for example). After adding the Assets module, it is necessary to initialize it as well, and in the following example, its default values are defined.

More about the chain specification and how to configure it will be covered in the article [Modifying Your ContainerChain](/builders/build/modifying).

```rust hl_lines="14"
fn testnet_genesis(
endowed_accounts: Vec<AccountId>,
id: ParaId,
root_key: AccountId,
) -> container_chain_template_frontier_runtime::GenesisConfig {
container_chain_template_frontier_runtime::GenesisConfig {
system: container_chain_template_frontier_runtime::SystemConfig {
code: container_chain_template_frontier_runtime::WASM_BINARY
.expect("WASM binary was not build, please build it!")
.to_vec(),
},
...
// Add the default state for this module in the genesis state
assets: Default::default()
...
}
}
```

With the module included, this new runtime version has unlocked a new set of functionalities ready to be composed with even more of the Substrate built-in modules or custom-made ones.
8 changes: 8 additions & 0 deletions builders/build/substrate/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: Basic Substrate
description: Substrate is a powerful and modular blockchain framework built in Rust that is used to build Polkadot's relay chain, the Tanssi network, and ContainerChains.
template: subsection-index-page.html
hide:
- toc
- feedback
---
Binary file added images/index-pages/builders/build/substrate.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading