Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update EIP-7201: Explain possibility to use different formulas #7760

Merged
merged 8 commits into from Sep 22, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 9 additions & 5 deletions EIPS/eip-7201.md
Expand Up @@ -24,13 +24,15 @@ These storage usage patterns are invisible to the Solidity and Vyper compilers b

## Specification

A _namespace_ consists of a set of ordered variables, some of which may be dynamic arrays or mappings, with its values laid out following the same rules as the default storage layout but rooted in some location that is not necessarily slot 0. It should be implemented as a struct.
A _namespace_ consists of a set of ordered variables, some of which may be dynamic arrays or mappings, with its values laid out following the same rules as the default storage layout but rooted in some location that is not necessarily slot 0. A contract using namespaces to organize storage is said to use _namespaced storage_.

A _namespace id_ is a string that uniquely identifies a namespace in a contract. It should not contain any whitespace characters.
A _namespace id_ is a string that identifies a namespace in a contract. It should not contain any whitespace characters.

The storage location for a namespace is defined as `ns_loc(id: string) = keccak256(keccak256(id) - 1) & ~0xff`.
A namespace in a contract should be implemented as a struct type. These structs should be annotated with the NatSpec tag `@custom:storage-location <FORMULA_ID>:<NAMESPACE_ID>`, where `<FORMULA_ID>` identifies a formula used to compute the storage location where the namespace is rooted, based on the namespace id. _(Note: The Solidity compiler includes this annotation in the AST since v0.8.20, so this is recommended as the minimum compiler version when using this pattern.)_ Structs with this annotation found outside of contracts are not considered to be namespaces for any contract in the source code.

A Solidity contract using namespaced storage can annotate a struct with the NatSpec tag `@custom:storage-location erc7201:<NAMESPACE_ID>` to identify it as a namespace with id `<NAMESPACE_ID>`. _(Note: The Solidity compiler includes this annotation in the AST since v0.8.20, so this is recommended as the minimum compiler version when using this pattern.)_ Structs with this annotation found outside of contracts are not considered to be namespaces for any contract in the source code.
The formula identified by `erc7201` is defined as `erc7201(id: string) = keccak256(keccak256(id) - 1) & ~0xff`. In Solidity, this corresponds to the expression `keccak256(abi.encode(uint256(keccak256(id)) - 1)) & ~bytes32(uint256(0xff))`. When using this formula the annotation becomes `@custom:storage-location erc7201:<NAMESPACE_ID>`. For example, `@custom:storage-location erc7201:foobar` annotates a namespace with id `"foobar"` rooted at `erc7201("foobar")`.

Future EIPs may define new formulas with unique formula identifiers. It is recommended to follow the convention set in this EIP and use an identifier of the format `erc1234`.

## Rationale

Expand Down Expand Up @@ -82,7 +84,9 @@ contract Example {

## Security Considerations

Needs discussion.
Namespaces should avoid collisions with other namespaces or with standard Solidity or Vyper storage layout. The formula defined in this ERC guarantees this property for arbitrary namespace ids under the assumption of keccak256 collision resistance, as discussed in Rationale.

`@custom:storage-location` is a NatSpec annotation that current compilers don't enforce any rules for or ascribe any meaning to. The contract developer is responsible for implementing the pattern and using the namespace as claimed in the annotation.

## Copyright

Expand Down