|
| 1 | +// SPDX-FileCopyrightText: 2024 IEXEC BLOCKCHAIN TECH <contact@iex.ec> |
| 2 | +// SPDX-License-Identifier: Apache-2.0 |
| 3 | + |
| 4 | +import hre, { deployments, ethers } from 'hardhat'; |
| 5 | +import { |
| 6 | + ENS, |
| 7 | + ENSIntegration__factory, |
| 8 | + ENSRegistry__factory, |
| 9 | + FIFSRegistrar, |
| 10 | + FIFSRegistrar__factory, |
| 11 | + IexecAccessors__factory, |
| 12 | + PublicResolver, |
| 13 | + PublicResolver__factory, |
| 14 | + ReverseRegistrar, |
| 15 | + ReverseRegistrar__factory, |
| 16 | +} from '../typechain'; |
| 17 | +import { deploy } from '../utils/deploy-tools'; |
| 18 | + |
| 19 | +module.exports = async function () { |
| 20 | + console.log('Deploying and configuring ENS..'); |
| 21 | + const chainId = (await ethers.provider.getNetwork()).chainId; |
| 22 | + if (chainId < 1000) { |
| 23 | + // skip ENS setup for mainnet and testnet |
| 24 | + console.log('Skipping ENS for public networks'); |
| 25 | + return; |
| 26 | + } |
| 27 | + const [owner] = await hre.ethers.getSigners(); |
| 28 | + const erc1538ProxyAddress = (await deployments.get('ERC1538Proxy')).address; |
| 29 | + const iexecAccessorsInstance = IexecAccessors__factory.connect(erc1538ProxyAddress, owner); |
| 30 | + const appRegistryAddress = await iexecAccessorsInstance.appregistry(); |
| 31 | + const datasetRegistryAddress = await iexecAccessorsInstance.datasetregistry(); |
| 32 | + const workerpoolRegistryAddress = await iexecAccessorsInstance.workerpoolregistry(); |
| 33 | + const ens = (await deploy(new ENSRegistry__factory(), owner, [])) as ENS; |
| 34 | + const resolver = (await deploy(new PublicResolver__factory(), owner, [ |
| 35 | + ens.address, |
| 36 | + ])) as PublicResolver; |
| 37 | + const reverseRegistrar = (await deploy(new ReverseRegistrar__factory(), owner, [ |
| 38 | + ens.address, |
| 39 | + resolver.address, |
| 40 | + ])) as ReverseRegistrar; |
| 41 | + const registrars: { [name: string]: FIFSRegistrar } = {}; |
| 42 | + // root registrar |
| 43 | + await registerDomain(''); |
| 44 | + await registrars[''].register(labelhash('reverse'), owner.address).then((tx) => tx.wait()); |
| 45 | + await ens |
| 46 | + .setSubnodeOwner( |
| 47 | + ethers.utils.namehash('reverse'), |
| 48 | + labelhash('addr'), |
| 49 | + reverseRegistrar.address, |
| 50 | + ) |
| 51 | + .then((tx) => tx.wait()); |
| 52 | + await registerDomain('eth'); |
| 53 | + await registerDomain('iexec', 'eth'); |
| 54 | + await registerDomain('v5', 'iexec.eth'); |
| 55 | + await registerDomain('users', 'iexec.eth'); |
| 56 | + await registerDomain('apps', 'iexec.eth'); |
| 57 | + await registerDomain('datasets', 'iexec.eth'); |
| 58 | + await registerDomain('pools', 'iexec.eth'); |
| 59 | + await registerAddress('admin', 'iexec.eth', owner.address); |
| 60 | + await registerAddress('rlc', 'iexec.eth', await iexecAccessorsInstance.token()); |
| 61 | + await registerAddress('core', 'v5.iexec.eth', erc1538ProxyAddress); |
| 62 | + await registerAddress('apps', 'v5.iexec.eth', appRegistryAddress); |
| 63 | + await registerAddress('datasets', 'v5.iexec.eth', datasetRegistryAddress); |
| 64 | + await registerAddress('workerpools', 'v5.iexec.eth', workerpoolRegistryAddress); |
| 65 | + await reverseRegistrar.setName('admin.iexec.eth').then((tx) => tx.wait()); |
| 66 | + await setReverseName(erc1538ProxyAddress, 'core.v5.iexec.eth'); |
| 67 | + await setReverseName(appRegistryAddress, 'apps.v5.iexec.eth'); |
| 68 | + await setReverseName(datasetRegistryAddress, 'datasets.v5.iexec.eth'); |
| 69 | + await setReverseName(workerpoolRegistryAddress, 'workerpools.v5.iexec.eth'); |
| 70 | + |
| 71 | + /** |
| 72 | + * Register domain on ENS. |
| 73 | + */ |
| 74 | + async function registerDomain(label: string, domain: string = '') { |
| 75 | + const name = domain ? `${label}.${domain}` : `${label}`; |
| 76 | + const labelHash = label ? labelhash(label) : ethers.constants.HashZero; |
| 77 | + const nameHash = name ? ethers.utils.namehash(name) : ethers.constants.HashZero; |
| 78 | + const existingRegistrarAddress = await ens.owner(nameHash); |
| 79 | + let registrar; |
| 80 | + if ((await ethers.provider.getCode(existingRegistrarAddress)) == '0x') { |
| 81 | + registrar = (await deploy( |
| 82 | + new FIFSRegistrar__factory(), |
| 83 | + owner, |
| 84 | + [ens.address, nameHash], |
| 85 | + { quiet: true }, |
| 86 | + )) as FIFSRegistrar; |
| 87 | + if (!!name) { |
| 88 | + await registrars[domain] |
| 89 | + .register(labelHash, registrar.address) |
| 90 | + .then((tx) => tx.wait()); |
| 91 | + } else { |
| 92 | + await ens.setOwner(nameHash, registrar.address).then((tx) => tx.wait()); |
| 93 | + } |
| 94 | + } else { |
| 95 | + registrar = FIFSRegistrar__factory.connect(existingRegistrarAddress, ethers.provider); |
| 96 | + } |
| 97 | + registrars[name] = registrar; |
| 98 | + console.log(`FIFSRegistrar for domain ${name}: ${registrars[name].address}`); |
| 99 | + return registrar; |
| 100 | + } |
| 101 | + |
| 102 | + /** |
| 103 | + * Register address on ENS. |
| 104 | + */ |
| 105 | + async function registerAddress(label: string, domain: string, address: string) { |
| 106 | + const name = `${label}.${domain}`; |
| 107 | + const labelHash = labelhash(label); |
| 108 | + const nameHash = ethers.utils.namehash(name); |
| 109 | + // register as subdomain |
| 110 | + await registrars[domain] |
| 111 | + .connect(owner) |
| 112 | + .register(labelHash, owner.address) |
| 113 | + .then((tx) => tx.wait()); |
| 114 | + // link to ens (resolver & addr) |
| 115 | + await ens |
| 116 | + .connect(owner) |
| 117 | + .setResolver(nameHash, resolver.address) |
| 118 | + .then((tx) => tx.wait()); |
| 119 | + await resolver |
| 120 | + .connect(owner) |
| 121 | + ['setAddr(bytes32,uint256,bytes)'](nameHash, 60, address) |
| 122 | + .then((tx) => tx.wait()); |
| 123 | + } |
| 124 | + |
| 125 | + /** |
| 126 | + * Set ENS reverse name of contract. |
| 127 | + */ |
| 128 | + async function setReverseName(contractAddress: string, name: string) { |
| 129 | + await ENSIntegration__factory.connect(contractAddress, owner) |
| 130 | + .setName(ens.address, name) |
| 131 | + .then((tx) => tx.wait()); |
| 132 | + } |
| 133 | + |
| 134 | + /** |
| 135 | + * Hash a label for the ENS. |
| 136 | + * See: https://docs.ens.domains/resolution/names#labelhash |
| 137 | + */ |
| 138 | + function labelhash(label: string) { |
| 139 | + return ethers.utils.id(label.toLowerCase()); |
| 140 | + } |
| 141 | +}; |
0 commit comments