diff --git a/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/package.json b/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/package.json index be1c31ada1..d46942cef9 100644 --- a/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/package.json +++ b/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/package.json @@ -9,13 +9,12 @@ "build" ], "dependencies": { - "@ensdomains/ens": "0.4.4", - "@ensdomains/resolver": "0.2.4", + "@ensdomains/ens-contracts": "0.0.22", "content-hash": "2.5.2", - "eth-ens-namehash": "2.0.8", "ethers": "5.6.6" }, "devDependencies": { + "@types/node": "18.15.3", "rimraf": "3.0.2", "ts-node": "10.9.1", "typescript": "4.9.5" diff --git a/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/deployENS.ts b/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/deployENS.ts index f651293684..7de63811fe 100644 --- a/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/deployENS.ts +++ b/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/deployENS.ts @@ -1,11 +1,20 @@ -import { loadContract, deploy, utf8ToKeccak256 } from "./utils"; +import { loadContract, deploy, utf8ToKeccak256, computeInterfaceId } from "./utils"; import { ethers } from "ethers"; -const ensJSON = loadContract("ens", "ENSRegistry"); -const fifsRegistrarJSON = loadContract("ens", "FIFSRegistrar"); -const reverseRegistrarJSON = loadContract("ens", "ReverseRegistrar"); -const publicResolverJSON = loadContract("resolver", "PublicResolver"); +const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; + +const ensJSON = loadContract( "registry", "ENSRegistry"); +const dummyOracleJSON = loadContract( "ethregistrar", "DummyOracle"); +const stablePriceOracleJSON = loadContract( "ethregistrar", "StablePriceOracle"); +const baseRegistrarJSON = loadContract( "ethregistrar", "BaseRegistrarImplementation"); +const ethControllerJSON = loadContract( "deployments", "ETHRegistrarController"); +const reverseRegistrarJSON = loadContract("deployments", "ReverseRegistrar"); +const nameWrapperJSON = loadContract( "deployments", "NameWrapper"); +const publicResolverJSON = loadContract( "deployments", "PublicResolver"); + +const iNameWrapperJSON = loadContract( "wrapper", "INameWrapper"); +const iEthControllerJSON = loadContract( "ethregistrar", "IETHRegistrarController"); const tld = "eth"; @@ -13,65 +22,109 @@ export async function deployENS(provider: ethers.providers.JsonRpcProvider) { const signer = provider.getSigner(); const signerAddress = await signer.getAddress(); // Registry + console.log("deploying registry"); const ens = await deploy(provider, ensJSON); - // Resolver - const resolver = await deploy(provider, publicResolverJSON, ens.address); - await setupResolver(ens, resolver, signerAddress); + // Reverse Registrar + console.log("deploying reverse registrar"); + const reverse = await deploy( + provider, + reverseRegistrarJSON, + ens.address + ); + console.log("setting up reverse registrar"); + await setupReverseRegistrar(ens, reverse, signerAddress); - // Registrar - const registrar = await deploy( + // Base Registrar + console.log("deploying base registrar"); + const baseRegistrar = await deploy( provider, - fifsRegistrarJSON, + baseRegistrarJSON, ens.address, ethers.utils.namehash(tld) ); - await setupRegistrar(ens, registrar, signerAddress); + console.log("setting up eth registrar"); + await setupBaseRegistrar(ens, baseRegistrar); - // Reverse Registrar - const reverse = await deploy( + // Name Wrapper + console.log("deploying name wrapper"); + const nameWrapper = await deploy( provider, - reverseRegistrarJSON, + nameWrapperJSON, ens.address, - resolver.address + baseRegistrar.address, + ZERO_ADDRESS, ); - await setupReverseRegistrar(ens, reverse, signerAddress); + console.log("setting up name wrapper"); + await setupNameWrapper(baseRegistrar, nameWrapper); + + // Eth Registrar Controller + console.log("deploying dummy oracle") + const dummyOracle = await deploy( + provider, + dummyOracleJSON, + 0 + ); + console.log("deploying stable price oracle") + const stablePriceOracle = await deploy( + provider, + stablePriceOracleJSON, + dummyOracle.address, + [0, 0, 0, 0, 0], + ); + console.log("deploying eth registrar controller"); + const ethController: ethers.Contract = await deploy( + provider, + ethControllerJSON, + baseRegistrar.address, + stablePriceOracle.address, + 1, + 3655, + reverse.address, + nameWrapper.address, + ens.address, + ); + await setupEthRegistrar(ethController, nameWrapper, reverse); + + // Resolver + console.log("deploying resolver") + const resolver = await deploy( + provider, + publicResolverJSON, + ens.address, + nameWrapper.address, + ethController.address, + reverse.address, + ); + console.log("setting up resolver") + await setupResolver(ens, resolver, reverse, nameWrapper, ethController); return { ensAddress: ens.address, resolverAddress: resolver.address, - registrarAddress: registrar.address, + registrarAddress: ethController.address, reverseAddress: reverse.address, }; } -async function setupResolver( +async function setupBaseRegistrar( ens: ethers.Contract, - resolver: ethers.Contract, - accountAddress: string + registrar: ethers.Contract ) { - const resolverNode = ethers.utils.namehash("resolver"); - const resolverLabel = utf8ToKeccak256("resolver"); - await ens.setSubnodeOwner( ethers.utils.hexZeroPad(ethers.constants.AddressZero, 32), - resolverLabel, - accountAddress + utf8ToKeccak256(tld), + registrar.address ); - await ens.setResolver(resolverNode, resolver.address); - await resolver["setAddr(bytes32,address)"](resolverNode, resolver.address); } -async function setupRegistrar( - ens: ethers.Contract, - registrar: ethers.Contract, - accountAddress: string +async function setupEthRegistrar( + ethController: ethers.Contract, + nameWrapper: ethers.Contract, + reverseRegistrar: ethers.Contract, ) { - await ens.setSubnodeOwner( - ethers.utils.hexZeroPad(ethers.constants.AddressZero, 32), - utf8ToKeccak256(tld), - registrar.address - ); + await nameWrapper.setController(ethController.address, true); + await reverseRegistrar.setController(ethController.address, true); } async function setupReverseRegistrar( @@ -90,3 +143,38 @@ async function setupReverseRegistrar( reverseRegistrar.address ); } + +async function setupResolver( + ens: ethers.Contract, + resolver: ethers.Contract, + reverseRegistrar: ethers.Contract, + nameWrapper: ethers.Contract, + ethController: ethers.Contract, +) { + const tldNode = ethers.utils.namehash("eth"); + + const iNameWrapper = new ethers.utils.Interface(iNameWrapperJSON.abi) + const iNameWrapperId = computeInterfaceId(iNameWrapper); + console.log(`setting resolver iNameWrapper interface with id ${iNameWrapperId}`) + await resolver.setInterface(tldNode, iNameWrapperId, nameWrapper.address); + + const iEthController = new ethers.utils.Interface(iEthControllerJSON.abi) + const iEthControllerId = computeInterfaceId(iEthController); + console.log(`setting resolver iEthController interface with id ${iEthControllerId}`) + await resolver.setInterface(tldNode, iEthControllerId, ethController.address); + + const resolverNode = ethers.utils.namehash("resolver.eth"); + console.log("calling ens.setResolver") + await ens.setResolver(resolverNode, resolver.address); + console.log("calling resolver.setAddr") + await resolver.setAddr(resolverNode, resolver.address); + console.log("calling reverseRegistrar.setDefaultResolver") + await reverseRegistrar.setDefaultResolver(resolver.address); +} + +async function setupNameWrapper( + registrar: ethers.Contract, + nameWrapper: ethers.Contract, +) { + await registrar.addController(nameWrapper.address) +} diff --git a/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/registerENS.ts b/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/registerENS.ts index fb4e6106fb..b09c13baea 100644 --- a/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/registerENS.ts +++ b/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/registerENS.ts @@ -3,9 +3,10 @@ import { loadContract, utf8ToKeccak256 } from "./utils"; import { ethers } from "ethers"; const contentHash = require("content-hash"); -const ensJSON = loadContract("ens", "ENSRegistry"); -const fifsRegistrarJSON = loadContract("ens", "FIFSRegistrar"); -const publicResolverJSON = loadContract("resolver", "PublicResolver"); + +const ensJSON = loadContract( "registry", "ENSRegistry"); +const fifsRegistrarJSON = loadContract( "registry", "FIFSRegistrar"); +const publicResolverJSON = loadContract( "deployments", "PublicResolver"); interface RegisterArgs { provider: ethers.providers.JsonRpcProvider; diff --git a/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/utils.ts b/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/utils.ts index 732621c30e..2a3ad2dbe3 100644 --- a/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/utils.ts +++ b/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/ens/scripts/src/utils/utils.ts @@ -5,15 +5,11 @@ interface ContractJson { bytecode: string; } -export function loadContract( - modName: string, - contractName: string -): ContractJson { - if (modName === "ens") { - const ens = require(`@ensdomains/ens`); - return ens[contractName]; +export function loadContract(modName: string, contractName: string): ContractJson { + if (modName === "deployments") { + return require(`@ensdomains/ens-contracts/deployments/mainnet/${contractName}`); } - return require(`@ensdomains/${modName}/build/contracts/${contractName}`); + return require(`@ensdomains/ens-contracts/artifacts/contracts/${modName}/${contractName}.sol/${contractName}`); } export async function deploy( @@ -32,6 +28,33 @@ export async function deploy( return contract; } -export async function utf8ToKeccak256(value: string) { +export function utf8ToKeccak256(value: string) { return ethers.utils.keccak256(ethers.utils.toUtf8Bytes(value)); } + +export function computeInterfaceId(iface: ethers.utils.Interface) { + const functions = Object.values(iface.functions); + const sigHashes = functions.map((frag) => frag.format('sighash')); + return makeInterfaceIdERC165(sigHashes); +} + +// see https://github.com/OpenZeppelin/openzeppelin-test-helpers/blob/master/src/makeInterfaceId.js +function makeInterfaceIdERC165 (functionSignatures: string[] = []) { + const INTERFACE_ID_LENGTH = 4; + + const interfaceIdBuffer = functionSignatures + .map(signature => utf8ToKeccak256(signature)) // keccak256 + .map(h => + Buffer + .from(h.substring(2), 'hex') + .slice(0, 4) // bytes4() + ) + .reduce((memo, bytes) => { + for (let i = 0; i < INTERFACE_ID_LENGTH; i++) { + memo[i] = memo[i] ^ bytes[i]; // xor + } + return memo; + }, Buffer.alloc(INTERFACE_ID_LENGTH)); + + return `0x${interfaceIdBuffer.toString('hex')}`; +} diff --git a/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/index.ts b/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/index.ts index cdbae7c62a..0ef2f12644 100644 --- a/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/index.ts +++ b/packages/cli/src/lib/defaults/infra-modules/eth-ens-ipfs/index.ts @@ -5,9 +5,9 @@ export const ETH_ENS_IPFS_MODULE_CONSTANTS = { ethereumProvider: "http://localhost:8545", ensAddresses: { ensAddress: "0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab", - resolverAddress: "0x5b1869D9A4C187F2EAa108f3062412ecf0526b24", - registrarAddress: "0xD833215cBcc3f914bD1C9ece3EE7BF8B14f841bb", - reverseAddress: "0xe982E462b094850F12AF94d21D470e21bE9D0E9C", + resolverAddress: "0x9561C133DD8580860B6b7E504bC5Aa500f0f06a7", + registrarAddress: "0x5b1869D9A4C187F2EAa108f3062412ecf0526b24", + reverseAddress: "0x254dffcd3277C0b1660F6d42EFbB754edaBAbC2B", } } as const; // $end diff --git a/yarn.lock b/yarn.lock index 2415cf732f..8fd5d05d8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3232,6 +3232,18 @@ array.prototype.reduce@^1.0.5: es-array-method-boxes-properly "^1.0.0" is-string "^1.0.7" +arraybuffer.prototype.slice@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz#9b5ea3868a6eebc30273da577eb888381c0044bb" + integrity sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -3661,9 +3673,9 @@ camelcase@^6.0.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001503: - version "1.0.30001515" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001515.tgz#418aefeed9d024cd3129bfae0ccc782d4cb8f12b" - integrity sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA== + version "1.0.30001516" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz#621b1be7d85a8843ee7d210fd9d87b52e3daab3a" + integrity sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g== capture-exit@^2.0.0: version "2.0.0" @@ -4438,9 +4450,9 @@ ecc-jsbn@~0.1.1: safer-buffer "^2.1.0" electron-to-chromium@^1.4.431: - version "1.4.460" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.460.tgz#f360a5059c039c4a5fb4dfa99680ad8129dd9f84" - integrity sha512-kKiHnbrHME7z8E6AYaw0ehyxY5+hdaRmeUbjBO22LZMdqTYCO29EvF0T1cQ3pJ1RN5fyMcHl1Lmcsdt9WWJpJQ== + version "1.4.463" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.463.tgz#8eb04355f24fef5c8097661d14e143f6d8554055" + integrity sha512-fT3hvdUWLjDbaTGzyOjng/CQhQJSQP8ThO3XZAoaxHvHo2kUXiRQVMj9M235l8uDFiNPsPa6KHT1p3RaR6ugRw== elliptic@6.5.4: version "6.5.4" @@ -4514,11 +4526,12 @@ error-ex@^1.2.0, error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: - version "1.21.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.3.tgz#8aaa0ffc080e8a6fef6ace72631dc1ec5d47bf94" - integrity sha512-ZU4miiY1j3sGPFLJ34VJXEqhpmL+HGByCinGHv4HC+Fxl2fI2Z4yR6tl0mORnDr6PA8eihWo4LmSWDbvhALckg== + version "1.22.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc" + integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw== dependencies: array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.1" available-typed-arrays "^1.0.5" call-bind "^1.0.2" es-set-tostringtag "^2.0.1" @@ -4545,10 +4558,13 @@ es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: object-keys "^1.1.1" object.assign "^4.1.4" regexp.prototype.flags "^1.5.0" + safe-array-concat "^1.0.0" safe-regex-test "^1.0.0" string.prototype.trim "^1.2.7" string.prototype.trimend "^1.0.6" string.prototype.trimstart "^1.0.6" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" typed-array-byte-offset "^1.0.0" typed-array-length "^1.0.4" unbox-primitive "^1.0.2" @@ -6158,15 +6174,11 @@ is-text-path@^1.0.1: text-extensions "^1.0.0" is-typed-array@^1.1.10, is-typed-array@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" + which-typed-array "^1.1.11" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" @@ -9732,6 +9744,25 @@ type@^2.7.2: resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + typed-array-byte-offset@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" @@ -10091,17 +10122,16 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== -which-typed-array@^1.1.10: - version "1.1.10" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.10.tgz#74baa2789991905c2076abb317103b866c64e69e" - integrity sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA== +which-typed-array@^1.1.10, which-typed-array@^1.1.11: + version "1.1.11" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" + integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== dependencies: available-typed-arrays "^1.0.5" call-bind "^1.0.2" for-each "^0.3.3" gopd "^1.0.1" has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" which@^1.2.9, which@^1.3.1: version "1.3.1"