问题
I have seen the Substrate Tutorial on creating crates of individual Substrate Runtime modules here in order to re-use the functionality, but I wondered if there is a way for one custom module to access the storage or functions from another custom module?
Something along these lines:
/// In ModuleA
pub type IndexType = u64;
decl_storage! {
trait Store for Module<T: Trait> as ModuleA {
pub MyIndexCount get(my_index_count): Option<IndexType>;
}
}
And then inside ModuleB - what do I need to do to use/include the functionality of ModuleA, and how do I call it?
/// In ModuleB
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn deposit_event<T>() = default;
pub fn edit_index(origin) -> Result {
let sender = ensure_signed(origin)?;
// --->>>> I want to read some storage from ModuleA whilst inside ModuleB
let c: IndexType = ReadStorageFromModuleA >>> my_index_count().ok_or("Storage Read Error: cannot get index")?;
// change storage in ModuleA from ModuleB
WriteToStorageInModuleA <MyIndexCount<T>>::put(&c + 1);
Ok(())
}
}
}
回答1:
If you are building a module (module2) which has a direct dependency on another module (module1), you must inherit module1's trait in module2's trait definition:
pub trait Trait: module1::Trait {
...
}
To access public storage items from module1 in module2, you need to do the following:
- Import the appropriate storage trait to access the storage API:
StorageValue
,StorageMap
, etc... - Access the public storage through module1's storage type
<module1::Something<T>>::get()
<module1::Something<T>>::put()
- etc...
To access other public functions from module 1 in module 2, you need to use the Module
type:
<module1::Module<T>>::public_function();
Here is a simple example of two modules interacting in this way:
module1.rs
Note that all the things in this module are marked public (
pub
)
use support::{decl_module, decl_storage, StorageValue};
pub trait Trait: system::Trait {}
decl_storage! {
trait Store for Module<T: Trait> as TemplateModule {
pub Something: u32;
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
}
}
impl<T: Trait> Module<T> {
pub fn get_value() -> u32 {
<Something<T>>::get()
}
}
module2.rs
use support::{decl_module, decl_event, StorageValue, dispatch::Result};
use system::ensure_signed;
use crate::module1;
pub trait Trait: module1::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
decl_module! {
/// The module declaration.
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn deposit_event<T>() = default;
pub fn get_value_directly(origin) -> Result {
let who = ensure_signed(origin)?;
let value = <module1::Something<T>>::get();
Self::deposit_event(RawEvent::ValueIs(value, who));
Ok(())
}
pub fn set_value_directly(origin, value: u32) -> Result {
let _ = ensure_signed(origin)?;
<module1::Something<T>>::put(value);
Ok(())
}
pub fn get_value_public_function(origin) -> Result {
let who = ensure_signed(origin)?;
let value = <module1::Module<T>>::get_value();
Self::deposit_event(RawEvent::ValueIs(value, who));
Ok(())
}
}
}
decl_event!(
pub enum Event<T> where <T as system::Trait>::AccountId {
ValueIs(u32, AccountId),
}
);
来源:https://stackoverflow.com/questions/56902167/in-substrate-is-there-a-way-to-use-storage-and-functions-from-one-custom-module