or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

access-control.mdcontract-presets.mdcryptography-math.mdgsn-support.mdindex.mdintrospection.mdpayment-mechanisms.mdproxy-patterns.mdsecurity-utilities.mdtoken-standards.md

proxy-patterns.mddocs/

0

# Proxy Patterns

1

2

OpenZeppelin provides comprehensive proxy patterns for creating upgradeable smart contracts including transparent proxies, beacon proxies, and minimal proxies. These patterns enable contract upgradeability while maintaining persistent storage and addresses.

3

4

## Capabilities

5

6

### Initializable - Upgradeable Contract Base

7

8

Base contract to aid in writing upgradeable contracts, ensuring initialization functions are only called once.

9

10

```solidity { .api }

11

/**

12

* This is a base contract to aid in writing upgradeable contracts

13

*/

14

abstract contract Initializable {

15

/**

16

* Modifier to protect an initializer function from being invoked twice

17

*/

18

modifier initializer();

19

20

/**

21

* Modifier to protect a function from being invoked after the contract has been initialized

22

*/

23

modifier onlyInitializing();

24

}

25

```

26

27

**Usage Example:**

28

29

```solidity

30

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

31

32

contract MyUpgradeableContract is Initializable {

33

uint256 private _value;

34

address private _owner;

35

36

function initialize(uint256 initialValue, address owner) public initializer {

37

_value = initialValue;

38

_owner = owner;

39

}

40

}

41

```

42

43

### Proxy - Base Proxy Contract

44

45

Abstract contract that implements a proxy pattern for upgradeable contracts.

46

47

```solidity { .api }

48

/**

49

* This abstract contract provides a fallback function that delegates all calls to another contract

50

*/

51

abstract contract Proxy {

52

/**

53

* Delegates the current call to implementation

54

*/

55

function _delegate(address implementation) internal virtual;

56

57

/**

58

* This is a virtual function that should be overridden so it returns the address to which the fallback function and _fallback should delegate

59

*/

60

function _implementation() internal view virtual returns (address);

61

62

/**

63

* Delegates the current call to the address returned by _implementation()

64

*/

65

function _fallback() internal virtual;

66

67

/**

68

* Fallback function that delegates calls to the address returned by _implementation()

69

*/

70

fallback() external payable virtual;

71

72

/**

73

* Fallback function that delegates calls to the address returned by _implementation()

74

*/

75

receive() external payable virtual;

76

}

77

```

78

79

### UpgradeableProxy - Basic Upgradeable Proxy

80

81

Upgradeable proxy that stores the implementation address in a specific storage slot.

82

83

```solidity { .api }

84

/**

85

* This contract implements an upgradeable proxy

86

*/

87

contract UpgradeableProxy is Proxy {

88

/**

89

* Initializes the upgradeable proxy with an initial implementation specified by implementation

90

*/

91

constructor(address _logic, bytes memory _data) payable;

92

93

/**

94

* Returns the current implementation address

95

*/

96

function _implementation() internal view virtual override returns (address impl);

97

98

/**

99

* Upgrades the proxy to a new implementation

100

*/

101

function _upgradeTo(address newImplementation) internal virtual;

102

103

/**

104

* Emitted when the implementation is upgraded

105

*/

106

event Upgraded(address indexed implementation);

107

}

108

```

109

110

### TransparentUpgradeableProxy - Admin-Controlled Proxy

111

112

Upgradeable proxy with an admin that can upgrade the implementation while preventing admin functions from being called by users.

113

114

```solidity { .api }

115

/**

116

* This contract implements a proxy that is upgradeable by an admin

117

*/

118

contract TransparentUpgradeableProxy is UpgradeableProxy {

119

/**

120

* Initializes an upgradeable proxy managed by admin, backed by the implementation at logic, and optionally initialized with data

121

*/

122

constructor(address logic, address admin, bytes memory data) payable UpgradeableProxy(logic, data);

123

124

/**

125

* Returns the current admin

126

*/

127

function admin() external view returns (address admin);

128

129

/**

130

* Returns the current implementation

131

*/

132

function implementation() external view returns (address implementation);

133

134

/**

135

* Changes the admin of the proxy

136

*/

137

function changeAdmin(address newAdmin) external;

138

139

/**

140

* Upgrade the implementation of the proxy

141

*/

142

function upgradeTo(address newImplementation) external;

143

144

/**

145

* Upgrade the implementation of the proxy, and then call a function from the new implementation

146

*/

147

function upgradeToAndCall(address newImplementation, bytes calldata data) external payable;

148

149

event AdminChanged(address previousAdmin, address newAdmin);

150

}

151

```

