Skip to content

Commit 619b0b8

Browse files
authored
feat: Set owner at deployment (#245)
2 parents 4376b26 + d2be60a commit 619b0b8

File tree

3 files changed

+85
-39
lines changed

3 files changed

+85
-39
lines changed

config/config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@
165165
"asset": "Token",
166166
"token": "0x86934B9A25212D94fb95486FAE8518d6039f0309",
167167
"richman": "0x9990cfb1Feb7f47297F54bef4d4EbeDf6c5463a3",
168+
"owner": "0x9990cfb1Feb7f47297F54bef4d4EbeDf6c5463a3",
168169
"uniswap": false,
169170
"v3": {
170171
"Hub": null,

deploy/0_deploy.ts

Lines changed: 83 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -44,37 +44,42 @@ import { getLibDiamondConfigOrEmpty } from '../utils/tools';
4444

4545
let factoryDeployer: FactoryDeployer;
4646

47+
// TODO: refactor this file to differentiate hardhat deployment from
48+
// other chains deployment.
4749
export default async function deploy() {
4850
console.log('Deploying PoCo..');
4951
const network = await ethers.provider.getNetwork();
5052
const chainId = network.chainId;
51-
const [owner] = await ethers.getSigners();
53+
const [deployer] = await ethers.getSigners();
5254
const deploymentOptions = config.getChainConfigOrDefault(chainId);
53-
factoryDeployer = new FactoryDeployer(owner, chainId);
55+
// TODO: remove the fallback on deployer address to avoid deployement
56+
// misconfiguration.
57+
const ownerAddress = deploymentOptions.owner || deployer.address;
58+
factoryDeployer = new FactoryDeployer(deployer, chainId);
5459
// Deploy RLC
5560
const isTokenMode = !config.isNativeChain(deploymentOptions);
5661
let rlcInstanceAddress = isTokenMode
57-
? await getOrDeployRlc(deploymentOptions.token!, owner) // token
62+
? await getOrDeployRlc(deploymentOptions.token!, deployer, ownerAddress) // token
5863
: ZeroAddress; // native
5964
console.log(`RLC: ${rlcInstanceAddress}`);
60-
/**
61-
* Deploy proxy and facets.
62-
*/
63-
// TODO put inside init() function.
64-
const transferOwnershipCall = await Ownable__factory.connect(
65+
// Prepare transferOwnership call to the deployer.
66+
// Ownership transfer should be done in the same deployment transaction
67+
// otherwise it is not possible to transfer ownership before hand if the
68+
// factory is set as the owner.
69+
const transferOwnershipToDeployerCall = await Ownable__factory.connect(
6570
ZeroAddress, // any is fine
66-
owner, // any is fine
71+
ethers.provider,
6772
)
68-
.transferOwnership.populateTransaction(owner.address)
73+
.transferOwnership.populateTransaction(deployer.address)
6974
.then((tx) => tx.data)
7075
.catch(() => {
7176
throw new Error('Failed to prepare transferOwnership data');
7277
});
73-
const diamondProxyAddress = await deployDiamondProxyWithDefaultFacets(
74-
owner,
75-
// transferOwnershipCall, //TODO
76-
);
77-
const diamond = DiamondCutFacet__factory.connect(diamondProxyAddress, owner);
78+
/**
79+
* Deploy proxy and facets.
80+
*/
81+
const diamondProxyAddress = await deployDiamondProxyWithDefaultFacets(deployer);
82+
const diamond = DiamondCutFacet__factory.connect(diamondProxyAddress, deployer);
7883
console.log(`IexecInstance found at address: ${await diamond.getAddress()}`);
7984
// Deploy library & facets
8085
const iexecLibOrdersAddress = await factoryDeployer.deployContract(
@@ -106,7 +111,7 @@ export default async function deploy() {
106111
// Verify linking on Diamond Proxy
107112
const diamondLoupeFacetInstance: DiamondLoupeFacet = DiamondLoupeFacet__factory.connect(
108113
diamondProxyAddress,
109-
owner,
114+
deployer,
110115
);
111116
const diamondFacets = await diamondLoupeFacetInstance.facets();
112117
const functionCount = diamondFacets
@@ -124,24 +129,27 @@ export default async function deploy() {
124129
const appRegistryAddress = await factoryDeployer.deployContract(
125130
new AppRegistry__factory(),
126131
[],
127-
transferOwnershipCall,
132+
transferOwnershipToDeployerCall,
128133
);
129134
const datasetRegistryAddress = await factoryDeployer.deployContract(
130135
new DatasetRegistry__factory(),
131136
[],
132-
transferOwnershipCall,
137+
transferOwnershipToDeployerCall,
133138
);
134139
const workerpoolRegistryAddress = await factoryDeployer.deployContract(
135140
new WorkerpoolRegistry__factory(),
136141
[],
137-
transferOwnershipCall,
142+
transferOwnershipToDeployerCall,
138143
);
139144

140-
const appRegistryInstance = AppRegistry__factory.connect(appRegistryAddress, owner);
141-
const datasetRegistryInstance = DatasetRegistry__factory.connect(datasetRegistryAddress, owner);
145+
const appRegistryInstance = AppRegistry__factory.connect(appRegistryAddress, deployer);
146+
const datasetRegistryInstance = DatasetRegistry__factory.connect(
147+
datasetRegistryAddress,
148+
deployer,
149+
);
142150
const workerpoolRegistryInstance = WorkerpoolRegistry__factory.connect(
143151
workerpoolRegistryAddress,
144-
owner,
152+
deployer,
145153
);
146154
// Base URI configuration from config.json
147155
const baseURIApp = config.registriesBaseUri.app;
@@ -172,11 +180,11 @@ export default async function deploy() {
172180
}
173181

174182
// Set main configuration
175-
const iexecAccessorsInstance = IexecAccessors__factory.connect(diamondProxyAddress, owner);
183+
const iexecAccessorsInstance = IexecAccessors__factory.connect(diamondProxyAddress, deployer);
176184
const iexecInitialized = (await iexecAccessorsInstance.eip712domain_separator()) != ZeroHash;
177185
if (!iexecInitialized) {
178186
// TODO replace this with DiamondInit.init().
179-
await IexecConfigurationFacet__factory.connect(diamondProxyAddress, owner)
187+
await IexecConfigurationFacet__factory.connect(diamondProxyAddress, deployer)
180188
.configure(
181189
rlcInstanceAddress,
182190
'Staked RLC',
@@ -193,7 +201,7 @@ export default async function deploy() {
193201
const catCountBefore = await iexecAccessorsInstance.countCategory();
194202
for (let i = Number(catCountBefore); i < config.categories.length; i++) {
195203
const category = config.categories[i];
196-
await IexecCategoryManager__factory.connect(diamondProxyAddress, owner)
204+
await IexecCategoryManager__factory.connect(diamondProxyAddress, deployer)
197205
.createCategory(
198206
category.name,
199207
JSON.stringify(category.description),
@@ -206,16 +214,28 @@ export default async function deploy() {
206214
for (let i = 0; i < Number(catCountAfter); i++) {
207215
console.log(`Category ${i}: ${await iexecAccessorsInstance.viewCategory(i)}`);
208216
}
209-
217+
// Transfer ownership of all contracts to the configured owner.
218+
await transferOwnershipToFinalOwner(
219+
diamondProxyAddress,
220+
appRegistryAddress,
221+
datasetRegistryAddress,
222+
workerpoolRegistryAddress,
223+
deployer,
224+
ownerAddress,
225+
);
210226
if (network.name !== 'hardhat' && network.name !== 'localhost') {
211227
console.log('Waiting for block explorer to index the contracts...');
212228
await new Promise((resolve) => setTimeout(resolve, 60000));
213229
await import('../scripts/verify').then((module) => module.default());
214230
}
215231
}
216232

217-
async function getOrDeployRlc(token: string, owner: SignerWithAddress) {
218-
const rlcFactory = new RLC__factory().connect(owner);
233+
async function getOrDeployRlc(
234+
token: string,
235+
deployer: SignerWithAddress,
236+
ownerAddress: string,
237+
): Promise<string> {
238+
const rlcFactory = new RLC__factory().connect(deployer);
219239
let rlcAddress: string;
220240

221241
if (token) {
@@ -228,6 +248,10 @@ async function getOrDeployRlc(token: string, owner: SignerWithAddress) {
228248
.then((contract) => contract.waitForDeployment())
229249
.then((contract) => contract.getAddress());
230250
console.log(`New RLC token deployed at: ${rlcAddress}`);
251+
await Ownable__factory.connect(rlcAddress, deployer)
252+
.transferOwnership(ownerAddress)
253+
.then((tx) => tx.wait());
254+
console.log(`Ownership of RLC token transferred to: ${deployer.address}`);
231255
}
232256

233257
await deployments.save('RLC', {
@@ -243,13 +267,10 @@ async function getOrDeployRlc(token: string, owner: SignerWithAddress) {
243267
* Deploys and initializes a Diamond proxy contract with default facets.
244268
* @returns The address of the deployed Diamond proxy contract.
245269
*/
246-
async function deployDiamondProxyWithDefaultFacets(
247-
owner: SignerWithAddress,
248-
// transferOwnershipCall: string, // TODO
249-
): Promise<string> {
270+
async function deployDiamondProxyWithDefaultFacets(deployer: SignerWithAddress): Promise<string> {
250271
const initAddress = await factoryDeployer.deployContract(new DiamondInit__factory());
251272
const initCalldata = DiamondInit__factory.createInterface().encodeFunctionData('init');
252-
const libDiamondConfig = await getLibDiamondConfigOrEmpty(owner);
273+
const libDiamondConfig = await getLibDiamondConfigOrEmpty(deployer);
253274
// Deploy required proxy facets.
254275
const facetFactories = [
255276
new DiamondCutFacet__factory(libDiamondConfig),
@@ -268,13 +289,36 @@ async function deployDiamondProxyWithDefaultFacets(
268289
}
269290
// Set diamond constructor arguments
270291
const diamondArgs: DiamondArgsStruct = {
271-
owner: owner.address,
292+
owner: deployer.address,
272293
init: initAddress,
273294
initCalldata: initCalldata,
274295
};
275-
return await factoryDeployer.deployContract(
276-
new Diamond__factory(libDiamondConfig),
277-
[facetCuts, diamondArgs],
278-
// transferOwnershipCall, // TODO
279-
);
296+
return await factoryDeployer.deployContract(new Diamond__factory(libDiamondConfig), [
297+
facetCuts,
298+
diamondArgs,
299+
]);
300+
}
301+
302+
/**
303+
* Prepares the transferOwnership calls for all provided contracts.
304+
*/
305+
async function transferOwnershipToFinalOwner(
306+
diamondAddress: string,
307+
appRegistryAddress: string,
308+
datasetRegistryAddress: string,
309+
workerpoolRegistryAddress: string,
310+
currentOwner: SignerWithAddress,
311+
ownerAddress: string,
312+
) {
313+
for (const contract of [
314+
{ name: 'Diamond', address: diamondAddress },
315+
{ name: 'AppRegistry', address: appRegistryAddress },
316+
{ name: 'DatasetRegistry', address: datasetRegistryAddress },
317+
{ name: 'WorkerpoolRegistry', address: workerpoolRegistryAddress },
318+
]) {
319+
await Ownable__factory.connect(contract.address, currentOwner)
320+
.transferOwnership(ownerAddress)
321+
.then((tx) => tx.wait());
322+
console.log(`Owner of ${contract.name}: ${ownerAddress}`);
323+
}
280324
}

utils/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type ChainConfig = {
4040
asset: string;
4141
token?: string | null; // The token deployed should be compatible with Approve and call
4242
richman?: string | null; // The richman account is needed if the token is already deployed
43+
owner?: string | null;
4344
uniswap?: boolean;
4445
etoken?: string;
4546
v3: {

0 commit comments

Comments
 (0)