0
# Proxy Patterns
1
2
Comprehensive upgradeability patterns enabling contract logic updates while preserving state and addresses, including transparent proxies, UUPS, beacon patterns, and minimal clones.
3
4
## Capabilities
5
6
### ERC1967 Proxy Standard
7
8
Core proxy implementation using standardized storage slots to prevent storage collisions in upgradeable contracts.
9
10
```solidity { .api }
11
/**
12
* @dev Utilities for ERC1967 proxy pattern with standardized storage slots
13
*/
14
library ERC1967Utils {
15
/**
16
* @dev Returns the current implementation address from storage
17
*/
18
function getImplementation() internal view returns (address);
19
20
/**
21
* @dev Upgrades implementation and calls new contract with data
22
*/
23
function upgradeToAndCall(address newImplementation, bytes memory data) internal;
24
25
/**
26
* @dev Returns the current admin address from storage
27
*/
28
function getAdmin() internal view returns (address);
29
30
/**
31
* @dev Changes the admin of the proxy
32
*/
33
function changeAdmin(address newAdmin) internal;
34
35
/**
36
* @dev Returns the current beacon address from storage
37
*/
38
function getBeacon() internal view returns (address);
39
40
/**
41
* @dev Upgrades beacon and calls new implementation with data
42
*/
43
function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal;
44
}
45
46
/**
47
* @dev Basic ERC1967 proxy with upgradeable implementation storage
48
*/
49
contract ERC1967Proxy is Proxy {
50
/**
51
* @dev Initializes proxy with implementation and optional setup call
52
*/
53
constructor(address implementation, bytes memory _data);
54
55
/**
56
* @dev Returns current implementation address from ERC1967 storage slot
57
*/
58
function _implementation() internal view virtual override returns (address);
59
}
60
```
61
62
### Transparent Upgradeable Proxy
63
64
Admin-controlled upgrade pattern that prevents function selector clashing between proxy and implementation.
65
66
```solidity { .api }
67
/**
68
* @dev Transparent proxy with separate admin for upgrade control
69
*/
70
contract TransparentUpgradeableProxy is ERC1967Proxy {
71
/**
72
* @dev Initializes transparent proxy with logic, admin, and setup data
73
*/
74
constructor(address _logic, address initialOwner, bytes memory _data);
75
76
/**
77
* @dev Fallback implementing transparent pattern (admin vs user calls)
78
*/
79
fallback() external payable virtual override;
80
}
81
82
/**
83
* @dev Admin contract for managing transparent upgradeable proxies
84
*/
85
contract ProxyAdmin is Ownable {
86
/**
87
* @dev Current interface version for upgrade compatibility
88
*/
89
string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
90
91
/**
92
* @dev Upgrades proxy to new implementation with initialization call
93
*/
94
function upgradeAndCall(
95
ITransparentUpgradeableProxy proxy,
96
address implementation,
97
bytes memory data
98
) public payable virtual onlyOwner;
99
}
100
```
101
102
**Usage Example:**
103
104
```solidity
105
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
106
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
107
108
// Deploy implementation
109
MyContract implementation = new MyContract();
110
111
// Deploy proxy admin
112
ProxyAdmin admin = new ProxyAdmin(msg.sender);
113
114
// Deploy transparent proxy
115
bytes memory initData = abi.encodeCall(MyContract.initialize, (param1, param2));
116
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
117
address(implementation),
118
address(admin),
119
initData
120
);
121
122
// Later upgrade through admin
123
MyContractV2 newImplementation = new MyContractV2();
124
admin.upgradeAndCall(
125
ITransparentUpgradeableProxy(address(proxy)),
126
address(newImplementation),
127
""
128
);
129
```
130
131
### UUPS (Universal Upgradeable Proxy Standard)
132
133
Implementation-controlled upgrade pattern where the logic contract manages its own upgrades for gas efficiency.
134
135
```solidity { .api }
136
/**
137
* @dev UUPS upgradeable implementation with self-managed upgrades
138
*/
139
abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Utils {
140
/**
141
* @dev Upgrades implementation and calls new contract with data
142
*/
143
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy;
144
145
/**
146
* @dev Returns ERC1822 compatible UUID for this implementation
147
*/
148
function proxiableUUID() external view virtual notDelegated returns (bytes32);
149
150
/**
151
* @dev Authorization function for upgrades (must be implemented by inheriting contract)
152
*/
153
function _authorizeUpgrade(address newImplementation) internal virtual;
154
155
/**
156
* @dev Modifier ensuring execution only through proxy delegatecall
157
*/
158
modifier onlyProxy();
159
160
/**
161
* @dev Modifier ensuring execution only in implementation context
162
*/
163
modifier notDelegated();
164
}
165
```
166
167
**Usage Example:**
168
169
```solidity
170
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
171
import "@openzeppelin/contracts/access/Ownable.sol";
172
173
contract MyUpgradeableContract is UUPSUpgradeable, OwnableUpgradeable {
174
function initialize(address owner) public initializer {
175
__Ownable_init(owner);
176
__UUPSUpgradeable_init();
177
}
178
179
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
180
}
181
182
// Deploy with ERC1967Proxy
183
MyUpgradeableContract implementation = new MyUpgradeableContract();
184
bytes memory initData = abi.encodeCall(MyUpgradeableContract.initialize, (owner));
185
ERC1967Proxy proxy = new ERC1967Proxy(address(implementation), initData);
186
187
// Upgrade through the proxy
188
MyUpgradeableContract proxyAsContract = MyUpgradeableContract(address(proxy));
189
MyUpgradeableContractV2 newImplementation = new MyUpgradeableContractV2();
190
proxyAsContract.upgradeToAndCall(address(newImplementation), "");
191
```
192
193
### Beacon Proxy Pattern
194
195
Centralized upgrade mechanism where multiple proxies point to a single beacon for coordinated upgrades.
196
197
```solidity { .api }
198
/**
199
* @dev Beacon interface for implementation address resolution
200
*/
201
interface IBeacon {
202
/**
203
* @dev Returns the current implementation address
204
*/
205
function implementation() external view returns (address);
206
}
207
208
/**
209
* @dev Upgradeable beacon managing implementation for multiple proxies
210
*/
211
contract UpgradeableBeacon is IBeacon, Ownable {
212
/**
213
* @dev Returns current implementation address
214
*/
215
function implementation() public view virtual returns (address);
216
217
/**
218
* @dev Upgrades implementation for all connected beacon proxies
219
*/
220
function upgradeTo(address newImplementation) public virtual onlyOwner;
221
}
222
223
/**
224
* @dev Proxy that gets implementation address from a beacon
225
*/
226
contract BeaconProxy is Proxy {
227
/**
228
* @dev Initializes proxy with beacon and optional setup call
229
*/
230
constructor(address beacon, bytes memory data);
231
232
/**
233
* @dev Returns beacon address
234
*/
235
function _getBeacon() internal view virtual returns (address);
236
237
/**
238
* @dev Returns implementation from beacon
239
*/
240
function _implementation() internal view virtual override returns (address);
241
}
242
```
243
244
**Usage Example:**
245
246
```solidity
247
// Deploy implementation and beacon
248
MyContract implementation = new MyContract();
249
UpgradeableBeacon beacon = new UpgradeableBeacon(address(implementation), owner);
250
251
// Deploy multiple beacon proxies
252
bytes memory initData = abi.encodeCall(MyContract.initialize, (param));
253
BeaconProxy proxy1 = new BeaconProxy(address(beacon), initData);
254
BeaconProxy proxy2 = new BeaconProxy(address(beacon), initData);
255
256
// Upgrade all proxies at once through beacon
257
MyContractV2 newImplementation = new MyContractV2();
258
beacon.upgradeTo(address(newImplementation));
259
```
260
261
### Minimal Clones (EIP-1167)
262
263
Ultra-lightweight, non-upgradeable proxy pattern for cost-efficient contract deployment via clone factories.
264
265
```solidity { .api }
266
/**
267
* @dev Library for creating minimal proxy clones (EIP-1167)
268
*/
269
library Clones {
270
/**
271
* @dev Creates clone using CREATE opcode
272
*/
273
function clone(address implementation) internal returns (address instance);
274
275
/**
276
* @dev Creates clone using CREATE2 with deterministic address
277
*/
278
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance);
279
280
/**
281
* @dev Creates clone with immutable arguments appended
282
*/
283
function cloneWithImmutableArgs(address implementation, bytes memory args) internal returns (address instance);
284
285
/**
286
* @dev Predicts address for deterministic clone
287
*/
288
function predictDeterministicAddress(
289
address implementation,
290
bytes32 salt,
291
address deployer
292
) internal pure returns (address predicted);
293
294
/**
295
* @dev Retrieves immutable arguments from clone instance
296
*/
297
function fetchCloneArgs(address instance) internal pure returns (bytes memory args);
298
}
299
```
300
301
**Usage Example:**
302
303
```solidity
304
import "@openzeppelin/contracts/proxy/Clones.sol";
305
306
contract TokenFactory {
307
address public immutable implementation;
308
309
constructor() {
310
implementation = address(new MyToken());
311
}
312
313
function createToken(string memory name, string memory symbol) external returns (address) {
314
// Create minimal clone
315
address clone = Clones.clone(implementation);
316
317
// Initialize the clone
318
MyToken(clone).initialize(name, symbol, msg.sender);
319
320
return clone;
321
}
322
323
function createDeterministicToken(
324
string memory name,
325
string memory symbol,
326
bytes32 salt
327
) external returns (address) {
328
// Create deterministic clone
329
address clone = Clones.cloneDeterministic(implementation, salt);
330
MyToken(clone).initialize(name, symbol, msg.sender);
331
return clone;
332
}
333
}
334
```
335
336
### Proxy Initialization
337
338
Safe initialization patterns for proxy contracts preventing double-initialization and supporting versioned upgrades.
339
340
```solidity { .api }
341
/**
342
* @dev Initialization utility for proxy contracts with version support
343
*/
344
abstract contract Initializable {
345
/**
346
* @dev Disables initializers (use in implementation constructor)
347
*/
348
function _disableInitializers() internal virtual;
349
350
/**
351
* @dev Returns current initialized version
352
*/
353
function _getInitializedVersion() internal view returns (uint64);
354
355
/**
356
* @dev Returns true if currently in initialization phase
357
*/
358
function _isInitializing() internal view returns (bool);
359
360
/**
361
* @dev Modifier allowing single initialization (version 1)
362
*/
363
modifier initializer();
364
365
/**
366
* @dev Modifier allowing versioned re-initialization
367
*/
368
modifier reinitializer(uint64 version);
369
370
/**
371
* @dev Modifier restricting access to initialization phase only
372
*/
373
modifier onlyInitializing();
374
}
375
```
376
377
**Usage Example:**
378
379
```solidity
380
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
381
382
contract MyUpgradeableContract is Initializable {
383
string public name;
384
address public owner;
385
386
/// @custom:oz-upgrades-unsafe-allow constructor
387
constructor() {
388
_disableInitializers();
389
}
390
391
function initialize(string memory _name, address _owner) public initializer {
392
name = _name;
393
owner = _owner;
394
}
395
396
function initializeV2(string memory _name, address _owner, uint256 _newFeature) public reinitializer(2) {
397
name = _name;
398
owner = _owner;
399
// Initialize new features for V2
400
}
401
}
402
```
403
404
### Base Proxy Implementation
405
406
Abstract proxy contract providing core delegation functionality for all proxy patterns.
407
408
```solidity { .api }
409
/**
410
* @dev Abstract proxy contract with core delegation logic
411
*/
412
abstract contract Proxy {
413
/**
414
* @dev Returns implementation address (must be implemented by inheriting contracts)
415
*/
416
function _implementation() internal view virtual returns (address);
417
418
/**
419
* @dev Performs delegatecall to implementation
420
*/
421
function _delegate(address implementation) internal virtual;
422
423
/**
424
* @dev Internal fallback logic
425
*/
426
function _fallback() internal virtual;
427
428
/**
429
* @dev External fallback function
430
*/
431
fallback() external payable virtual;
432
433
/**
434
* @dev Receive function for ETH transfers
435
*/
436
receive() external payable virtual;
437
}
438
```
439
440
## Types
441
442
```solidity { .api }
443
/**
444
* @dev ERC-1967 standardized storage slots
445
*/
446
bytes32 constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
447
bytes32 constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
448
bytes32 constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
449
450
/**
451
* @dev ERC-1822 Universal Upgradeable Proxy Standard interface
452
*/
453
interface IERC1822Proxiable {
454
/**
455
* @dev Returns the storage slot used by the implementation
456
*/
457
function proxiableUUID() external view returns (bytes32);
458
}
459
460
/**
461
* @dev ERC-1967 Proxy Storage Slots interface
462
*/
463
interface IERC1967 {
464
event Upgraded(address indexed implementation);
465
event AdminChanged(address previousAdmin, address newAdmin);
466
event BeaconUpgraded(address indexed beacon);
467
}
468
469
/**
470
* @dev Transparent upgradeable proxy interface
471
*/
472
interface ITransparentUpgradeableProxy is IERC1967 {
473
function upgradeToAndCall(address newImplementation, bytes calldata data) external payable;
474
}
475
```