-
Notifications
You must be signed in to change notification settings - Fork 428
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
Define a Standard for Proxy Storage Variables #1680
Comments
What's the status of this issue? Is it still planned to implement? |
I have a very strong opinion on this. Please use the exact storage slots as defined in |
AFAIK we are using a different hash function across ink! (blake2x256). Secondly, using storage slots implies using If we have a strong requirement to have matching storage slots with solidity, we can surely propose a PSP |
How does the this matter (also, both are 32 bytes)? The pre-image for the storage slots in EIP-1967 isn't known anyways (on purpose).
ink! contracts do potentially have storage collisions when using
Technically, I don't see a strong requirement for picking any particular slot. And given this is true, picking different ones would just set us up for bad interop with Solidity. |
The hash is derived by running the hash function on the known preimage and then subtracting 1. We can either take hash from EIP directly or derive our own using blake2x256.
We don't have a compiler. We can achieve this only using lints. If we get to hard-code those slots into ink! storage somehow, that would imply that every new contract would be deployed with these 3 empty proxy slots that are also wrapped into |
Ultimately, you can't force anyone to store anything specific in any storage slot. At least not on the contract source level. But if you define a standard, yes you are asking contract devs to adhere to that. And for upgradable contracts and proxy implementations, not using all manual keys is a bad idea anyways isn't it? |
The only way I see we can ensure that proxy storage slots are not used by anything else is to "silently" define those storage fields in the contract storage definition, and hide them until the user uses them. Ultimately, this is what I mentioned above is that every future contract deployed will have these well-known storage keys for proxy fields that may and may not have a value. This is essentially a breaking change and some thoughts need to be put into the API. If we just introduce the PSP defining without safety guarantees, then it looks kind of pointless. |
I assume we are discussing the following section of the OZ report https://blog.openzeppelin.com/security-review-ink-cargo-contract My initial thought is that this (predefined storage slots for proxy storage) is not something that should be baked into the language itself, and that such standards are defined and adopted "organically", e.g. with the existing PSP standards from openbrush. Further, the Rationale for https://eips.ethereum.org/EIPS/eip-1967 states that:
We now have built in protection against selector clashing attacks: #1708 so this is not an issue, the public fallback function can be called directly to force the upgrade.
A less opinionated way to do it, to allow standards to be developed, would be to similarly define a range of storage keys we guarantee will never be written to by the derived set_code_hashIdeally we would promote the usage of |
I think, best would be to have the |
I agree. The implementer of the Proxy contract is responsible for using a separate storage cell to avoid overlapping. As an example, OpenBrush already uses a separate storage cell.
I don't think it is possible to implement because any public API provided by ink! can invalidate/corrupt the storage. ink! generates code that works with the storage on the user's side, so it uses a public API. Anyone can easily reuse these public functions in Plus, the safest way is to control it during runtime -> it affects the performance.
Usually, this kind of functionality is hidden or uses other names, but yeah, we can ask users to use pre-defined names. But it already sounds like some standardization=) Maybe we can have The problem with this solution is that it will not work in the case of the Diamond standard. But we can have one command for storage migration(between two contracts) and another like |
Agreed, then we can simply require some arguments e.g. |
Overall, I agree that
I still believe we need to address this point for future purposes. Perhaps reserve some chunk of keys for "system" purposes, have some range of keys which are never automatically allocated. |
It is possible that such a standard could still be proposed/developed and adopted, As @xgreenx mentioned there is something like this in But this should not be baked into the language itself, given that we have the built-in upgradeability mechanism already which achieves most of what we want. |
In the Ethereum world there is EIP-1967 which defines a well-known set of storage
slots used to represent key variables in the Proxy pattern, such as the
admin
andimplementation
.It would be nice to have something similar for ink!.
The EIP-1967 approach uses storage slots that are known to not be used by the Solidity
compiler. I don't think we can make the same guarantees with
pallet-contracts
orSubstrate, so we'll probably need to find a different approach to this.
The text was updated successfully, but these errors were encountered: