Skip to content

Commit bd0cb24

Browse files
committed
test: upgradable contracts initializers
1 parent 9a6b869 commit bd0cb24

File tree

6 files changed

+446
-89
lines changed

6 files changed

+446
-89
lines changed

contracts/deploy/utils/deployUpgradable.ts

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { DeployResult, DeployOptions } from "hardhat-deploy/types";
1+
import { DeployResult, DeployOptions, DeploymentsExtension } from "hardhat-deploy/types";
22
import { HardhatRuntimeEnvironment } from "hardhat/types";
33

44
export const deployUpgradable = async (
@@ -33,3 +33,72 @@ export const deployUpgradable = async (
3333
...otherOptions,
3434
});
3535
};
36+
37+
export const deployUpgradableEXPERIMENTAL = async (
38+
deployments: DeploymentsExtension,
39+
contract: string,
40+
options: DeployOptions
41+
): Promise<DeployResult> => {
42+
const { deploy } = deployments;
43+
const { args, ...otherOptions } = options;
44+
// Rationale: https://github.com/kleros/kleros-v2/pull/1214#issue-1879116629
45+
return deploy(contract, {
46+
proxy: {
47+
proxyContract: "UUPSProxy",
48+
proxyArgs: ["{implementation}", "{data}"],
49+
checkProxyAdmin: false, // Not relevant for UUPSProxy
50+
checkABIConflict: false, // Not relevant for UUPSProxy
51+
upgradeFunction: {
52+
methodName: "upgradeToAndCall",
53+
upgradeArgs: ["{implementation}", "{data}"],
54+
},
55+
execute: {
56+
init: {
57+
methodName: "initialize",
58+
args: args ?? [],
59+
},
60+
onUpgrade: {
61+
methodName: "initialize",
62+
args: args ?? [],
63+
},
64+
},
65+
},
66+
...otherOptions,
67+
});
68+
};
69+
70+
export const deployUpgradableEXPERIMENTAL2 = async (
71+
deployments: DeploymentsExtension,
72+
proxy: string,
73+
newImplementation: string,
74+
initializer = "initialize",
75+
options: DeployOptions
76+
): Promise<DeployResult> => {
77+
const { deploy } = deployments;
78+
const { args, ...otherOptions } = options;
79+
return await deploy(proxy, {
80+
contract: newImplementation,
81+
proxy: {
82+
implementationName: newImplementation + "_Implementation",
83+
proxyContract: "UUPSProxy",
84+
proxyArgs: ["{implementation}", "{data}"],
85+
checkProxyAdmin: false, // Not relevant for UUPSProxy
86+
checkABIConflict: false, // Not relevant for UUPSProxy
87+
upgradeFunction: {
88+
methodName: "upgradeToAndCall",
89+
upgradeArgs: ["{implementation}", "{data}"],
90+
},
91+
execute: {
92+
init: {
93+
methodName: initializer,
94+
args: args ?? [],
95+
},
96+
onUpgrade: {
97+
methodName: initializer,
98+
args: args ?? [],
99+
},
100+
},
101+
},
102+
...otherOptions,
103+
});
104+
};

contracts/src/proxy/mock/MockImplementations.sol

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
pragma solidity 0.8.18;
55

66
import "../UUPSProxiable.sol";
7+
import "../Initializable.sol";
78

