Two Modules with same Storage Name
See original GitHub issueIf two modules have the same name for their storage, only one item appears in the “chain state”.
For example:
"name": "substrate_module_template",
"prefix": "TemplateModule",
and
"name": "template",
"prefix": "TemplateModule",

Here is the full chain metadata:
{
"magicNumber": 1635018093,
"metadata": {
"MetadataV4": {
"modules": [
{
"name": "system",
"prefix": "System",
"storage": [
{
"name": "AccountNonce",
"modifier": "Default",
"type": {
"MapType": {
"hasher": "Blake2_256",
"key": "AccountId",
"value": "Index",
"isLinked": false
}
},
"fallback": "0x0000000000000000",
"documentation": [
" Extrinsics nonce for accounts."
]
},
{
"name": "ExtrinsicCount",
"modifier": "Optional",
"type": {
"PlainType": "u32"
},
"fallback": "0x00",
"documentation": [
" Total extrinsics count for the current block."
]
},
{
"name": "AllExtrinsicsLen",
"modifier": "Optional",
"type": {
"PlainType": "u32"
},
"fallback": "0x00",
"documentation": [
" Total length in bytes for all extrinsics put together, for the current block."
]
},
{
"name": "BlockHash",
"modifier": "Default",
"type": {
"MapType": {
"hasher": "Blake2_256",
"key": "BlockNumber",
"value": "Hash",
"isLinked": false
}
},
"fallback": "0x0000000000000000000000000000000000000000000000000000000000000000",
"documentation": [
" Map of block numbers to block hashes."
]
},
{
"name": "ExtrinsicData",
"modifier": "Default",
"type": {
"MapType": {
"hasher": "Blake2_256",
"key": "u32",
"value": "Bytes",
"isLinked": false
}
},
"fallback": "0x00",
"documentation": [
" Extrinsics data for the current block (maps extrinsic's index to its data)."
]
},
{
"name": "RandomSeed",
"modifier": "Default",
"type": {
"PlainType": "Hash"
},
"fallback": "0x0000000000000000000000000000000000000000000000000000000000000000",
"documentation": [
" Random seed of the current block."
]
},
{
"name": "Number",
"modifier": "Default",
"type": {
"PlainType": "BlockNumber"
},
"fallback": "0x0000000000000000",
"documentation": [
" The current block number being processed. Set by `execute_block`."
]
},
{
"name": "ParentHash",
"modifier": "Default",
"type": {
"PlainType": "Hash"
},
"fallback": "0x0000000000000000000000000000000000000000000000000000000000000000",
"documentation": [
" Hash of the previous block."
]
},
{
"name": "ExtrinsicsRoot",
"modifier": "Default",
"type": {
"PlainType": "Hash"
},
"fallback": "0x0000000000000000000000000000000000000000000000000000000000000000",
"documentation": [
" Extrinsics root of the current block, also part of the block header."
]
},
{
"name": "Digest",
"modifier": "Default",
"type": {
"PlainType": "Digest"
},
"fallback": "0x00",
"documentation": [
" Digest of the current block, also part of the block header."
]
},
{
"name": "Events",
"modifier": "Default",
"type": {
"PlainType": "Vec<EventRecord>"
},
"fallback": "0x00",
"documentation": [
" Events deposited for the current block."
]
}
],
"calls": null,
"events": [
{
"name": "ExtrinsicSuccess",
"args": [],
"documentation": [
" An extrinsic completed successfully."
]
},
{
"name": "ExtrinsicFailed",
"args": [],
"documentation": [
" An extrinsic failed."
]
}
]
},
{
"name": "timestamp",
"prefix": "Timestamp",
"storage": [
{
"name": "Now",
"modifier": "Default",
"type": {
"PlainType": "Moment"
},
"fallback": "0x0000000000000000",
"documentation": [
" Current time for the current block."
]
},
{
"name": "BlockPeriod",
"modifier": "Optional",
"type": {
"PlainType": "Moment"
},
"fallback": "0x00",
"documentation": [
" Old storage item provided for compatibility. Remove after all networks upgraded."
]
},
{
"name": "MinimumPeriod",
"modifier": "Default",
"type": {
"PlainType": "Moment"
},
"fallback": "0x0300000000000000",
"documentation": [
" The minimum period between blocks. Beware that this is different to the *expected* period",
" that the block production apparatus provides. Your chosen consensus system will generally",
" work with this to determine a sensible block time. e.g. For Aura, it will be double this",
" period on default settings."
]
},
{
"name": "DidUpdate",
"modifier": "Default",
"type": {
"PlainType": "bool"
},
"fallback": "0x00",
"documentation": [
" Did the timestamp get updated in this block?"
]
}
],
"calls": [
{
"name": "set",
"args": [
{
"name": "now",
"type": "Compact<Moment>"
}
],
"documentation": [
" Set the current time.",
"",
" This call should be invoked exactly once per block. It will panic at the finalization phase,",
" if this call hasn't been invoked by that time.",
"",
" The timestamp should be greater than the previous one by the amount specified by `minimum_period`.",
"",
" The dispatch origin for this call must be `Inherent`."
]
}
],
"events": null
},
{
"name": "consensus",
"prefix": "Consensus",
"storage": [
{
"name": "OriginalAuthorities",
"modifier": "Optional",
"type": {
"PlainType": "Vec<SessionKey>"
},
"fallback": "0x00",
"documentation": []
}
],
"calls": [
{
"name": "report_misbehavior",
"args": [
{
"name": "_report",
"type": "Bytes"
}
],
"documentation": [
" Report some misbehavior."
]
},
{
"name": "note_offline",
"args": [
{
"name": "offline",
"type": "InherentOfflineReport"
}
],
"documentation": [
" Note that the previous block's validator missed its opportunity to propose a block."
]
},
{
"name": "remark",
"args": [
{
"name": "_remark",
"type": "Bytes"
}
],
"documentation": [
" Make some on-chain remark."
]
},
{
"name": "set_heap_pages",
"args": [
{
"name": "pages",
"type": "u64"
}
],
"documentation": [
" Set the number of pages in the WebAssembly environment's heap."
]
},
{
"name": "set_code",
"args": [
{
"name": "new",
"type": "Bytes"
}
],
"documentation": [
" Set the new code."
]
},
{
"name": "set_storage",
"args": [
{
"name": "items",
"type": "Vec<KeyValue>"
}
],
"documentation": [
" Set some items of storage."
]
},
{
"name": "kill_storage",
"args": [
{
"name": "keys",
"type": "Vec<Key>"
}
],
"documentation": [
" Kill some items from storage."
]
}
],
"events": null
},
{
"name": "aura",
"prefix": "",
"storage": null,
"calls": null,
"events": null
},
{
"name": "indices",
"prefix": "Indices",
"storage": [
{
"name": "NextEnumSet",
"modifier": "Default",
"type": {
"PlainType": "AccountIndex"
},
"fallback": "0x00000000",
"documentation": [
" The next free enumeration set."
]
},
{
"name": "EnumSet",
"modifier": "Default",
"type": {
"MapType": {
"hasher": "Blake2_256",
"key": "AccountIndex",
"value": "Vec<AccountId>",
"isLinked": false
}
},
"fallback": "0x00",
"documentation": [
" The enumeration sets."
]
}
],
"calls": [],
"events": [
{
"name": "NewAccountIndex",
"args": [
"AccountId",
"AccountIndex"
],
"documentation": [
" A new account index was assigned.",
"",
" This event is not triggered when an existing index is reassigned",
" to another `AccountId`."
]
}
]
},
{
"name": "balances",
"prefix": "Balances",
"storage": [
{
"name": "TotalIssuance",
"modifier": "Default",
"type": {
"PlainType": "Balance"
},
"fallback": "0x00000000000000000000000000000000",
"documentation": [
" The total units issued in the system."
]
},
{
"name": "ExistentialDeposit",
"modifier": "Default",
"type": {
"PlainType": "Balance"
},
"fallback": "0x00000000000000000000000000000000",
"documentation": [
" The minimum amount required to keep an account open."
]
},
{
"name": "TransferFee",
"modifier": "Default",
"type": {
"PlainType": "Balance"
},
"fallback": "0x00000000000000000000000000000000",
"documentation": [
" The fee required to make a transfer."
]
},
{
"name": "CreationFee",
"modifier": "Default",
"type": {
"PlainType": "Balance"
},
"fallback": "0x00000000000000000000000000000000",
"documentation": [
" The fee required to create an account."
]
},
{
"name": "TransactionBaseFee",
"modifier": "Default",
"type": {
"PlainType": "Balance"
},
"fallback": "0x00000000000000000000000000000000",
"documentation": [
" The fee to be paid for making a transaction; the base."
]
},
{
"name": "TransactionByteFee",
"modifier": "Default",
"type": {
"PlainType": "Balance"
},
"fallback": "0x00000000000000000000000000000000",
"documentation": [
" The fee to be paid for making a transaction; the per-byte portion."
]
},
{
"name": "Vesting",
"modifier": "Optional",
"type": {
"MapType": {
"hasher": "Blake2_256",
"key": "AccountId",
"value": "VestingSchedule",
"isLinked": false
}
},
"fallback": "0x00",
"documentation": [
" Information regarding the vesting of a given account."
]
},
{
"name": "FreeBalance",
"modifier": "Default",
"type": {
"MapType": {
"hasher": "Blake2_256",
"key": "AccountId",
"value": "Balance",
"isLinked": false
}
},
"fallback": "0x00000000000000000000000000000000",
"documentation": [
" The 'free' balance of a given account.",
"",
" This is the only balance that matters in terms of most operations on tokens. It",
" alone is used to determine the balance when in the contract execution environment. When this",
" balance falls below the value of `ExistentialDeposit`, then the 'current account' is",
" deleted: specifically `FreeBalance`. Further, the `OnFreeBalanceZero` callback",
" is invoked, giving a chance to external modules to clean up data associated with",
" the deleted account.",
"",
" `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets",
" collapsed to zero if it ever becomes less than `ExistentialDeposit`."
]
},
{
"name": "ReservedBalance",
"modifier": "Default",
"type": {
"MapType": {
"hasher": "Blake2_256",
"key": "AccountId",
"value": "Balance",
"isLinked": false
}
},
"fallback": "0x00000000000000000000000000000000",
"documentation": [
" The amount of the balance of a given account that is externally reserved; this can still get",
" slashed, but gets slashed last of all.",
"",
" This balance is a 'reserve' balance that other subsystems use in order to set aside tokens",
" that are still 'owned' by the account holder, but which are suspendable.",
"",
" When this balance falls below the value of `ExistentialDeposit`, then this 'reserve account'",
" is deleted: specifically, `ReservedBalance`.",
"",
" `system::AccountNonce` is also deleted if `FreeBalance` is also zero (it also gets",
" collapsed to zero if it ever becomes less than `ExistentialDeposit`.)"
]
},
{
"name": "Locks",
"modifier": "Default",
"type": {
"MapType": {
"hasher": "Blake2_256",
"key": "AccountId",
"value": "Vec<BalanceLock>",
"isLinked": false
}
},
"fallback": "0x00",
"documentation": [
" Any liquidity locks on some account balances."
]
}
],
"calls": [
{
"name": "transfer",
"args": [
{
"name": "dest",
"type": "Address"
},
{
"name": "value",
"type": "Compact<Balance>"
}
],
"documentation": [
" Transfer some liquid free balance to another account.",
"",
" `transfer` will set the `FreeBalance` of the sender and receiver.",
" It will decrease the total issuance of the system by the `TransferFee`.",
" If the sender's account is below the existential deposit as a result",
" of the transfer, the account will be reaped.",
"",
" The dispatch origin for this call must be `Signed` by the transactor."
]
},
{
"name": "set_balance",
"args": [
{
"name": "who",
"type": "Address"
},
{
"name": "free",
"type": "Compact<Balance>"
},
{
"name": "reserved",
"type": "Compact<Balance>"
}
],
"documentation": [
" Set the balances of a given account.",
"",
" This will alter `FreeBalance` and `ReservedBalance` in storage.",
" If the new free or reserved balance is below the existential deposit,",
" it will also decrease the total issuance of the system (`TotalIssuance`)",
" and reset the account nonce (`system::AccountNonce`).",
"",
" The dispatch origin for this call is `root`."
]
}
],
"events": [
{
"name": "NewAccount",
"args": [
"AccountId",
"Balance"
],
"documentation": [
" A new account was created."
]
},
{
"name": "ReapedAccount",
"args": [
"AccountId"
],
"documentation": [
" An account was reaped."
]
},
{
"name": "Transfer",
"args": [
"AccountId",
"AccountId",
"Balance",
"Balance"
],
"documentation": [
" Transfer succeeded (from, to, value, fees)."
]
}
]
},
{
"name": "sudo",
"prefix": "Sudo",
"storage": [
{
"name": "Key",
"modifier": "Default",
"type": {
"PlainType": "AccountId"
},
"fallback": "0x0000000000000000000000000000000000000000000000000000000000000000",
"documentation": [
" The `AccountId` of the sudo key."
]
}
],
"calls": [
{
"name": "sudo",
"args": [
{
"name": "proposal",
"type": "Proposal"
}
],
"documentation": [
" Authenticates the sudo key and dispatches a function call with `Root` origin.",
"",
" The dispatch origin for this call must be _Signed_."
]
},
{
"name": "set_key",
"args": [
{
"name": "new",
"type": "Address"
}
],
"documentation": [
" Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo key.",
"",
" The dispatch origin for this call must be _Signed_."
]
}
],
"events": [
{
"name": "Sudid",
"args": [
"bool"
],
"documentation": [
" A sudo just took place."
]
},
{
"name": "KeyChanged",
"args": [
"AccountId"
],
"documentation": [
" The sudoer just switched identity; the old key is supplied."
]
}
]
},
{
"name": "template",
"prefix": "TemplateModule",
"storage": [
{
"name": "Something",
"modifier": "Optional",
"type": {
"PlainType": "u32"
},
"fallback": "0x00",
"documentation": []
}
],
"calls": [
{
"name": "do_something",
"args": [
{
"name": "something",
"type": "u32"
}
],
"documentation": []
}
],
"events": [
{
"name": "SomethingStored",
"args": [
"u32",
"AccountId"
],
"documentation": []
}
]
},
{
"name": "substrate_module_template",
"prefix": "TemplateModule",
"storage": [
{
"name": "Something",
"modifier": "Optional",
"type": {
"PlainType": "u32"
},
"fallback": "0x00",
"documentation": []
}
],
"calls": [
{
"name": "do_something",
"args": [
{
"name": "something",
"type": "u32"
}
],
"documentation": []
}
],
"events": [
{
"name": "SomethingStored",
"args": [
"u32",
"AccountId"
],
"documentation": []
}
]
}
]
}
}
}
Issue Analytics
- State:
- Created 4 years ago
- Comments:12 (11 by maintainers)
Top Results From Across the Web
python: Two modules and classes with the same name under ...
You want to import the User modules in the package __init__.py files to make them available as attributes. So in both Helper/__init_.py and ......
Read more >How to import two modules with same function name in Python
Let me create another module with two functions and the names the functions are: Add and Divide. I call this module as prog2.py...
Read more >How to access/modify the same instance of a class across ...
I am struggling to access/modify the same instance of a class across multiple modules. Which software design pattern should I use to have...
Read more >about Modules - PowerShell | Microsoft Learn
Explains how to install, import, and use PowerShell modules. ... includes commands of the same type with the same name, such as two...
Read more >Placement of modules in LPA - IBM
When frequently-used modules are placed in LPA, all address spaces share the same copy, and central storage usage tends to be reduced.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Pick same name: -> should be forbidden. Pick same prefix: -> no problem.
Not sure what happens now if you create 2 modules with the same name, but imo that should be forbidden in substrate.
Ok, the issue is - what is valid? The first item of a specific storage? The second? Which rules apply? As it stands the API needs to make assumptions as to which to take - it currently already makes an assumption - the second module as a whole is valid, overriding the first.
So certainly, different assumptions can be made - but it is just that, assumptions of developer intent. Since you can override calls, entries, anything - which is valid in which cases. (Since even at the base of substrate there are conflicts, e.g. storage due to
hash(<ModuleName> <EntryName>)
)It is not a UI thing, the UI only displays what the API provides it.