It seems like the Upgrade pattern takes some pages out of this book here - what are your folk’s thoughts on this EIP for “transparent contracts”?
OpenZeppelin SDK uses the “unstructured storage” proxy pattern for upgradeability.
OpenZeppelin Labs included a number of experiments with upgradeability, one of which was vtable.
As per the draft, the inspiration for ERC1538 was OpenZeppelin Labs upgradeability_with_vtable.
The draft has comments from some of the OpenZeppelin team.
I suggest reading this comment in particular:
Hey @mudgen! Santiago from ZeppelinOS here. Just got the time to review the proposal. Looks pretty solid, and thanks a lot for picking up the vtable experiment and pushing it forward!!
FWIW, for the current version of ZeppelinOS, we decided to go with a more simple approach (a proxy that delegates to a single address) since it removes a few complications when coding upgradeable contracts (such as having to coordinate storage, or not being able to share internal functions). But we do envision supporting other upgradeability patterns in the future, and it’s nice to see the community pushing for alternatives
An improvement I’d strongly suggest is using unstructured storage for storing the contract owner and the delegates. This removes the need for any implementation contract to extend from a
UpgradeStoragebase contract. From our experience, the fewer requirements you impose on your users, the better the chances for adoption.
As for allowing users to decide which version of each function they want to call (which was mentioned in the last comments), I’m not very sold on the idea to be honest: I feel it may open the door to certain incompatible calls in a wider system. I’d keep it simple for the time being, until we have a better understanding of this pattern.
Also, I’m not sure this implementation does prevent the selector clashing exploit, as was mentioned before. Registering a delegate which has a different function name but the same function identifier as
updateContractmay end up in accidentally removing upgradeability. I’d be particularly careful in protecting that function.
Last but not least, we have a clash on the naming itself! We are pushing for the transparent proxy naming from ZeppelinOS to describe proxies that are indistinguishable from the implementation for anyone but their owner. You can read more about that here, and we’ll be probably releasing a blogpost soon. I’d suggest renaming this proposal to something that better describes its main selling points, which to me are being able to upgrade functions individually, and having the proxy dispatch to the correct implementation. I personally like vtable , but that’s just because I came up with that name and are somewhat attached to it
I moved to #general as assume this is more of a discussion.
I also asked Nick Mudgen via Twitter if he is still working on this EIP:
I have used EIP 1538 in production and it has been great.
Here is my reply to Santiago’s comments:
@spalladino Thank you so much for your feedback here. I really appreciate and like the work you and your team are doing with upgradeable contracts.
Yes, I very much like the unstructured storage approach and I think it is better. How variable storage and ownership is done is not part of the standard but I think people are likely to follow the example given. So I’ll update the example to use the unstructured storage approach. Thanks for pointing this out.
Update: To keep the example given simple I decided to keep it how it is.
Yes, I agree with your thoughts on the versioning. One thing that can happen is that a bug is written into a function. When the contract is upgraded to fix the bug you never want users to be able to call the buggy version of the function.
You are right that the standard itself does not prevent selector clashing. But because the function signatures are passed into the
updateContractfunction it is possible to prevent selector clashes within the implementation of
updateContract. I will add a note about this to the standard.
EIP-1538 is solid. I have implemented it for Caesar’s Triumph (previously CryptoRome), and am now using it for another game we are releasing soon. No issues at all using the inherited storage pattern. I did build a lightweight UI to handle configuration management i.e. allows me to easily perform function upgrades and also pulls all functions and displays which contract address each one is implemented in.
Welcome to the community
Feel free to share links to repositories for your examples if you are able to.
I’ve got an implementation here: https://github.com/iExecBlockchainComputing/iexec-solidity/tree/master/contracts/ERC1538
It uses this datastructure: https://github.com/Amxx/SolStruct