VIP: Global Storage Namespace
Simple Summary
Allow expressing a global storage namespace as a top-level pragma that modifies the base storage slot from 0
Motivation
For some modular contract systems (Diamond Standard, Purse) that allows arbitrary storage access to a shared account it is useful to be able to specify "shared storage namespaces" (a concept also captured in ERC 7201).
By being able to set this as a top-level pragma, this allows us to support this feature without any language-level changes. Further, because it is part of the canonical file, it is easy to verify when publishing.
This is similar to https://github.com/vyperlang/vyper/issues/3556, but global instead of per-storage variable
Specification
You would specify this as a top-level pragma statement using a string. If the string is prefixed with 0x it is interpreted as a hex bytes value. If not, it is first hashed per EIP-7201 semantics via the definition erc7201(id: string) = keccak256(keccak256(id) - 1) & ~0xff
# pragma storage-namespace purse.accessories.sponsor
a: address # located @ 94740a2cbfe678b9f11c58528f63f25c3b97a5b3d7a45a9ae93a842e0af605b2
NOTE: Check my math on 94740a2cbfe678b9f11c58528f63f25c3b97a5b3d7a45a9ae93a842e0af605b2, I used:
>>> from eth_utils import keccak, to_bytes, to_int
>>> keccak(to_bytes((to_int(keccak(b"purse.accessories.sponsor")) - 1) & ~to_int(to_bytes(0xff) + b"\x00" * 31))).hex()
'94740a2cbfe678b9f11c58528f63f25c3b97a5b3d7a45a9ae93a842e0af605b2'
Backwards Compatibility
Unsure how this works with modules. Otherwise, there are no backwards compatibility issues.
Dependencies
N/A
References
VIP https://github.com/vyperlang/vyper/issues/3556 https://eips.ethereum.org/EIPS/eip-7201
Copyright
Copyright and related rights waived via CC0
Unsure how this works with modules. Otherwise, there are no backwards compatibility issues.
I would probably have the top level module defining the storage layout for its submodules, the rationale behind it is:
- consistency with solidity
layout atbehavior (see docs).The storage layout can only be specified for the topmost contract of an inheritance tree, and affects locations of all the storage variables in all the contracts in that tree
- Vyper focuses on WYSIWYG, one should not have to read the module content to use it safely
- I don't see a good usecase for a library writer to have an independent storage namespace (there might be some obscure usecase with proxies tho).
Unsure how this works with modules. Otherwise, there are no backwards compatibility issues.
I would probably have the top level module defining the storage layout for its submodules
I agree with that. Practically speaking, since it's a pragma we can just ignore the pragmas of imported modules? (I think we already do)
Another riff on this idea https://eips.ethereum.org/EIPS/eip-8042