-
Notifications
You must be signed in to change notification settings - Fork 43
/
uups-upgradeable.ts
140 lines (126 loc) · 3.76 KB
/
uups-upgradeable.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import {SignerWithAddress} from '@nomiclabs/hardhat-ethers/signers';
import {expect} from 'chai';
import {Contract, ContractFactory, errors} from 'ethers';
import {upgrades} from 'hardhat';
import {DAO} from '../../typechain';
import {readImplementationValueFromSlot} from '../../utils/storage';
// Deploys and upgrades a contract that is managed by a DAO
export async function ozUpgradeCheckManagedContract(
deployer: SignerWithAddress,
upgrader: SignerWithAddress,
managingDao: DAO,
initArgs: any,
initializerName: string,
from: ContractFactory,
to: ContractFactory,
upgradePermissionId: string
): Promise<{
proxy: Contract;
fromImplementation: string;
toImplementation: string;
}> {
// Deploy the proxy
let proxy = await upgrades.deployProxy(
from.connect(deployer),
Object.values(initArgs),
{
kind: 'uups',
initializer: initializerName,
unsafeAllow: ['constructor'],
constructorArgs: [],
}
);
const fromImplementation = await readImplementationValueFromSlot(
proxy.address
);
// Check that upgrade permission is required
await expect(
upgrades.upgradeProxy(proxy.address, to.connect(upgrader), {
unsafeAllow: ['constructor'],
constructorArgs: [],
})
)
.to.be.revertedWithCustomError(proxy, 'DaoUnauthorized')
.withArgs(
managingDao.address,
proxy.address,
upgrader.address,
upgradePermissionId
);
// Grant the upgrade permission
await managingDao
.connect(deployer)
.grant(proxy.address, upgrader.address, upgradePermissionId);
// Upgrade the proxy
await upgrades.upgradeProxy(proxy.address, to.connect(upgrader), {
unsafeAllow: ['constructor'],
constructorArgs: [],
});
const toImplementation = await readImplementationValueFromSlot(proxy.address);
return {proxy, fromImplementation, toImplementation};
}
// Deploys and upgrades a contract that has its own permission manager
export async function ozUpgradeCheckManagingContract(
deployer: SignerWithAddress,
upgrader: SignerWithAddress,
initArgs: any,
initializerName: string,
from: ContractFactory,
to: ContractFactory,
upgradePermissionId: string
): Promise<{
proxy: Contract;
fromImplementation: string;
toImplementation: string;
}> {
// Deploy the proxy
let proxy = await upgrades.deployProxy(
from.connect(deployer),
Object.values(initArgs),
{
kind: 'uups',
initializer: initializerName,
unsafeAllow: ['constructor'],
constructorArgs: [],
}
);
const fromImplementation = await readImplementationValueFromSlot(
proxy.address
);
// Check that upgrade permission is required
await expect(
upgrades.upgradeProxy(proxy.address, to.connect(upgrader), {
unsafeAllow: ['constructor'],
constructorArgs: [],
})
)
.to.be.revertedWithCustomError(proxy, 'Unauthorized')
.withArgs(proxy.address, upgrader.address, upgradePermissionId);
// Grant the upgrade permission
await proxy
.connect(deployer)
.grant(proxy.address, upgrader.address, upgradePermissionId);
// Upgrade the proxy
await upgrades.upgradeProxy(proxy.address, to.connect(upgrader), {
unsafeAllow: ['constructor'],
constructorArgs: [],
});
const toImplementation = await readImplementationValueFromSlot(proxy.address);
return {proxy, fromImplementation, toImplementation};
}
export async function getProtocolVersion(
contract: Contract
): Promise<[number, number, number]> {
let protocolVersion: [number, number, number];
try {
contract.interface.getFunction('protocolVersion');
protocolVersion = await contract.protocolVersion();
} catch (error) {
if (error.code === errors.INVALID_ARGUMENT) {
protocolVersion = [1, 0, 0];
} else {
throw error;
}
}
return protocolVersion;
}