Configuring Genesis for Balances
Genesis configuration defines the initial state for things such as accounts, balances, genesis for custom pallets, and more. This guide explains how to configure the genesis of a pallet with 2 simple storage items.
Implement genesis inside your pallet
For the sake of this guide, we'll assume you have a pallet <SingleValue<T>> and <AccountMap<T>>.
For example:
#[pallet::storage]
#[pallet::getter(fn something)]
pub type SingleValue<T: Config> = StorageValue<_, T::Balance>;
// A map that has enumerable entries.
#[pallet::storage]
#[pallet::getter(fn accounts)]
pub type AccountMap<T: Config> = StorageMap<_, Blake2_128Concat, T::AccountId, T::Balance>;
The GenesisConfig code should go after your storage items.
Using the
#[pallet::genesis_config]attribute, write theGenesisConfigstruct for your pallet.#[pallet::genesis_config] pub struct GenesisConfig<T: Config> { pub single_value: T::Balance, pub account_map: Vec<(T::AccountId, T::Balance)>, }Set the default value for the
GenesisConfigstruct.#[cfg(feature = "std")] impl<T: Config> Default for GenesisConfig<T> { fn default() -> Self { Self { single_value: Default::default(), account_map: Default::default() } } }Using the
#[pallet::genesis_build]attribute, implement theGenesisBuildtrait.#[pallet::genesis_build] impl<T: Config> GenesisBuild<T> for GenesisConfig<T> { fn build(&self) { <SingleValue<T>>::put(&self.single_value); for (a, b) in &self.account_map { <AccountMap<T>>::insert(a, b); } } }This allows you to execute some logic to define how the
GenesisConfigstruct places something in storage.
Configure your node's chain spec
All that's left to do is to specify what values we want to put in the genesis state of our chain.
We'll assume our pallet is called pallet_something, declared as PalletSomething in our runtime's construct_runtime! macro.
In
node/chain_spec.rs, create a constant value of typeT::Balanceto be stored in<SingleValue<T>>(inside thetestnet_genesismethod).const VALUE: Balance = 235813;Note that this step also implies that we have
use node_template_runtime::Balance;imported at the top of ourchain_spec.rsfile.Create a vector of accounts to initialize
<AccountMap<T>>with (also inside thetestnet_genesismethod).let accounts_to_map: Vec<AccountId> = vec![ get_account_id_from_seed::<sr25519::Public>("Alice"), get_account_id_from_seed::<sr25519::Public>("Bob"), get_account_id_from_seed::<sr25519::Public>("Charlie"), ];Complete the
GenesisConfigclause in thetestnet_genesisfunction.The convention is to use lowercase spelling of the name of your pallet in
runtime/src/lib.rsinsideconstruct_runtime!. For pallets declared asCamelCasefor example, the convention is to refer to it ascamel_casein thetestnet_genesisfunction.In our example, this looks like:
pallet_something: PalletSomethingConfig { single_value: VALUE, account_map: accounts_to_map.iter().cloned().map(|x| (x, VALUE)).collect(), }In the above code, we're mapping each account from
accounts_to_mapto an amount equal toVALUE. This pattern is very similar to the Balances pallet'sGenesisConfigimplementation.
Example
Related material
- Learn how to customize a chain's genesis configuration for the balances pallet.
BalancesConfig