Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@
"asset": "Token",
"token": "0x86934B9A25212D94fb95486FAE8518d6039f0309",
"richman": "0x9990cfb1Feb7f47297F54bef4d4EbeDf6c5463a3",
"owner": "0x9990cfb1Feb7f47297F54bef4d4EbeDf6c5463a3",
"uniswap": false,
"v3": {
"Hub": null,
Expand Down
122 changes: 83 additions & 39 deletions deploy/0_deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,37 +44,42 @@ import { getLibDiamondConfigOrEmpty } from '../utils/tools';

let factoryDeployer: FactoryDeployer;

// TODO: refactor this file to differentiate hardhat deployment from
// other chains deployment.
export default async function deploy() {
console.log('Deploying PoCo..');
const network = await ethers.provider.getNetwork();
const chainId = network.chainId;
const [owner] = await ethers.getSigners();
const [deployer] = await ethers.getSigners();
const deploymentOptions = config.getChainConfigOrDefault(chainId);
factoryDeployer = new FactoryDeployer(owner, chainId);
// TODO: remove the fallback on deployer address to avoid deployement
// misconfiguration.
const ownerAddress = deploymentOptions.owner || deployer.address;
factoryDeployer = new FactoryDeployer(deployer, chainId);
// Deploy RLC
const isTokenMode = !config.isNativeChain(deploymentOptions);
let rlcInstanceAddress = isTokenMode
? await getOrDeployRlc(deploymentOptions.token!, owner) // token
? await getOrDeployRlc(deploymentOptions.token!, deployer, ownerAddress) // token
: ZeroAddress; // native
console.log(`RLC: ${rlcInstanceAddress}`);
/**
* Deploy proxy and facets.
*/
// TODO put inside init() function.
const transferOwnershipCall = await Ownable__factory.connect(
// Prepare transferOwnership call to the deployer.
// Ownership transfer should be done in the same deployment transaction
// otherwise it is not possible to transfer ownership before hand if the
// factory is set as the owner.
const transferOwnershipToDeployerCall = await Ownable__factory.connect(
ZeroAddress, // any is fine
owner, // any is fine
ethers.provider,
)
.transferOwnership.populateTransaction(owner.address)
.transferOwnership.populateTransaction(deployer.address)
.then((tx) => tx.data)
.catch(() => {
throw new Error('Failed to prepare transferOwnership data');
});
const diamondProxyAddress = await deployDiamondProxyWithDefaultFacets(
owner,
// transferOwnershipCall, //TODO
);
const diamond = DiamondCutFacet__factory.connect(diamondProxyAddress, owner);
/**
* Deploy proxy and facets.
*/
const diamondProxyAddress = await deployDiamondProxyWithDefaultFacets(deployer);
const diamond = DiamondCutFacet__factory.connect(diamondProxyAddress, deployer);
console.log(`IexecInstance found at address: ${await diamond.getAddress()}`);
// Deploy library & facets
const iexecLibOrdersAddress = await factoryDeployer.deployContract(
Expand Down Expand Up @@ -106,7 +111,7 @@ export default async function deploy() {
// Verify linking on Diamond Proxy
const diamondLoupeFacetInstance: DiamondLoupeFacet = DiamondLoupeFacet__factory.connect(
diamondProxyAddress,
owner,
deployer,
);
const diamondFacets = await diamondLoupeFacetInstance.facets();
const functionCount = diamondFacets
Expand All @@ -124,24 +129,27 @@ export default async function deploy() {
const appRegistryAddress = await factoryDeployer.deployContract(
new AppRegistry__factory(),
[],
transferOwnershipCall,
transferOwnershipToDeployerCall,
);
const datasetRegistryAddress = await factoryDeployer.deployContract(
new DatasetRegistry__factory(),
[],
transferOwnershipCall,
transferOwnershipToDeployerCall,
);
const workerpoolRegistryAddress = await factoryDeployer.deployContract(
new WorkerpoolRegistry__factory(),
[],
transferOwnershipCall,
transferOwnershipToDeployerCall,
);

const appRegistryInstance = AppRegistry__factory.connect(appRegistryAddress, owner);
const datasetRegistryInstance = DatasetRegistry__factory.connect(datasetRegistryAddress, owner);
const appRegistryInstance = AppRegistry__factory.connect(appRegistryAddress, deployer);
const datasetRegistryInstance = DatasetRegistry__factory.connect(
datasetRegistryAddress,
deployer,
);
const workerpoolRegistryInstance = WorkerpoolRegistry__factory.connect(
workerpoolRegistryAddress,
owner,
deployer,
);
// Base URI configuration from config.json
const baseURIApp = config.registriesBaseUri.app;
Expand Down Expand Up @@ -172,11 +180,11 @@ export default async function deploy() {
}

// Set main configuration
const iexecAccessorsInstance = IexecAccessors__factory.connect(diamondProxyAddress, owner);
const iexecAccessorsInstance = IexecAccessors__factory.connect(diamondProxyAddress, deployer);
const iexecInitialized = (await iexecAccessorsInstance.eip712domain_separator()) != ZeroHash;
if (!iexecInitialized) {
// TODO replace this with DiamondInit.init().
await IexecConfigurationFacet__factory.connect(diamondProxyAddress, owner)
await IexecConfigurationFacet__factory.connect(diamondProxyAddress, deployer)
.configure(
rlcInstanceAddress,
'Staked RLC',
Expand All @@ -193,7 +201,7 @@ export default async function deploy() {
const catCountBefore = await iexecAccessorsInstance.countCategory();
for (let i = Number(catCountBefore); i < config.categories.length; i++) {
const category = config.categories[i];
await IexecCategoryManager__factory.connect(diamondProxyAddress, owner)
await IexecCategoryManager__factory.connect(diamondProxyAddress, deployer)
.createCategory(
category.name,
JSON.stringify(category.description),
Expand All @@ -206,16 +214,28 @@ export default async function deploy() {
for (let i = 0; i < Number(catCountAfter); i++) {
console.log(`Category ${i}: ${await iexecAccessorsInstance.viewCategory(i)}`);
}

// Transfer ownership of all contracts to the configured owner.
await transferOwnershipToFinalOwner(
diamondProxyAddress,
appRegistryAddress,
datasetRegistryAddress,
workerpoolRegistryAddress,
deployer,
ownerAddress,
);
if (network.name !== 'hardhat' && network.name !== 'localhost') {
console.log('Waiting for block explorer to index the contracts...');
await new Promise((resolve) => setTimeout(resolve, 60000));
await import('../scripts/verify').then((module) => module.default());
}
}

async function getOrDeployRlc(token: string, owner: SignerWithAddress) {
const rlcFactory = new RLC__factory().connect(owner);
async function getOrDeployRlc(
token: string,
deployer: SignerWithAddress,
ownerAddress: string,
): Promise<string> {
const rlcFactory = new RLC__factory().connect(deployer);
let rlcAddress: string;

if (token) {
Expand All @@ -228,6 +248,10 @@ async function getOrDeployRlc(token: string, owner: SignerWithAddress) {
.then((contract) => contract.waitForDeployment())
.then((contract) => contract.getAddress());
console.log(`New RLC token deployed at: ${rlcAddress}`);
await Ownable__factory.connect(rlcAddress, deployer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
await Ownable__factory.connect(rlcAddress, deployer)
await RLC__factory.connect(rlcAddress, deployer)

more readable

.transferOwnership(ownerAddress)
.then((tx) => tx.wait());
console.log(`Ownership of RLC token transferred to: ${deployer.address}`);
}

await deployments.save('RLC', {
Expand All @@ -243,13 +267,10 @@ async function getOrDeployRlc(token: string, owner: SignerWithAddress) {
* Deploys and initializes a Diamond proxy contract with default facets.
* @returns The address of the deployed Diamond proxy contract.
*/
async function deployDiamondProxyWithDefaultFacets(
owner: SignerWithAddress,
// transferOwnershipCall: string, // TODO
): Promise<string> {
async function deployDiamondProxyWithDefaultFacets(deployer: SignerWithAddress): Promise<string> {
const initAddress = await factoryDeployer.deployContract(new DiamondInit__factory());
const initCalldata = DiamondInit__factory.createInterface().encodeFunctionData('init');
const libDiamondConfig = await getLibDiamondConfigOrEmpty(owner);
const libDiamondConfig = await getLibDiamondConfigOrEmpty(deployer);
// Deploy required proxy facets.
const facetFactories = [
new DiamondCutFacet__factory(libDiamondConfig),
Expand All @@ -268,13 +289,36 @@ async function deployDiamondProxyWithDefaultFacets(
}
// Set diamond constructor arguments
const diamondArgs: DiamondArgsStruct = {
owner: owner.address,
owner: deployer.address,
init: initAddress,
initCalldata: initCalldata,
};
return await factoryDeployer.deployContract(
new Diamond__factory(libDiamondConfig),
[facetCuts, diamondArgs],
// transferOwnershipCall, // TODO
);
return await factoryDeployer.deployContract(new Diamond__factory(libDiamondConfig), [
facetCuts,
diamondArgs,
]);
}

/**
* Prepares the transferOwnership calls for all provided contracts.
*/
async function transferOwnershipToFinalOwner(
diamondAddress: string,
appRegistryAddress: string,
datasetRegistryAddress: string,
workerpoolRegistryAddress: string,
currentOwner: SignerWithAddress,
ownerAddress: string,
) {
for (const contract of [
{ name: 'Diamond', address: diamondAddress },
{ name: 'AppRegistry', address: appRegistryAddress },
{ name: 'DatasetRegistry', address: datasetRegistryAddress },
{ name: 'WorkerpoolRegistry', address: workerpoolRegistryAddress },
]) {
await Ownable__factory.connect(contract.address, currentOwner)
.transferOwnership(ownerAddress)
.then((tx) => tx.wait());
console.log(`Owner of ${contract.name}: ${ownerAddress}`);
}
}
1 change: 1 addition & 0 deletions utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type ChainConfig = {
asset: string;
token?: string | null; // The token deployed should be compatible with Approve and call
richman?: string | null; // The richman account is needed if the token is already deployed
owner?: string | null;
uniswap?: boolean;
etoken?: string;
v3: {
Expand Down