152

153

### ProxyAdmin - Proxy Administration

154

155

Administrative contract for managing multiple transparent upgradeable proxies.

156

157

```solidity { .api }

158

/**

159

* This is an auxiliary contract meant to be assigned as the admin of a TransparentUpgradeableProxy

160

*/

161

contract ProxyAdmin is Ownable {

162

/**

163

* Returns the current implementation of proxy

164

*/

165

function getImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address);

166

167

/**

168

* Changes the admin of proxy to newAdmin

169

*/

170

function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner;

171

172

/**

173

* Upgrades proxy to implementation

174

*/

175

function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner;

176

177

/**

178

* Upgrades proxy to implementation and calls a function on the new implementation

179

*/

180

function upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) public payable virtual onlyOwner;

181

}

182

```

183

184

### BeaconProxy - Beacon-Based Proxy

185

186

Proxy that uses a beacon contract to determine its implementation address.

187

188

```solidity { .api }

189

/**

190

* This contract implements a proxy that gets the implementation address for each call from a UpgradeableBeacon

191

*/

192

contract BeaconProxy is Proxy, ERC1967Upgrade {

193

/**

194

* Initializes the proxy with beacon

195

*/

196

constructor(address beacon, bytes memory data) payable;

197

198

/**

199

* Returns the current beacon

200

*/

201

function _beacon() internal view virtual returns (address);

202

203

/**

204

* Returns the current implementation address of the associated beacon

205

*/

206

function _implementation() internal view virtual override returns (address);

207

208

/**

209

* Changes the proxy to use a new beacon

210

*/

211

function _setBeacon(address beacon, bytes memory data) internal virtual;

212

}

213

```

214

215

### UpgradeableBeacon - Implementation Beacon

216

217

Beacon contract that stores an implementation address and allows authorized accounts to upgrade it.

218

219

```solidity { .api }

220

/**

221

* This contract is used in conjunction with one or more instances of BeaconProxy to determine their implementation contract

222

*/

223

contract UpgradeableBeacon is IBeacon, Ownable {

224

/**

225

* Sets the address of the initial implementation, and the deployer account as the owner

226

*/

227

constructor(address implementation);

228

229

/**

230

* Returns the current implementation address

231

*/

232

function implementation() public view virtual override returns (address);

233

234

/**

235

* Upgrades the beacon to a new implementation

236

*/

237

function upgradeTo(address newImplementation) public virtual onlyOwner;

238

239

/**

240

* Emitted when the implementation returned by the beacon is changed

241

*/

242

event Upgraded(address indexed implementation);

243

}

244

```

245

246

### Clones - Minimal Proxy Factory

247

248

Library for deploying minimal proxy contracts (EIP-1167) that delegate all calls to a master contract.

249

250

```solidity { .api }

251

/**

252

* This library enables deploying and managing minimal proxy contracts

253

*/

254

library Clones {

255

/**

256

* Deploys and returns the address of a clone that mimics the behaviour of implementation

257

*/

258

function clone(address implementation) internal returns (address instance);

259

260

/**

261

* Deploys and returns the address of a clone that mimics the behaviour of implementation

262

* This function uses the create2 opcode and a salt to deterministically deploy the clone

263

*/

264

function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance);

265

266

/**

267

* Computes the address of a clone deployed using Clones.cloneDeterministic

268

*/

269

function predictDeterministicAddress(

270

address implementation,

271

bytes32 salt,

272

address deployer

273

) internal pure returns (address predicted);

274

275

/**

276

* Computes the address of a clone deployed using Clones.cloneDeterministic

277

*/

278

function predictDeterministicAddress(address implementation, bytes32 salt) internal view returns (address predicted);

279

}

280

```

281

282

**Usage Example:**

283

284

```solidity

285

import "@openzeppelin/contracts/proxy/Clones.sol";

286

287

contract TokenFactory {

288

address immutable tokenImplementation;

289

290

constructor() {

291

tokenImplementation = address(new MyToken());

292

}

293

294

function createToken(string memory name, string memory symbol) external returns (address) {

295

address clone = Clones.clone(tokenImplementation);

296

MyToken(clone).initialize(name, symbol, msg.sender);

297

return clone;

298

}

299

}

300

```

301

302

## Upgrade Patterns

303

304

### Basic Upgrade Pattern

305

306

