Skip to content

Commit 9e88888

Browse files
committed
Add instantiable pallets
1 parent 2e6b38e commit 9e88888

File tree

4 files changed

+316
-128
lines changed

4 files changed

+316
-128
lines changed

develop/parachains/customize-parachain/.pages

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ nav:
33
- index.md
44
- 'Overview (FRAME)': overview.md
55
- 'Add Existing Pallets': add-existing-pallets.md
6+
- 'Add Multiple Pallet Instances': add-pallet-instances.md
67
- 'Add Smart Contract Functionality': add-smart-contract-functionality.md
78
- 'Make a Custom Pallet': make-custom-pallet.md

develop/parachains/customize-parachain/add-existing-pallets.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,14 @@ With the pallet successfully added and configured, the runtime is ready to be co
149149
150150
<div class="grid cards" markdown>
151151
152+
- <span class="badge guide">Guide</span> __Add Multiple Pallet Instances__
153+
154+
---
155+
156+
Learn how to implement multiple instances of the same pallet in your Polkadot SDK-based runtime to create and interact with modular blockchain components.
157+
158+
[:octicons-arrow-right-24: Reference](/develop/parachains/customize-parachain/add-pallet-instances/)
159+
152160
- <span class="badge guide">Guide</span> __Make a Custom Pallet__
153161
154162
---
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
title: Add Multiple Pallet Instances
3+
description: Learn how to implement multiple instances of the same pallet in your Polkadot SDK-based runtime to create and interact with modular blockchain components.
4+
---
5+
6+
# Add Multiple Pallet Instances
7+
8+
## Introduction
9+
10+
Running multiple instances of the same pallet within a runtime is a powerful technique in Polkadot SDK development. This approach lets you reuse pallet functionality without reimplementing it, enabling diverse use cases with the same codebase. The Polkadot SDK provides developer-friendly traits for creating instantiable pallets and in most cases handles unique storage allocation for different instances automatically. This guide teaches you how to implement and configure multiple instances of a pallet in your runtime.
11+
12+
## Understanding Instantiable Pallets
13+
14+
Unlike standard pallets that exist as a single instance in a runtime, instantiable pallets require special configuration through an additional generic parameter `I`.
15+
This generic `I` creates a unique lifetime for each pallet instance, affecting the pallet's generic types and its configuration trait `T`.
16+
17+
You can identify an instantiable pallet by examining its `Pallet` struct definition, which will include both the standard generic `T` and the instantiation generic `I`:
18+
19+
```rust
20+
#[pallet::pallet]
21+
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
22+
```
23+
24+
The instantiation generic also appears throughout the pallet's components, including the `Config` trait, storage items, events, errors, and genesis configuration.
25+
26+
## Adding Instantiable Pallets to Your Runtime
27+
28+
The process resembles adding a standard pallet with some key differences. In this example you will see how adding two instances of the [pallet-collective](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2412/substrate/frame/collective){target=\_blank} is implemented.
29+
30+
### Define Pallet Parameters:
31+
32+
First, define the parameters needed to configure the pallet instances. This step is identical whether implementing single or multiple instances:
33+
34+
```rust
35+
parameter_types! {
36+
pub const MotionDuration: BlockNumber = 24 * HOURS;
37+
pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block;
38+
pub const MaxProposals: u32 = 100;
39+
pub const MaxMembers: u32 = 100;
40+
}
41+
```
42+
43+
### Configure the Pallet Instances
44+
45+
For a single instance, the configuration would look like this:
46+
47+
```rust
48+
impl pallet_collective::Config for Runtime {
49+
type RuntimeOrigin = RuntimeOrigin;
50+
type Proposal = RuntimeCall;
51+
type RuntimeEvent = RuntimeEvent;
52+
type MotionDuration = MotionDuration;
53+
type MaxProposals = MaxProposals;
54+
type MaxMembers = MaxMembers;
55+
type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote;
56+
type SetMembersOrigin = EnsureRoot<AccountId>;
57+
type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
58+
type MaxProposalWeight = MaxProposalWeight;
59+
type DisapproveOrigin = EnsureRoot<Self::AccountId>;
60+
type KillOrigin = EnsureRoot<Self::AccountId>;
61+
type Consideration = ();
62+
}
63+
```
64+
65+
For multiple instances, you need to create a unique identifier for each instance using the `Instance` type with a number suffix, then implement the configuration for each one:
66+
67+
```rust
68+
// Configure first instance
69+
type Collective1 = pallet_collective::Instance1;
70+
impl pallet_collective::Config<Collective1> for Runtime {
71+
type RuntimeOrigin = RuntimeOrigin;
72+
type Proposal = RuntimeCall;
73+
type RuntimeEvent = RuntimeEvent;
74+
type MotionDuration = MotionDuration;
75+
type MaxProposals = MaxProposals;
76+
type MaxMembers = MaxMembers;
77+
type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote;
78+
type SetMembersOrigin = EnsureRoot<AccountId>;
79+
type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
80+
type MaxProposalWeight = MaxProposalWeight;
81+
type DisapproveOrigin = EnsureRoot<Self::AccountId>;
82+
type KillOrigin = EnsureRoot<Self::AccountId>;
83+
type Consideration = ();
84+
}
85+
86+
// Configure second instance
87+
type Collective2 = pallet_collective::Instance2;
88+
impl pallet_collective::Config<Collective2> for Runtime {
89+
type RuntimeOrigin = RuntimeOrigin;
90+
type Proposal = RuntimeCall;
91+
type RuntimeEvent = RuntimeEvent;
92+
type MotionDuration = MotionDuration;
93+
type MaxProposals = MaxProposals;
94+
type MaxMembers = MaxMembers;
95+
type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote;
96+
type SetMembersOrigin = EnsureRoot<AccountId>;
97+
type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
98+
type MaxProposalWeight = MaxProposalWeight;
99+
type DisapproveOrigin = EnsureRoot<Self::AccountId>;
100+
type KillOrigin = EnsureRoot<Self::AccountId>;
101+
type Consideration = ();
102+
}
103+
```
104+
105+
While the example above uses identical configurations for both instances, you can customize each instance's parameters to serve different purposes within your runtime.
106+
107+
### Add Pallet Instances to the Runtime
108+
109+
Finally, add both pallet instances to your runtime definition, ensuring each has:
110+
111+
- A unique pallet index
112+
- The correct instance type specified
113+
114+
```rust
115+
#[frame_support::runtime]
116+
mod runtime {
117+
#[runtime::runtime]
118+
// ... other runtime configuration
119+
120+
#[runtime::pallet_index(16)]
121+
pub type Collective1 = pallet_collective<Instance1>;
122+
123+
#[runtime::pallet_index(17)]
124+
pub type Collective2 = pallet_collective<Instance2>;
125+
126+
// ... other pallets
127+
}
128+
```
129+
130+
## Where to Go Next
131+
132+
If you've followed all the steps correctly, you should now be able to compile your runtime and interact with both instances of the pallet. Each instance will operate independently with its own storage, events, and configured parameters.
133+
134+
Now that you've mastered implementing multiple pallet instances, the natural next step is creating your own custom pallets. Explore the following resources:
135+
136+
<div class="grid cards" markdown>
137+
138+
- <span class="badge guide">Guide</span> __Make a Custom Pallet__
139+
140+
---
141+
142+
Learn how to create custom pallets using FRAME, allowing for flexible, modular, and scalable blockchain development. Follow the step-by-step guide.
143+
144+
[:octicons-arrow-right-24: Reference](/develop/parachains/customize-parachain/make-custom-pallet/)
145+
146+
</div>

0 commit comments

Comments
 (0)