From 61195cac23853fb0781ac9de762ecf54943ff42b Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Fri, 7 Feb 2025 10:03:38 +0100 Subject: [PATCH 01/12] update constant file to be typed --- test/000_fullchain-boost.test.ts | 2 +- .../IexecPoco/IexecPoco2-claim.test.ts | 2 +- .../IexecPocoBoost/IexecPocoBoost.test.ts | 2 +- utils/constants.d.ts | 10 ------ utils/{constants.js => constants.ts} | 36 ++++++++----------- utils/createOrders.ts | 4 +-- 6 files changed, 20 insertions(+), 36 deletions(-) delete mode 100644 utils/constants.d.ts rename utils/{constants.js => constants.ts} (63%) diff --git a/test/000_fullchain-boost.test.ts b/test/000_fullchain-boost.test.ts index 1c5324161..d799392e5 100644 --- a/test/000_fullchain-boost.test.ts +++ b/test/000_fullchain-boost.test.ts @@ -17,7 +17,7 @@ import { TestClient__factory, WorkerpoolInterface__factory, } from '../typechain'; -import constants from '../utils/constants'; +import * as constants from '../utils/constants'; import { OrdersActors, OrdersAssets, diff --git a/test/byContract/IexecPoco/IexecPoco2-claim.test.ts b/test/byContract/IexecPoco/IexecPoco2-claim.test.ts index 0e95fd6d5..3376b4fcb 100644 --- a/test/byContract/IexecPoco/IexecPoco2-claim.test.ts +++ b/test/byContract/IexecPoco/IexecPoco2-claim.test.ts @@ -17,7 +17,7 @@ import { getTaskId, } from '../../../utils/poco-tools'; import { IexecWrapper } from '../../utils/IexecWrapper'; -import constants from './../../../utils/constants'; +import * as constants from './../../../utils/constants'; const categoryTime = 300; const maxDealDuration = 10 * categoryTime; diff --git a/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts b/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts index e8db113b6..5ddc20ef1 100644 --- a/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts +++ b/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts @@ -33,7 +33,7 @@ import { TestClient, TestClient__factory, } from '../../../typechain'; -import constants from '../../../utils/constants'; +import * as constants from '../../../utils/constants'; import { IexecOrders, OrdersActors, diff --git a/utils/constants.d.ts b/utils/constants.d.ts deleted file mode 100644 index 37441f3b4..000000000 --- a/utils/constants.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-FileCopyrightText: 2023 IEXEC BLOCKCHAIN TECH -// SPDX-License-Identifier: Apache-2.0 - -export declare const NULL: { - ADDRESS: string; - BYTES32: string; - SIGNATURE: string; -}; - -export declare const MULTIADDR_BYTES: string; diff --git a/utils/constants.js b/utils/constants.ts similarity index 63% rename from utils/constants.js rename to utils/constants.ts index 5123a5ebd..b438f8edd 100644 --- a/utils/constants.js +++ b/utils/constants.ts @@ -1,16 +1,12 @@ -// SPDX-FileCopyrightText: 2020 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2024 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 -function define(name, value) { - Object.defineProperty(exports, name, { value: value, enumerable: true }); -} - //config -define('EVENT_WAIT_TIMEOUT', 100000); -define('AMOUNT_GAS_PROVIDED', 4500000); -//define("AMOUNT_GAS_PROVIDED", 0xFFFFFFFFFFFFFFFF); +export const EVENT_WAIT_TIMEOUT = 100000; +export const AMOUNT_GAS_PROVIDED = 4500000; +// export const AMOUNT_GAS_PROVIDED = "0xFFFFFFFFFFFFFFFF"; -define('NULL', { +export const NULL = { ADDRESS: '0x0000000000000000000000000000000000000000', BYTES32: '0x0000000000000000000000000000000000000000000000000000000000000000', SIGNATURE: '0x', @@ -25,29 +21,27 @@ define('NULL', { salt: '0x0000000000000000000000000000000000000000000000000000000000000000', sign: '0x', }, -}); +}; // ENUM -define('OrderOperationEnum', { +export const OrderOperationEnum = { SIGN: 0, CLOSE: 1, -}); -define('TaskStatusEnum', { +}; +export const TaskStatusEnum = { UNSET: 0, ACTIVE: 1, REVEALING: 2, COMPLETED: 3, FAILED: 4, -}); -define('ContributionStatusEnum', { +}; +export const ContributionStatusEnum = { UNSET: 0, CONTRIBUTED: 1, PROVED: 2, REJECTED: 3, -}); +}; -define('MULTIADDR', '/ipfs/QmRwwTz9Chq4Y7F7ReKKcx1GV6s3H7egmNGrku9XrwiDa8'); -define( - 'MULTIADDR_BYTES', - '0xa503221220359d55f58a43126d4ba446a35940265eb2dab57ecbc439e7f105c558f8774819', -); +export const MULTIADDR = '/ipfs/QmRwwTz9Chq4Y7F7ReKKcx1GV6s3H7egmNGrku9XrwiDa8'; +export const MULTIADDR_BYTES = + '0xa503221220359d55f58a43126d4ba446a35940265eb2dab57ecbc439e7f105c558f8774819'; diff --git a/utils/createOrders.ts b/utils/createOrders.ts index e33e4e0ea..9133b80de 100644 --- a/utils/createOrders.ts +++ b/utils/createOrders.ts @@ -6,7 +6,7 @@ import { BigNumber } from '@ethersproject/bignumber'; import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { ethers } from 'hardhat'; import { IexecLibOrders_v5 } from '../typechain'; -import constants, { NULL } from './constants'; +import * as constants from './constants'; import { utils } from './odb-tools'; import { OrderOperationEnum } from './poco-tools'; @@ -168,7 +168,7 @@ export function createEmptyDatasetOrder(): IexecLibOrders_v5.DatasetOrderStruct * Create an order operation from an existing order. */ export function createOrderOperation(order: OrderType, operation: OrderOperationEnum) { - return { order, operation: BigNumber.from(operation), sign: NULL.SIGNATURE }; + return { order, operation: BigNumber.from(operation), sign: constants.NULL.SIGNATURE }; } export function buildOrders(matchOrdersArgs: MatchOrdersArgs) { From 9f8cac96c5fdf0c2461ec34a16f158d5b4af51d6 Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Fri, 7 Feb 2025 14:18:11 +0100 Subject: [PATCH 02/12] update odb-tools in TS --- utils/createOrders.ts | 8 ++-- utils/{odb-tools.js => odb-tools.ts} | 57 ++++++++++++++++++---------- 2 files changed, 42 insertions(+), 23 deletions(-) rename utils/{odb-tools.js => odb-tools.ts} (80%) diff --git a/utils/createOrders.ts b/utils/createOrders.ts index 9133b80de..ca2b8b514 100644 --- a/utils/createOrders.ts +++ b/utils/createOrders.ts @@ -7,7 +7,7 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { ethers } from 'hardhat'; import { IexecLibOrders_v5 } from '../typechain'; import * as constants from './constants'; -import { utils } from './odb-tools'; +import { hashStruct, signStruct } from './odb-tools'; import { OrderOperationEnum } from './poco-tools'; export interface OrdersAssets { @@ -295,7 +295,7 @@ export async function signOrder( order: Record, signer: SignerWithAddress, ): Promise { - return utils.signStruct(getTypeOf(order), order, domain, signer); + return signStruct(getTypeOf(order), order, domain, signer); } /** @@ -307,7 +307,7 @@ export async function signOrderOperation( orderOperation: OrderOperation, signer: SignerWithAddress, ): Promise { - return utils.signStruct( + return signStruct( getTypeOf(orderOperation.order) + 'Operation', orderOperation, domain, @@ -320,7 +320,7 @@ export async function signOrderOperation( * @returns order hash */ export function hashOrder(domain: TypedDataDomain, order: Record): string { - return utils.hashStruct(getTypeOf(order), order, domain); + return hashStruct(getTypeOf(order), order, domain); } /** diff --git a/utils/odb-tools.js b/utils/odb-tools.ts similarity index 80% rename from utils/odb-tools.js rename to utils/odb-tools.ts index 80423553a..c53c75ff1 100644 --- a/utils/odb-tools.js +++ b/utils/odb-tools.ts @@ -1,9 +1,19 @@ // SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 -const ethers = require('ethers'); +import { TypedDataDomain, TypedDataField, ethers } from 'ethers'; +import hre from 'hardhat'; -const TYPES = { +interface WalletInfo { + privateKey?: string; + address?: string; +} + +interface Types { + [key: string]: Array; +} + +const TYPES: Types = { EIP712Domain: [ { type: 'string', name: 'name' }, { type: 'string', name: 'version' }, @@ -77,9 +87,9 @@ const TYPES = { ], }; -function buildTypes(primaryType) { +function buildTypes(primaryType: string): Types { const OPERATION = 'Operation'; - const types = { + const types: Types = { [primaryType]: TYPES[primaryType], }; @@ -92,7 +102,12 @@ function buildTypes(primaryType) { return types; } -function eth_signTypedData(primaryType, message, domain, wallet) { +async function eth_signTypedData( + primaryType: string, + message: Record, + domain: TypedDataDomain, + wallet: WalletInfo, +): Promise { return new Promise((resolve, reject) => { const typedDataDomain = { name: domain.name, @@ -108,7 +123,12 @@ function eth_signTypedData(primaryType, message, domain, wallet) { const walletInstance = new ethers.Wallet(wallet.privateKey, hre.ethers.provider); signerPromise = Promise.resolve(walletInstance); } else { - signerPromise = hre.ethers.getSigner(wallet.address); + if (wallet.address) { + signerPromise = hre.ethers.getSigner(wallet.address); + } else { + reject(new Error('Wallet address is undefined')); + return; + } } signerPromise @@ -118,15 +138,24 @@ function eth_signTypedData(primaryType, message, domain, wallet) { }); } -function signStruct(primaryType, message, domain, wallet) { +export async function signStruct( + primaryType: string, + message: Record, + domain: TypedDataDomain, + wallet: WalletInfo, +): Promise> { return eth_signTypedData(primaryType, message, domain, wallet).then((sign) => { message.sign = sign; return message; }); } -function hashStruct(primaryType, message, domain) { - let typedDataDomain = { +export function hashStruct( + primaryType: string, + message: Record, + domain: TypedDataDomain, +): string { + const typedDataDomain: TypedDataDomain = { name: domain.name, version: domain.version, chainId: domain.chainId, @@ -138,13 +167,3 @@ function hashStruct(primaryType, message, domain) { return ethers.utils._TypedDataEncoder.hash(typedDataDomain, types, message); } - -/***************************************************************************** - * MODULE * - *****************************************************************************/ -module.exports = { - utils: { - signStruct, - hashStruct, - }, -}; From d6292ac50e98c9fca51eb5011b7da7f9361151ef Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Fri, 7 Feb 2025 16:02:22 +0100 Subject: [PATCH 03/12] updtate FactoryDeployer to TS --- ...{FactoryDeployer.js => FactoryDeployer.ts} | 117 ++++++++++++------ 1 file changed, 79 insertions(+), 38 deletions(-) rename utils/{FactoryDeployer.js => FactoryDeployer.ts} (60%) diff --git a/utils/FactoryDeployer.js b/utils/FactoryDeployer.ts similarity index 60% rename from utils/FactoryDeployer.js rename to utils/FactoryDeployer.ts index b09de2d75..a286ba370 100644 --- a/utils/FactoryDeployer.js +++ b/utils/FactoryDeployer.ts @@ -1,25 +1,67 @@ // SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 -const { ethers } = require('ethers'); -const FACTORY = - require('../config/config.json').chains.default.asset == 'Token' && - hre.network.name.includes('hardhat') // Required until dev-token chain EIPs are updated - ? require('@amxx/factory/deployments/GenericFactory_shanghai.json') - : require('@amxx/factory/deployments/GenericFactory.json'); - -async function waitTx(txPromise) { +import { Contract, ethers } from 'ethers'; +import hre from 'hardhat'; + +import factoryJson from '@amxx/factory/deployments/GenericFactory.json'; +import factoryShanghaiJson from '@amxx/factory/deployments/GenericFactory_shanghai.json'; +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; +import config from '../config/config.json'; + +interface FactoryConfig { + address: string; + deployer: string; + cost: string; + tx: string; + abi: any[]; +} + +interface DeployOptions { + libraries?: any[]; + salt?: string; + call?: string; + [key: string]: any; +} + +interface Artefact { + contractName: string; + abi: any[]; + bytecode: string; + at: (address: string) => Promise; + setAsDeployed: (instance: any) => void; + _hArtifact: { + sourceName: string; + contractName: string; + linkReferences?: { + [key: string]: { + [key: string]: Array<{ + start: number; + length: number; + }>; + }; + }; + }; +} + +const FACTORY: FactoryConfig = + config.chains.default.asset === 'Token' && hre.network.name.includes('hardhat') + ? factoryShanghaiJson + : factoryJson; + +async function waitTx(txPromise: Promise): Promise { await (await txPromise).wait(); } -class EthersDeployer { - // factory: ethers.Contract - // factoryAsPromise: Promise +export class EthersDeployer { + private factory!: Contract; + private factoryAsPromise: Promise; + private options: DeployOptions; - constructor(wallet, options = {}) { + constructor(wallet: SignerWithAddress, options: DeployOptions = {}) { this.options = options; this.factoryAsPromise = new Promise(async (resolve, reject) => { - if ((await wallet.provider.getCode(FACTORY.address)) !== '0x') { + if ((await wallet.provider!.getCode(FACTORY.address)) !== '0x') { console.debug(`→ Factory is available on this network`); } else { try { @@ -27,7 +69,7 @@ class EthersDeployer { await waitTx( wallet.sendTransaction({ to: FACTORY.deployer, value: FACTORY.cost }), ); - await waitTx(wallet.provider.sendTransaction(FACTORY.tx)); + await waitTx(wallet.provider!.sendTransaction(FACTORY.tx)); console.debug(`→ Factory successfully deployed`); } catch (e) { console.debug(`→ Error deploying the factory`); @@ -39,39 +81,43 @@ class EthersDeployer { }); } - async ready() { + async ready(): Promise { await this.factoryAsPromise; } - async deploy(artefact, ...extra) { + async deploy(artefact: Artefact, ...extra: any[]): Promise { await this.ready(); console.log(`[factoryDeployer] ${artefact.contractName}`); - const constructorABI = artefact.abi.find((e) => e.type == 'constructor'); + + const constructorABI = artefact.abi.find((e) => e.type === 'constructor'); const argsCount = constructorABI ? constructorABI.inputs.length : 0; const args = extra.slice(0, argsCount); - const options = { ...this.options, ...extra[argsCount] }; - var librariesLinkPlaceHolderAndAddress = []; + const options: DeployOptions = { ...this.options, ...extra[argsCount] }; + + let librariesLinkPlaceHolderAndAddress: any[] = []; if (options.libraries) { librariesLinkPlaceHolderAndAddress = await Promise.all( options.libraries.map(async (library) => { const linkPlaceholder = this.getLinkPlaceholder(library, artefact); if (linkPlaceholder) { return { - linkPlaceholder: linkPlaceholder, + linkPlaceholder, address: (await library.deployed()).address, }; } + return undefined; }), ); } - var coreCode = artefact.bytecode; + + let coreCode = artefact.bytecode; librariesLinkPlaceHolderAndAddress - .filter((data) => data != undefined) + .filter( + (data): data is { linkPlaceholder: string; address: string } => data !== undefined, + ) .forEach((element) => { - // Replace `__$9d824026d0515d8abd681f0f0f4707f16a$__` - // by address library without 0x prefix - coreCode = coreCode.replaceAll( - element.linkPlaceholder, + coreCode = coreCode.replace( + new RegExp(element.linkPlaceholder, 'g'), element.address.slice(2).toLowerCase(), ); }); @@ -79,18 +125,19 @@ class EthersDeployer { const argsCode = constructorABI ? ethers.utils.defaultAbiCoder .encode( - constructorABI.inputs.map((e) => e.type), + constructorABI.inputs.map((e: { type: string }) => e.type), args, ) .slice(2) : ''; + const code = coreCode + argsCode; const salt = options.salt || ethers.constants.HashZero; const contractAddress = options.call ? await this.factory.predictAddressWithCall(code, salt, options.call) : await this.factory.predictAddress(code, salt); - if ((await this.factory.provider.getCode(contractAddress)) == '0x') { + if ((await this.factory.provider.getCode(contractAddress)) === '0x') { console.log(`[factory] Preparing to deploy ${artefact.contractName} ...`); await waitTx( options.call @@ -105,17 +152,12 @@ class EthersDeployer { `[factory] ${artefact.contractName} already deployed at ${contractAddress}`, ); } + const instance = await artefact.at(contractAddress); artefact.setAsDeployed(instance); } - /** - * Get placeholder to be replaced with library address for a given contract. - * @param libraryArtefact artefact of the library - * @param contractArtefact artefact of the contract to be linked with the library - * @returns the placeholder to be replaced - */ - getLinkPlaceholder(libraryArtefact, contractArtefact) { + getLinkPlaceholder(libraryArtefact: Artefact, contractArtefact: Artefact): string | undefined { const hardhatLibraryArtifact = libraryArtefact._hArtifact; const hardhatContractArtifact = contractArtefact._hArtifact; if (hardhatContractArtifact.linkReferences) { @@ -123,15 +165,14 @@ class EthersDeployer { hardhatContractArtifact.linkReferences[hardhatLibraryArtifact.sourceName]; if (linkSourceName) { const firstLinkData = linkSourceName[hardhatLibraryArtifact.contractName][0]; - // linkPlaceholder code from: - // https://github.com/NomicFoundation/hardhat/blob/v1.3.3/packages/buidler-truffle5/src/artifacts.ts#L123 return contractArtefact.bytecode.substr( firstLinkData.start * 2 + 2, firstLinkData.length * 2, ); } } + return undefined; } } -module.exports = { EthersDeployer, factoryAddress: FACTORY.address }; +export const factoryAddress = FACTORY.address; From fc61a6f265ed8fda7e26f9580af8dc21e0371b2e Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Fri, 7 Feb 2025 16:28:30 +0100 Subject: [PATCH 04/12] remove useless deprecated ens deployement file --- scripts/ens/sidechain.js | 214 --------------------------------------- 1 file changed, 214 deletions(-) delete mode 100644 scripts/ens/sidechain.js diff --git a/scripts/ens/sidechain.js b/scripts/ens/sidechain.js deleted file mode 100644 index f18bcc2a5..000000000 --- a/scripts/ens/sidechain.js +++ /dev/null @@ -1,214 +0,0 @@ -// SPDX-FileCopyrightText: 2020 IEXEC BLOCKCHAIN TECH -// SPDX-License-Identifier: Apache-2.0 - -const { ethers } = require('ethers'); -const { EthersDeployer: FactoryDeployer } = require('../../utils/FactoryDeployer'); -const ENSRegistry = require('@ensdomains/ens/build/contracts/ENSRegistry.json'); -const FIFSRegistrar = require('@ensdomains/ens/build/contracts/FIFSRegistrar.json'); -const ReverseRegistrar = require('@ensdomains/ens/build/contracts/ReverseRegistrar.json'); -const PublicResolver = require('@ensdomains/resolver/build/contracts/PublicResolver.json'); - -(async () => { - const provider = new ethers.getDefaultProvider(process.env.NODE); - const wallet = new ethers.Wallet(process.env.MNEMONIC, provider); - const deployer = new FactoryDeployer(wallet); - - await deployer.deploy(ENSRegistry, { - call: new ethers.utils.Interface(ENSRegistry.abi).encodeFunctionData('setOwner', [ - ethers.constants.HashZero, - wallet.address, - ]), - }); - const ens = new ethers.Contract(ENSRegistry.address, ENSRegistry.abi, wallet); - - await deployer.deploy(PublicResolver, { args: [ens.address] }); - const publicresolver = new ethers.Contract(PublicResolver.address, PublicResolver.abi, wallet); - - await deployer.deploy(ReverseRegistrar, { args: [ens.address, publicresolver.address] }); - const reverseregistrar = new ethers.Contract( - ReverseRegistrar.address, - ReverseRegistrar.abi, - wallet, - ); - - const domains = [ - { - name: 'eth', - }, - { - name: 'iexec.eth', - }, - { - name: 'erlc.iexec.eth', - address: '0x0000000000000000000000000000000000000000', - }, - { - name: 'timelock.iexec.eth', - address: '0x4611B943AA1d656Fc669623b5DA08756A7e288E9', - }, - { - name: 'v5.iexec.eth', - }, - { - name: 'core.v5.iexec.eth', - address: '0x3eca1B216A7DF1C7689aEb259fFB83ADFB894E7f', - setName: true, - }, - { - name: 'apps.v5.iexec.eth', - address: '0xB1C52075b276f87b1834919167312221d50c9D16', - setName: true, - }, - { - name: 'datasets.v5.iexec.eth', - address: '0x799DAa22654128d0C64d5b79eac9283008158730', - setName: true, - }, - { - name: 'workerpools.v5.iexec.eth', - address: '0xC76A18c78B7e530A165c5683CB1aB134E21938B4', - setName: true, - }, - { - name: 'resolver.eth', - address: publicresolver.address, - }, - { - name: 'reverse', - }, - { - name: 'addr.reverse', - owner: reverseregistrar.address, - }, - ]; - - // Register domains - await new Promise((resolve) => { - Promise.all( - domains - .filter((entry) => entry.name) - .map(async (entry) => ({ - ...entry, - owner: entry.owner || wallet.address, - _owner: await ens.owner(ethers.utils.namehash(entry.name)), - })), - ).then((_) => { - _.filter(({ _owner, owner }) => _owner != owner) - .reduce(async (promise, entry) => { - await Promise.resolve(promise); - console.log(`setSubnodeOwner(${entry.name}) → ${entry.owner}`); - const i = entry.name.indexOf('.'); - const label = i == -1 ? entry.name : entry.name.substr(0, i); - const parent = i == -1 ? '' : entry.name.substr(i + 1); - await ( - await ens.setSubnodeOwner( - ethers.utils.namehash(parent), - ethers.utils.id(label), - entry.owner, - ) - ).wait(); - }, Promise.resolve()) - .then(resolve); - }); - }); - - // Set resolver - await new Promise((resolve) => { - Promise.all( - domains - .filter((entry) => entry.resolver || entry.address) - .map(async (entry) => ({ - ...entry, - resolver: entry.resolver || publicresolver.address, - _resolver: await ens.resolver(ethers.utils.namehash(entry.name)), - })), - ).then((_) => { - _.filter(({ _resolver, resolver }) => _resolver != resolver) - .reduce(async (promise, entry) => { - await Promise.resolve(promise); - console.log(`setResolver(${entry.name}) → ${entry.resolver}`); - await ( - await ens.setResolver(ethers.utils.namehash(entry.name), entry.resolver) - ).wait(); - }, Promise.resolve()) - .then(resolve); - }); - }); - - // Set address - await new Promise((resolve) => { - Promise.all( - domains - .filter((entry) => entry.address) - .map(async (entry) => { - try { - const resolverContract = new ethers.Contract( - await ens.resolver(ethers.utils.namehash(entry.name)), - PublicResolver.abi, - wallet, - ); - const address = await resolverContract['addr(bytes32)']( - ethers.utils.namehash(entry.name), - ); - return address == entry.address ? null : { ...entry, resolverContract }; - } catch { - return null; // invalid resolverContract - } - }), - ).then((_) => { - _.filter(Boolean) - .reduce(async (promise, entry) => { - await Promise.resolve(promise); - console.log(`setAddr(${entry.name}) → ${entry.address}`); - await ( - await entry.resolverContract['setAddr(bytes32,address)']( - ethers.utils.namehash(entry.name), - entry.address, - ) - ).wait(); - }, Promise.resolve()) - .then(resolve); - }); - }); - - // Set reverse - await new Promise((resolve) => { - Promise.all( - domains - .filter((entry) => entry.name && entry.address && entry.setName) - .map((entry) => ({ - ...entry, - lookup: `${entry.address.toLowerCase().substr(2)}.addr.reverse`, - })) - .map(async (entry) => { - try { - const reverseResolver = new ethers.Contract( - await ens.resolver(ethers.utils.namehash(entry.lookup)), - PublicResolver.abi, - wallet, - ); - const name = await reverseResolver.name( - ethers.utils.namehash(entry.lookup), - ); - return name == entry.name ? null : entry; - } catch { - return entry; // reverseResolver not set - } - }), - ).then((_) => { - _.filter(Boolean) - .reduce(async (promise, entry) => { - await Promise.resolve(promise); - console.log(`setName(${entry.address}) → ${entry.name}`); - await ( - await new ethers.Contract( - entry.address, - [ethers.utils.FunctionFragment.fromString('setName(address,string)')], - wallet, - ).setName(ens.address, entry.name) - ).wait(); - }, Promise.resolve()) - .then(resolve); - }); - }); -})().catch(console.error); From f1efd705c3d1ab708ba72574884cb97208f75606 Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Fri, 7 Feb 2025 16:29:22 +0100 Subject: [PATCH 05/12] keep only usefull function in EthersDeployer class --- utils/FactoryDeployer.ts | 127 ++------------------------------------- 1 file changed, 4 insertions(+), 123 deletions(-) diff --git a/utils/FactoryDeployer.ts b/utils/FactoryDeployer.ts index a286ba370..34a21fbff 100644 --- a/utils/FactoryDeployer.ts +++ b/utils/FactoryDeployer.ts @@ -1,12 +1,11 @@ -// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 -import { Contract, ethers } from 'ethers'; -import hre from 'hardhat'; - import factoryJson from '@amxx/factory/deployments/GenericFactory.json'; import factoryShanghaiJson from '@amxx/factory/deployments/GenericFactory_shanghai.json'; import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; +import { Contract, ethers } from 'ethers'; +import hre from 'hardhat'; import config from '../config/config.json'; interface FactoryConfig { @@ -17,33 +16,6 @@ interface FactoryConfig { abi: any[]; } -interface DeployOptions { - libraries?: any[]; - salt?: string; - call?: string; - [key: string]: any; -} - -interface Artefact { - contractName: string; - abi: any[]; - bytecode: string; - at: (address: string) => Promise; - setAsDeployed: (instance: any) => void; - _hArtifact: { - sourceName: string; - contractName: string; - linkReferences?: { - [key: string]: { - [key: string]: Array<{ - start: number; - length: number; - }>; - }; - }; - }; -} - const FACTORY: FactoryConfig = config.chains.default.asset === 'Token' && hre.network.name.includes('hardhat') ? factoryShanghaiJson @@ -56,10 +28,8 @@ async function waitTx(txPromise: Promise): Promise; - private options: DeployOptions; - constructor(wallet: SignerWithAddress, options: DeployOptions = {}) { - this.options = options; + constructor(wallet: SignerWithAddress) { this.factoryAsPromise = new Promise(async (resolve, reject) => { if ((await wallet.provider!.getCode(FACTORY.address)) !== '0x') { console.debug(`→ Factory is available on this network`); @@ -84,95 +54,6 @@ export class EthersDeployer { async ready(): Promise { await this.factoryAsPromise; } - - async deploy(artefact: Artefact, ...extra: any[]): Promise { - await this.ready(); - console.log(`[factoryDeployer] ${artefact.contractName}`); - - const constructorABI = artefact.abi.find((e) => e.type === 'constructor'); - const argsCount = constructorABI ? constructorABI.inputs.length : 0; - const args = extra.slice(0, argsCount); - const options: DeployOptions = { ...this.options, ...extra[argsCount] }; - - let librariesLinkPlaceHolderAndAddress: any[] = []; - if (options.libraries) { - librariesLinkPlaceHolderAndAddress = await Promise.all( - options.libraries.map(async (library) => { - const linkPlaceholder = this.getLinkPlaceholder(library, artefact); - if (linkPlaceholder) { - return { - linkPlaceholder, - address: (await library.deployed()).address, - }; - } - return undefined; - }), - ); - } - - let coreCode = artefact.bytecode; - librariesLinkPlaceHolderAndAddress - .filter( - (data): data is { linkPlaceholder: string; address: string } => data !== undefined, - ) - .forEach((element) => { - coreCode = coreCode.replace( - new RegExp(element.linkPlaceholder, 'g'), - element.address.slice(2).toLowerCase(), - ); - }); - - const argsCode = constructorABI - ? ethers.utils.defaultAbiCoder - .encode( - constructorABI.inputs.map((e: { type: string }) => e.type), - args, - ) - .slice(2) - : ''; - - const code = coreCode + argsCode; - const salt = options.salt || ethers.constants.HashZero; - const contractAddress = options.call - ? await this.factory.predictAddressWithCall(code, salt, options.call) - : await this.factory.predictAddress(code, salt); - - if ((await this.factory.provider.getCode(contractAddress)) === '0x') { - console.log(`[factory] Preparing to deploy ${artefact.contractName} ...`); - await waitTx( - options.call - ? this.factory.createContractAndCall(code, salt, options.call) - : this.factory.createContract(code, salt), - ); - console.log( - `[factory] ${artefact.contractName} successfully deployed at ${contractAddress}`, - ); - } else { - console.log( - `[factory] ${artefact.contractName} already deployed at ${contractAddress}`, - ); - } - - const instance = await artefact.at(contractAddress); - artefact.setAsDeployed(instance); - } - - getLinkPlaceholder(libraryArtefact: Artefact, contractArtefact: Artefact): string | undefined { - const hardhatLibraryArtifact = libraryArtefact._hArtifact; - const hardhatContractArtifact = contractArtefact._hArtifact; - if (hardhatContractArtifact.linkReferences) { - const linkSourceName = - hardhatContractArtifact.linkReferences[hardhatLibraryArtifact.sourceName]; - if (linkSourceName) { - const firstLinkData = linkSourceName[hardhatLibraryArtifact.contractName][0]; - return contractArtefact.bytecode.substr( - firstLinkData.start * 2 + 2, - firstLinkData.length * 2, - ); - } - } - return undefined; - } } export const factoryAddress = FACTORY.address; From 10ac15c1835d1e7130222a6e611d89831e769b26 Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Mon, 10 Feb 2025 09:15:55 +0100 Subject: [PATCH 06/12] update SPDX copyright years in constants and createOrders files --- utils/constants.ts | 2 +- utils/createOrders.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/constants.ts b/utils/constants.ts index b438f8edd..c77ebe508 100644 --- a/utils/constants.ts +++ b/utils/constants.ts @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2024-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 //config diff --git a/utils/createOrders.ts b/utils/createOrders.ts index ca2b8b514..4a3aea957 100644 --- a/utils/createOrders.ts +++ b/utils/createOrders.ts @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023-2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2023-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 import { TypedDataDomain } from '@ethersproject/abstract-signer'; From 762d9f33568fda96e72b45e8d65ab1125681a06a Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Mon, 10 Feb 2025 09:27:36 +0100 Subject: [PATCH 07/12] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c2ced08f..50d0b80fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ - [x] `IexecPoco2Delegate.sol` ### Features +- Migrated utility files to TypeScript : (#183) + - `FactoryDeployer.js`, `constants.js`, `odb-tools.js` + - Removed deprecated `scripts/ens/sidechain.js` - Purge Truffle leftovers (#180, #181, #182) - Sunset Jenkins pipeline (#178) - Re-use variable in `IexecPoco2Delegate` in `contribute(...)` function. (#168) From a772b4a7404742edf86487f8625bd23e1391980e Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Mon, 10 Feb 2025 11:22:23 +0100 Subject: [PATCH 08/12] update debug to log --- utils/FactoryDeployer.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/FactoryDeployer.ts b/utils/FactoryDeployer.ts index 34a21fbff..b0aa538f1 100644 --- a/utils/FactoryDeployer.ts +++ b/utils/FactoryDeployer.ts @@ -32,17 +32,17 @@ export class EthersDeployer { constructor(wallet: SignerWithAddress) { this.factoryAsPromise = new Promise(async (resolve, reject) => { if ((await wallet.provider!.getCode(FACTORY.address)) !== '0x') { - console.debug(`→ Factory is available on this network`); + console.log(`→ Factory is available on this network`); } else { try { - console.debug(`→ Factory is not yet deployed on this network`); + console.log(`→ Factory is not yet deployed on this network`); await waitTx( wallet.sendTransaction({ to: FACTORY.deployer, value: FACTORY.cost }), ); await waitTx(wallet.provider!.sendTransaction(FACTORY.tx)); - console.debug(`→ Factory successfully deployed`); + console.log(`→ Factory successfully deployed`); } catch (e) { - console.debug(`→ Error deploying the factory`); + console.log(`→ Error deploying the factory`); reject(e); } } From 09a31f0d9dcfe7f0f5df925075f9947949a1f8c3 Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Mon, 10 Feb 2025 11:26:50 +0100 Subject: [PATCH 09/12] update to factoryConfig name --- utils/FactoryDeployer.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/utils/FactoryDeployer.ts b/utils/FactoryDeployer.ts index b0aa538f1..3f63bee52 100644 --- a/utils/FactoryDeployer.ts +++ b/utils/FactoryDeployer.ts @@ -16,7 +16,7 @@ interface FactoryConfig { abi: any[]; } -const FACTORY: FactoryConfig = +const factoryConfig: FactoryConfig = config.chains.default.asset === 'Token' && hre.network.name.includes('hardhat') ? factoryShanghaiJson : factoryJson; @@ -31,22 +31,25 @@ export class EthersDeployer { constructor(wallet: SignerWithAddress) { this.factoryAsPromise = new Promise(async (resolve, reject) => { - if ((await wallet.provider!.getCode(FACTORY.address)) !== '0x') { + if ((await wallet.provider!.getCode(factoryConfig.address)) !== '0x') { console.log(`→ Factory is available on this network`); } else { try { console.log(`→ Factory is not yet deployed on this network`); await waitTx( - wallet.sendTransaction({ to: FACTORY.deployer, value: FACTORY.cost }), + wallet.sendTransaction({ + to: factoryConfig.deployer, + value: factoryConfig.cost, + }), ); - await waitTx(wallet.provider!.sendTransaction(FACTORY.tx)); + await waitTx(wallet.provider!.sendTransaction(factoryConfig.tx)); console.log(`→ Factory successfully deployed`); } catch (e) { console.log(`→ Error deploying the factory`); reject(e); } } - this.factory = new ethers.Contract(FACTORY.address, FACTORY.abi, wallet); + this.factory = new ethers.Contract(factoryConfig.address, factoryConfig.abi, wallet); resolve(this.factory); }); } @@ -56,4 +59,4 @@ export class EthersDeployer { } } -export const factoryAddress = FACTORY.address; +export const factoryAddress = factoryConfig.address; From ef91722d5e08883dcdda8cfc2945ff5a38b2188f Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Mon, 10 Feb 2025 11:28:50 +0100 Subject: [PATCH 10/12] add todo --- utils/constants.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/constants.ts b/utils/constants.ts index c77ebe508..763744082 100644 --- a/utils/constants.ts +++ b/utils/constants.ts @@ -1,9 +1,10 @@ -// SPDX-FileCopyrightText: 2024-2025 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 //config export const EVENT_WAIT_TIMEOUT = 100000; export const AMOUNT_GAS_PROVIDED = 4500000; +// TODO remove this if not used anymore. // export const AMOUNT_GAS_PROVIDED = "0xFFFFFFFFFFFFFFFF"; export const NULL = { From f43e0a5b24f5010ff9cd49b52dfe9d6cd01abc2c Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Mon, 10 Feb 2025 12:11:53 +0100 Subject: [PATCH 11/12] create ens doc --- docs/ENS-Addresses.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 docs/ENS-Addresses.md diff --git a/docs/ENS-Addresses.md b/docs/ENS-Addresses.md new file mode 100644 index 000000000..01726ec15 --- /dev/null +++ b/docs/ENS-Addresses.md @@ -0,0 +1,25 @@ +# ENS Addresses in iExec PoCo + +This document describes the ENS (Ethereum Name Service) addresses used in the iExec Protocol. + +## Domain Structure + +The iExec protocol uses the following ENS domain hierarchy: +- Root domain: `iexec.eth` +- Protocol version domain: `v5.iexec.eth` +- User domain: `users.iexec.eth` +- Resource domains: + - `apps.iexec.eth` + - `datasets.iexec.eth` + - `pools.iexec.eth` + +## Core Protocol Addresses + +The following ENS names are registered for core protocol components: + +- `admin.iexec.eth` - Protocol administrator address +- `rlc.iexec.eth` - RLC token contract address +- `core.v5.iexec.eth` - Core protocol proxy (ERC1538Proxy) +- `apps.v5.iexec.eth` - App registry contract +- `datasets.v5.iexec.eth` - Dataset registry contract +- `workerpools.v5.iexec.eth` - Workerpool registry contract \ No newline at end of file From 84a700e5726d1c2e89a13be88cfc94938f42f975 Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Mon, 10 Feb 2025 17:38:52 +0100 Subject: [PATCH 12/12] add addresses on ens file --- docs/ENS-Addresses.md | 8 +++++++- docs/README.md | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/ENS-Addresses.md b/docs/ENS-Addresses.md index 01726ec15..e99dcc0ce 100644 --- a/docs/ENS-Addresses.md +++ b/docs/ENS-Addresses.md @@ -20,6 +20,12 @@ The following ENS names are registered for core protocol components: - `admin.iexec.eth` - Protocol administrator address - `rlc.iexec.eth` - RLC token contract address - `core.v5.iexec.eth` - Core protocol proxy (ERC1538Proxy) + - `0x3eca1B216A7DF1C7689aEb259fFB83ADFB894E7f` - `apps.v5.iexec.eth` - App registry contract + - `0xB1C52075b276f87b1834919167312221d50c9D16` - `datasets.v5.iexec.eth` - Dataset registry contract -- `workerpools.v5.iexec.eth` - Workerpool registry contract \ No newline at end of file + - `0x799DAa22654128d0C64d5b79eac9283008158730` +- `workerpools.v5.iexec.eth` - Workerpool registry contract + - `0xC76A18c78B7e530A165c5683CB1aB134E21938B4` + +To get more details, see [1_deploy-ens.ts script](../deploy/1_deploy-ens.ts). diff --git a/docs/README.md b/docs/README.md index 335d9efbc..20077ec3d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,3 +24,6 @@ * Nominal TEE [![Nominal TEE](https://tinyurl.com/2zubyfvw)](https://tinyurl.com/2zubyfvw) + +# ENS +Registered ENS names on Bellecour or Mainnet are documented in [./ENS-Addresses.md](./ENS-Addresses.md) \ No newline at end of file