This project is built on Foundry development framework. ERC1967Proxy and UUPSUpgradeable is used from Openzeppelin.
This project demonstrates the UUPS proxy upgrade flow: separate storage (proxy) from logic (implementation), deploy & initialize the proxy, then replace the implementation later to add functionality without losing stored data.
BoxV1 -
A first-version smart contract that stores a single number and lets anyone read it. It’s initialized (owner set) after deployment rather than via a constructor, and only the owner can approve future upgrades. version() returns 1.
BoxV2.sol -
The upgraded version of the same contract: it keeps the same stored number but adds a setNumber function so the stored value can be changed. It keeps the same owner/upgrade control and reports version() as 2.
DeployBox (script) -
Automates deployment: it deploys the BoxV1 implementation and an on-chain proxy that points to it, then calls the proxy’s initialize so the owner is set. The proxy is what users interact with; the implementation contains the logic.
UpgradeBox (script) -
Automates an upgrade: it finds the most recently deployed proxy, deploys the new BoxV2 implementation, and tells the proxy to switch its logic to BoxV2 (so behavior changes while existing stored data remains). Only the owner can perform this upgrade.
DelegateCall -
This code shows how one contract can reuse another contract’s logic while keeping its own data using delegatecall. Contract A calls a function from contract B, but the changes are saved inside A, not B. The original caller and sent ETH are preserved. Because of this, both contracts must store data in the same order. This pattern is commonly used to upgrade contract behavior without losing stored data.