
OpenZeppelin provides two distinct types ofcontracts: standard contracts and upgradeable contracts. Understanding thedifference between these two is from utmost importance.
The OpenZeppelin contracts repositorycontains standard smart contracts designed to be inherited by your owncontracts. These contracts cover a wide range of common use cases, includingtoken creation (ERC20, ERC721), security features (ReentrancyGuard, Ownable),and access control mechanisms (Roles, AccessControl). The idea is to providedevelopers with a solid foundation, allowing them to focus on building theunique aspects of their project rather than reinventing the wheel.
On the other hand, OpenZeppelin upgradeablecontracts are specifically designed for use with proxy contracts. Thesecontracts cover to the need for upgradability in smart contracts. Upgradabilityis crucial for fixing bugs and enhancing contract functionality over timewithout losing the state or having to deploy a new contract. The upgradeablecontracts follow a different architectural pattern, necessitating a distinctapproach to initialization and state management.
At first glance, it might seem weird tohave two separate repositories for standard and upgradeable contracts. However,this separation addresses specific technical necessities associated withupgradeable smart contracts:
Initializers over Constructors
Upgradeable Contracts Need Initializers:Unlike traditional smart contracts that use constructors to initialize contractstate, upgradeable contracts must use initializer functions. This is becausethe proxy pattern used for upgradeability does not support the direct use ofconstructors. Initializers ensure that state variables are set correctly whenthe contract is first used, rather than when it's deployed.
Storage Collision Prevention
Storage Layout and the gap[] Variable: Upgradeablecontracts must be carefully designed to prevent storage collisions betweendifferent contract versions. This is where the gap[] variable comes into play.By including a reserved space in the contract's storage layout, developers canadd new variables in future versions without risking collisions with existingones. This technique ensures that the contract's state remains consistent andpredictable across upgrades.
Understanding the difference betweenOpenZeppelin's standard and upgradeable contracts is essential for Soliditydevelopers. While both are designed to be inherited and provide a secure,community-vetted foundation for smart contract development, they cater todistinct needs—standard contracts for a solid, unchanging foundation, andupgradeable contracts for flexibility and evolution over time.