89
contract NonUpgradeableMock {
910
uint256 public _counter;
@@ -22,7 +23,7 @@ contract NonUpgradeableMock {
2223
}
2324

2425
contract UUPSUpgradeableMock is UUPSProxiable, NonUpgradeableMock {
25-
bool private initialized;
26+
bool public initialized;
2627
address public governor;
2728

2829
uint256[50] __gap;
@@ -61,3 +62,58 @@ contract UUPSUnsupportedProxiableUUID is UUPSUpgradeableMock {
6162
return "UUPSUnsupportedProxiableUUID 1.0.0";
6263
}
6364
}
65+
66+
contract UUPSUpgradableInitializableInheritanceV1 is UUPSProxiable, Initializable {
67+
address public governor;
68+
uint256 public counter;
69+
uint256[50] __gap;
70+
71+
constructor() {
72+
_disableInitializers();
73+
}
74+
75+
function initialize(address _governor) external virtual reinitializer(1) {
76+
governor = _governor;
77+
counter = 1;
78+
}
79+
80+
function _authorizeUpgrade(address) internal view override {
81+
require(governor == msg.sender, "No privilege to upgrade");
82+
}
83+
84+
function increment() external {
85+
++counter;
86+
}
87+
88+
function version() external pure virtual returns (string memory) {
89+
return "V1";
90+
}
91+
}
92+
93+
contract UUPSUpgradableInitializableInheritanceV2 is UUPSUpgradableInitializableInheritanceV1 {
94+
string public newVariable;
95+
uint256[50] __gap2;
96+
97+
constructor() {
98+
_disableInitializers();
99+
}
100+
101+
function initializeV2(string memory _newVariable) external reinitializer(2) {
102+
newVariable = _newVariable;
103+
this.increment();
104+
}
105+
106+
function version() external pure virtual override returns (string memory) {
107+
return "V2";
108+
}
109+
}
110+
111+
contract UUPSUpgradableInitializableInheritanceV3Bad is UUPSUpgradableInitializableInheritanceV2 {
112+
constructor() {
113+
_disableInitializers();
114+
}
115+
116+
function initializeV3() external reinitializer(1) {
117+
// Wrong reinitializer version.
118+
}
119+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//SPDX-License-Identifier: MIT
2+
// Adapted from <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/mocks/proxy/UUPSUpgradeableMock.sol>
3+
4+
pragma solidity 0.8.18;
5+
6+
import "../UUPSProxiable.sol";
7+
import "../Initializable.sol";
8+
9+
contract UUPSUpgradableInitializable is UUPSProxiable, Initializable {
10+
//------------------------
11+
// V1 State
12+
//------------------------
13+
address public governor;
14+
uint256 public counter;
15+
uint256[50] __gap;
16+
17+
constructor() {
18+
_disableInitializers();
19+
}
20+
21+
function initialize(address _governor) external virtual reinitializer(1) {
22+
governor = _governor;
23+
counter = 1;
24+
}
25+
26+
function _authorizeUpgrade(address) internal view override {
27+
require(governor == msg.sender, "No privilege to upgrade");
28+
}
29+
30+
function increment() external {
31+
++counter;
32+
}
33+
34+
function version() external pure virtual returns (string memory) {
35+
return "V1";
36+
}
37+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//SPDX-License-Identifier: MIT
2+
// Adapted from <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/mocks/proxy/UUPSUpgradeableMock.sol>
3+
4+
pragma solidity 0.8.18;
5+
6+
import "../UUPSProxiable.sol";
7+
import "../Initializable.sol";
8+
9+
contract UUPSUpgradableInitializable is UUPSProxiable, Initializable {
10+
//------------------------
11+
// V1 State
12+
//------------------------
13+
address public governor;
14+
uint256 public counter;
15+
uint256[50] __gap;
16+
17+
//------------------------
18+
// V2 State
19+
//------------------------
20+
string public newVariable;
21+
22+
constructor() {
23+
_disableInitializers();
24+
}
25+
26+
function initialize(string memory _newVariable) external reinitializer(2) {
27+
newVariable = _newVariable;
28+
this.increment();
29+
}
30+
31+
function _authorizeUpgrade(address) internal view override {
32+
require(governor == msg.sender, "No privilege to upgrade");
33+
}
34+
35+
function increment() external {
36+
++counter;
37+
}
38+
39+
function version() external pure virtual returns (string memory) {
40+
return "V2";
41+
}
42+
}

0 commit comments

Comments
 (0)