```solidity

307

// Implementation V1

308

contract MyContractV1 is Initializable {

309

uint256 private _value;

310

311

function initialize(uint256 initialValue) public initializer {

312

_value = initialValue;

313

}

314

315

function getValue() public view returns (uint256) {

316

return _value;

317

}

318

319

function setValue(uint256 newValue) public {

320

_value = newValue;

321

}

322

}

323

324

// Implementation V2 - adds new functionality

325

contract MyContractV2 is Initializable {

326

uint256 private _value;

327

uint256 private _multiplier; // New storage variable

328

329

function initialize(uint256 initialValue) public initializer {

330

_value = initialValue;

331

_multiplier = 1;

332

}

333

334

function getValue() public view returns (uint256) {

335

return _value * _multiplier;

336

}

337

338

function setValue(uint256 newValue) public {

339

_value = newValue;

340

}

341

342

// New function in V2

343

function setMultiplier(uint256 newMultiplier) public {

344

_multiplier = newMultiplier;

345

}

346

}

347

```

348

349

### Factory with Clones Pattern

350

351

```solidity

352

import "@openzeppelin/contracts/proxy/Clones.sol";

353

import "@openzeppelin/contracts/access/Ownable.sol";

354

355

contract TokenFactory is Ownable {

356

address public immutable tokenImplementation;

357

address[] public deployedTokens;

358

359

event TokenCreated(address indexed token, address indexed creator);

360

361

constructor(address _tokenImplementation) {

362

tokenImplementation = _tokenImplementation;

363

}

364

365

function createToken(

366

string memory name,

367

string memory symbol,

368

uint256 initialSupply

369

) external returns (address) {

370

bytes32 salt = keccak256(abi.encodePacked(msg.sender, name, symbol));

371

address tokenClone = Clones.cloneDeterministic(tokenImplementation, salt);

372

373

IToken(tokenClone).initialize(name, symbol, initialSupply, msg.sender);

374

375

deployedTokens.push(tokenClone);

376

emit TokenCreated(tokenClone, msg.sender);

377

378

return tokenClone;

379

}

380

381

function predictTokenAddress(

382

address creator,

383

string memory name,

384

string memory symbol

385

) external view returns (address) {

386

bytes32 salt = keccak256(abi.encodePacked(creator, name, symbol));

387

return Clones.predictDeterministicAddress(tokenImplementation, salt);

388

}

389

390

function getDeployedTokensCount() external view returns (uint256) {

391

return deployedTokens.length;

392

}

393

}

394

```

395

396

### Beacon Upgrade Pattern

397

398

```solidity

399

import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";

400

import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";

401

402

contract MyBeaconFactory is Ownable {

403

UpgradeableBeacon public immutable beacon;

404

address[] public deployedProxies;

405

406

constructor(address initialImplementation) {

407

beacon = new UpgradeableBeacon(initialImplementation);

408

}

409

410

function createProxy(bytes memory data) external returns (address) {

411

BeaconProxy proxy = new BeaconProxy(address(beacon), data);

412

deployedProxies.push(address(proxy));

413

return address(proxy);

414

}

415

416

function upgradeAll(address newImplementation) external onlyOwner {

417

beacon.upgradeTo(newImplementation);

418

// All deployed proxies now use the new implementation

419

}

420

421

function getCurrentImplementation() external view returns (address) {

422

return beacon.implementation();

423

}

424

}

425

```

426

427

### Complete Upgrade Workflow

428

429

```solidity

430

// 1. Deploy ProxyAdmin

431

ProxyAdmin proxyAdmin = new ProxyAdmin();

432

433

// 2. Deploy implementation contract

434

MyContractV1 implementationV1 = new MyContractV1();

435

436

// 3. Deploy proxy with initialization

437

bytes memory initData = abi.encodeWithSelector(

438

MyContractV1.initialize.selector,

439

123 // initial value

440

);

441

442

TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(

443

address(implementationV1),

444

address(proxyAdmin),

445

initData

446

);

447

448

// 4. Use proxy as if it were the implementation

449

MyContractV1 myContract = MyContractV1(address(proxy));

450

myContract.setValue(456);

451

452

// 5. Later, upgrade to V2

453

MyContractV2 implementationV2 = new MyContractV2();

454

proxyAdmin.upgrade(proxy, address(implementationV2));

455

456

// 6. Proxy now uses V2 implementation

457

MyContractV2 myContractV2 = MyContractV2(address(proxy));

458

myContractV2.setMultiplier(2);

459

```