[Ethereum] Pros and Cons of smart contract upgradable patterns

contract-designcontract-developmentdelegatecallopenzeppelinopenzeppelin-sdk

There have been quite many arguments around how to achieve smart contract updates like Upgradeable smart contracts.
I feel Proxycontract with Delegate-call is currently the most famous one. But aside from that, there are also other patterns.

So, I list the summary of some of the most known patterns and compare each pattern.

1. Delegatecall-based proxies pattern
The most known one. also led by OpenZeppelin which distributes great tools and development kits. the proxy pattern splits a contract in two: one contract holding the logic and a proxy contract holding the data. In this pattern, the proxy contract calls the logic contract with delegatecall. Data returned by the logic contract will be stored in the proxy contract.

  • Pros: Most flexible that developer team can alter the contract completely. This enables unpredictable bug fix in the future and smooth update without any needs of user participation.
  • Cons: As mentioned in the trailofbits blog This pattern is most complicated that may cause serious damage to contracts. Implementing this requires a deep understanding of EVM. Thanks to OpenZeppelin, they check those complicated tasks.
    But, it's doubtful that a fully upgradable contract remains "Decentralized".

2. Data separation pattern

Also introduced in trailofbits blog.
This pattern also separates data and logic. But, they don't use delegate-call, so an upgrade can be achieved by calling the new logic contract which stores data on the same contract.

  • Pros: Doesn't use complicated delegate-call function and doesn't require a deep understanding of EVM and can upgrade flexibly.
  • Cons: it still makes contract complicate and also it's doubtful that fully upgradable contract remains "Decentralized".

3. Registery pattern
This pattern was introduced in Consensys blog

  • Pros: Simple, easy to audit.
  • Cons: You will need to think carefully about how to deal with the contract data when you replace the contract

4. Updates through functions
This pattern is not standardized. Each project considers their upgradability before deployment and makes some of the contract(e,g, variables like the owner) upgradable through functions. I think Compound finance is using this pattern.

  • Pros: Simple, easy to audit, can reduce vulnerability by minimalizing upgradability.
  • Cons: Cannot deal with unexpected errors or bugs.

Thanks for reading so far.
So, my questions are

  • If there is something wrong with my explanations, please give me feedback
  • Do you know any of active projects using one of those patterns?
  • Do you think of any other pros and cons, or other patterns?

Best Answer

OpenZeppelin uses the "unstructured storage" proxy pattern.
See the documentation for details: https://docs.openzeppelin.com/sdk/2.5/pattern

OpenZeppelin in the proxy patterns blog post (https://blog.openzeppelin.com/proxy-patterns/) explored three proxy pattern options:

  1. Inherited Storage
  2. Eternal Storage
  3. Unstructured Storage

An upgradeable contract can be "decentralized", depending on the governance used.
The upgrade mechanism for OpenZeppelin SDK upgradeable smart contracts can be controlled by any type of governance, be it a multi-signature wallet, a simple address or a complex DAO.
The documentation shows using a multi-signature wallet to manage contract upgrades: https://docs.openzeppelin.com/sdk/2.5/upgrades-governance

Example project
Coinbase and Circle’s USDC uses ZeppelinOS (now called OpenZeppelin SDK) proxy pattern: https://github.com/centrehq/centre-tokens


If you have questions on using OpenZeppelin you can ask in the Community Forum: https://forum.openzeppelin.com/

Disclosure: I am the Community Manager at OpenZeppelin

Related Topic