You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Learn how to implement multiple instances of the same pallet in your Polkadot SDK-based runtime to create and interact with modular blockchain components.
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](https://doc.rust-lang.org/reference/items/generics.html){target=\_blank} `I`.
15
+
This generic `I` creates a unique [lifetime](https://doc.rust-lang.org/rust-by-example/scope/lifetime.html){target=\_blank} 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
+
pubstructPallet<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/{{dependencies.repositories.polkadot_sdk.version}}/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:
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:
While the example above uses identical configurations for both instances, you can customize each instance's parameters to serve different purposes within your runtime.
107
+
108
+
### Add Pallet Instances to the Runtime
109
+
110
+
Finally, add both pallet instances to your runtime definition, ensuring each has:
111
+
112
+
- A unique pallet index
113
+
- The correct instance type specified
114
+
115
+
```rust hl_lines="6-10"
116
+
#[frame_support::runtime]
117
+
modruntime {
118
+
#[runtime::runtime]
119
+
// ... other runtime configuration
120
+
121
+
#[runtime::pallet_index(16)]
122
+
pubtypeCollective1=pallet_collective<Instance1>;
123
+
124
+
#[runtime::pallet_index(17)]
125
+
pubtypeCollective2=pallet_collective<Instance2>;
126
+
127
+
// ... other pallets
128
+
}
129
+
```
130
+
131
+
## Where to Go Next
132
+
133
+
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.
134
+
135
+
Now that you've mastered implementing multiple pallet instances, the next step is creating your own custom pallets. Explore the following resources:
136
+
137
+
<divclass="grid cards"markdown>
138
+
139
+
- <spanclass="badge guide">Guide</span> __Make a Custom Pallet__
140
+
141
+
---
142
+
143
+
Learn how to create custom pallets using FRAME, allowing for flexible, modular, and scalable blockchain development. Follow the step-by-step guide.
Learn how to implement multiple instances of the same pallet in your Polkadot SDK-based runtime to create and interact with modular blockchain components.
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.
3112
+
---
3113
+
3114
+
# Add Multiple Pallet Instances
3115
+
3116
+
## Introduction
3117
+
3118
+
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.
3119
+
3120
+
## Understanding Instantiable Pallets
3121
+
3122
+
Unlike standard pallets that exist as a single instance in a runtime, instantiable pallets require special configuration through an additional [generic parameter](https://doc.rust-lang.org/reference/items/generics.html){target=\_blank} `I`.
3123
+
This generic `I` creates a unique [lifetime](https://doc.rust-lang.org/rust-by-example/scope/lifetime.html){target=\_blank} for each pallet instance, affecting the pallet's generic types and its configuration trait `T`.
3124
+
3125
+
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`:
3126
+
3127
+
```rust
3128
+
#[pallet::pallet]
3129
+
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
3130
+
```
3131
+
3132
+
The instantiation generic also appears throughout the pallet's components, including the `Config` trait, storage items, events, errors, and genesis configuration.
3133
+
3134
+
## Adding Instantiable Pallets to Your Runtime
3135
+
3136
+
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/{{dependencies.repositories.polkadot_sdk.version}}/substrate/frame/collective){target=\_blank} is implemented.
3137
+
3138
+
### Define Pallet Parameters
3139
+
3140
+
First, define the parameters needed to configure the pallet instances. This step is identical whether implementing single or multiple instances:
For a single instance, the configuration would look like this:
3154
+
3155
+
```rust hl_lines="1"
3156
+
impl pallet_collective::Config for Runtime {
3157
+
type RuntimeOrigin = RuntimeOrigin;
3158
+
type Proposal = RuntimeCall;
3159
+
type RuntimeEvent = RuntimeEvent;
3160
+
type MotionDuration = MotionDuration;
3161
+
type MaxProposals = MaxProposals;
3162
+
type MaxMembers = MaxMembers;
3163
+
type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote;
3164
+
type SetMembersOrigin = EnsureRoot<AccountId>;
3165
+
type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
3166
+
type MaxProposalWeight = MaxProposalWeight;
3167
+
type DisapproveOrigin = EnsureRoot<Self::AccountId>;
3168
+
type KillOrigin = EnsureRoot<Self::AccountId>;
3169
+
type Consideration = ();
3170
+
}
3171
+
```
3172
+
3173
+
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:
3174
+
3175
+
```rust hl_lines="2-3"
3176
+
// Configure first instance
3177
+
type Collective1 = pallet_collective::Instance1;
3178
+
impl pallet_collective::Config<Collective1> for Runtime {
3179
+
type RuntimeOrigin = RuntimeOrigin;
3180
+
type Proposal = RuntimeCall;
3181
+
type RuntimeEvent = RuntimeEvent;
3182
+
type MotionDuration = MotionDuration;
3183
+
type MaxProposals = MaxProposals;
3184
+
type MaxMembers = MaxMembers;
3185
+
type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote;
3186
+
type SetMembersOrigin = EnsureRoot<AccountId>;
3187
+
type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
3188
+
type MaxProposalWeight = MaxProposalWeight;
3189
+
type DisapproveOrigin = EnsureRoot<Self::AccountId>;
3190
+
type KillOrigin = EnsureRoot<Self::AccountId>;
3191
+
type Consideration = ();
3192
+
}
3193
+
```
3194
+
```rust hl_lines="2-3"
3195
+
// Configure second instance
3196
+
type Collective2 = pallet_collective::Instance2;
3197
+
impl pallet_collective::Config<Collective2> for Runtime {
3198
+
type RuntimeOrigin = RuntimeOrigin;
3199
+
type Proposal = RuntimeCall;
3200
+
type RuntimeEvent = RuntimeEvent;
3201
+
type MotionDuration = MotionDuration;
3202
+
type MaxProposals = MaxProposals;
3203
+
type MaxMembers = MaxMembers;
3204
+
type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote;
3205
+
type SetMembersOrigin = EnsureRoot<AccountId>;
3206
+
type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
3207
+
type MaxProposalWeight = MaxProposalWeight;
3208
+
type DisapproveOrigin = EnsureRoot<Self::AccountId>;
3209
+
type KillOrigin = EnsureRoot<Self::AccountId>;
3210
+
type Consideration = ();
3211
+
}
3212
+
```
3213
+
3214
+
While the example above uses identical configurations for both instances, you can customize each instance's parameters to serve different purposes within your runtime.
3215
+
3216
+
### Add Pallet Instances to the Runtime
3217
+
3218
+
Finally, add both pallet instances to your runtime definition, ensuring each has:
3219
+
3220
+
- A unique pallet index
3221
+
- The correct instance type specified
3222
+
3223
+
```rust hl_lines="6-10"
3224
+
#[frame_support::runtime]
3225
+
mod runtime {
3226
+
#[runtime::runtime]
3227
+
// ... other runtime configuration
3228
+
3229
+
#[runtime::pallet_index(16)]
3230
+
pub type Collective1 = pallet_collective<Instance1>;
3231
+
3232
+
#[runtime::pallet_index(17)]
3233
+
pub type Collective2 = pallet_collective<Instance2>;
3234
+
3235
+
// ... other pallets
3236
+
}
3237
+
```
3238
+
3239
+
## Where to Go Next
3240
+
3241
+
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.
3242
+
3243
+
Now that you've mastered implementing multiple pallet instances, the next step is creating your own custom pallets. Explore the following resources:
3244
+
3245
+
<div class="grid cards" markdown>
3246
+
3247
+
- <span class="badge guide">Guide</span> __Make a Custom Pallet__
3248
+
3249
+
---
3250
+
3251
+
Learn how to create custom pallets using FRAME, allowing for flexible, modular, and scalable blockchain development. Follow the step-by-step guide.
0 commit comments