So you have 2 pallets. The goal is to have a configuration variable C in pallet_1:
The configuration variable in pallet_1's trait should be something like MyConfig: Get<u32>
Something like this: https://github.com/paritytech/substrate/blob/master/frame/recovery/src/lib.rs#L200
So this says that we need to define a type which implements the Get<T>
trait:
https://github.com/paritytech/substrate/blob/master/frame/support/src/traits.rs#L471
So this is just a function fn get() -> T
Lets then assume you have pallet_2, where there is some storage item you want to control this config:
decl_storage!{
MyStorage: u32;
}
In your runtime/src/lib.rs, you define something like:
struct StorageToConfig;
impl Get<u32> for StorageToConfig {
fn get() -> u32 {
return pallet_2::MyStorage::get();
}
}
How can you use this struct in your trait definition in pallet_1, and make sure the runtime automatically pushes (or pallet_1 pulls from the runtime) the MyStorage var in pallet_2?
Here is a working example of how you would attach the value of a configuration trait to another pallet's storage item.
Here is pallet_1
which has the storage item we want to use.
NOTE: This storage is marked
pub
so it is accessible outside the pallet.
use frame_support::{decl_module, decl_storage};
use frame_system::ensure_signed;
pub trait Trait: frame_system::Trait {}
decl_storage! {
trait Store for Module<T: Trait> as TemplateModule {
pub MyStorage: u32;
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
#[weight = 0]
pub fn set_storage(origin, value: u32) {
let _ = ensure_signed(origin)?;
MyStorage::put(value);
}
}
}
Here is pallet_2
which has a configuration trait that we want to populate with the storage item from pallet_1
:
use frame_support::{decl_module, dispatch, traits::Get};
use frame_system::ensure_signed;
pub trait Trait: frame_system::Trait {
type MyConfig: Get<u32>;
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
#[weight = 0]
pub fn do_something(origin) -> dispatch::DispatchResult {
let _ = ensure_signed(origin)?;
let _my_config = T::MyConfig::get();
Ok(())
}
}
}
These two pallets are very straightforward and work separately. But if we want to connect them, we need to configure our runtime:
use frame_support::traits::Get;
impl pallet_1::Trait for Runtime {}
pub struct StorageToConfig;
impl Get<u32> for StorageToConfig {
fn get() -> u32 {
return pallet_1::MyStorage::get();
}
}
impl pallet_2::Trait for Runtime {
type MyConfig = StorageToConfig;
}
// We also update the `construct_runtime!`, but that is omitted for this example.
Here we have defined a struct StorageToConfig
which implements the Get<u32>
trait that is expected by pallet_2
. This struct tells the runtime when MyConfig::get()
is called, it should then call pallet_1::MyStorage::get()
which reads into runtime storage and gets that value.
So now, every call to T::MyConfig::get()
in pallet_2
will be a storage read, and will get whatever value is set in pallet_1
.
Let me know if this helps!