Back to Lessons
Lesson 17

Upgradeable ERC-20: Proxies & Storage

+25EFFORT
5 sections
security()
01
text

Deployed bytecode is immutable, so to fix bugs or add features teams use the PROXY pattern. A lightweight proxy contract holds all the storage (balances, allowances) and delegatecalls a separate implementation contract for the logic. Upgrading means pointing the proxy at a new implementation — the state lives in the proxy and is preserved across upgrades.

02
code
solidity
1// Upgradeable contracts replace the constructor with an initializer:
2contract MyToken is ERC20Upgradeable, OwnableUpgradeable, UUPSUpgradeable {
3 function initialize() public initializer {
4 __ERC20_init("MyToken", "MTK");
5 __Ownable_init(msg.sender);
6 __UUPSUpgradeable_init();
7 }
8 // UUPS: the upgrade authorization lives in the implementation
9 function _authorizeUpgrade(address newImpl) internal override onlyOwner {}
10}
03
text

Two rules dominate. (1) No constructors: constructor code runs in the implementation's own context, not the proxy's storage, so initialization must happen in an initializer() guarded by the initializer modifier (run-once). (2) Append-only storage: because delegatecall uses the proxy's storage slots, the implementation's variable layout must never be reordered or have variables inserted — doing so corrupts existing state. OZ reserves room with a storage gap (uint256[50] __gap).

04
note
Key Insight

Trust implication: 'upgradeable' means 'whoever holds the upgrade key can rewrite the token's rules later' — including mint logic or blocklists. That key is power over every holder, so it should sit behind a timelock and/or multisig, never a single hot wallet. Always check who can upgrade a token before trusting it.

05
code
solidity
1// Transparent proxy vs UUPS:
2// - Transparent: upgrade logic lives in the proxy/admin (more bytecode)
3// - UUPS: upgrade logic lives in the implementation via
4// _authorizeUpgrade (cheaper, but you MUST keep it in every version
5// or the contract becomes permanently un-upgradeable)
Complete

Connect your wallet to mark this lesson as complete

Earn 25 EFFORT tokens