diff --git a/contracts/tasks/etherscanVerify.ts b/contracts/tasks/etherscanVerify.ts index 609cde16..0a8f8c51 100644 --- a/contracts/tasks/etherscanVerify.ts +++ b/contracts/tasks/etherscanVerify.ts @@ -2,8 +2,8 @@ import dotenv from 'dotenv'; import fs from 'fs'; import { task } from 'hardhat/config'; -task('task:verifyContracts').setAction(async function (taskArguments, { upgrades, run }) { - const parsedEnvACL = dotenv.parse(fs.readFileSync('addresses/.env.acl')); +task('task:verifyACL').setAction(async function (taskArguments, { upgrades, run }) { + const parsedEnvACL = dotenv.parse(fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.acl')); const proxyACLAddress = parsedEnvACL.ACL_CONTRACT_ADDRESS; const implementationACLAddress = await upgrades.erc1967.getImplementationAddress(proxyACLAddress); await run('verify:verify', { @@ -14,8 +14,10 @@ task('task:verifyContracts').setAction(async function (taskArguments, { upgrades address: proxyACLAddress, constructorArguments: [], }); +}); - const parsedEnvTFHEExecutor = dotenv.parse(fs.readFileSync('addresses/.env.exec')); +task('task:verifyTFHEExecutor').setAction(async function (taskArguments, { upgrades, run }) { + const parsedEnvTFHEExecutor = dotenv.parse(fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.exec')); const proxyTFHEExecutorAddress = parsedEnvTFHEExecutor.TFHE_EXECUTOR_CONTRACT_ADDRESS; const implementationTFHEExecutorAddress = await upgrades.erc1967.getImplementationAddress(proxyTFHEExecutorAddress); await run('verify:verify', { @@ -26,8 +28,12 @@ task('task:verifyContracts').setAction(async function (taskArguments, { upgrades address: proxyTFHEExecutorAddress, constructorArguments: [], }); +}); - const parsedEnvKMSVerifier = dotenv.parse(fs.readFileSync('addresses/.env.kmsverifier')); +task('task:verifyKMSVerifier').setAction(async function (taskArguments, { upgrades, run }) { + const parsedEnvKMSVerifier = dotenv.parse( + fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.kmsverifier'), + ); const proxyKMSVerifier = parsedEnvKMSVerifier.KMS_VERIFIER_CONTRACT_ADDRESS; const implementationKMSVerifierAddress = await upgrades.erc1967.getImplementationAddress(proxyKMSVerifier); await run('verify:verify', { @@ -38,8 +44,12 @@ task('task:verifyContracts').setAction(async function (taskArguments, { upgrades address: proxyKMSVerifier, constructorArguments: [], }); +}); - const parsedEnvInputVerifier = dotenv.parse(fs.readFileSync('addresses/.env.inputverifier')); +task('task:verifyInputVerifier').setAction(async function (taskArguments, { upgrades, run }) { + const parsedEnvInputVerifier = dotenv.parse( + fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.inputverifier'), + ); const proxyInputVerifier = parsedEnvInputVerifier.INPUT_VERIFIER_CONTRACT_ADDRESS; const implementationInputVerifierAddress = await upgrades.erc1967.getImplementationAddress(proxyInputVerifier); await run('verify:verify', { @@ -50,8 +60,12 @@ task('task:verifyContracts').setAction(async function (taskArguments, { upgrades address: proxyInputVerifier, constructorArguments: [], }); +}); - const parsedEnvFHEPayment = dotenv.parse(fs.readFileSync('addresses/.env.fhepayment')); +task('task:verifyFHEPayment').setAction(async function (taskArguments, { upgrades, run }) { + const parsedEnvFHEPayment = dotenv.parse( + fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.fhepayment'), + ); const proxyFHEPayment = parsedEnvFHEPayment.FHE_PAYMENT_CONTRACT_ADDRESS; const implementationFHEPaymentAddress = await upgrades.erc1967.getImplementationAddress(proxyFHEPayment); await run('verify:verify', { @@ -62,7 +76,9 @@ task('task:verifyContracts').setAction(async function (taskArguments, { upgrades address: proxyFHEPayment, constructorArguments: [], }); +}); +task('task:verifyGatewayContract').setAction(async function (taskArguments, { upgrades, run }) { const parsedEnvGateway = dotenv.parse(fs.readFileSync('gateway/.env.gateway')); const proxyGateway = parsedEnvGateway.GATEWAY_CONTRACT_PREDEPLOY_ADDRESS; const implementationGatewayAddress = await upgrades.erc1967.getImplementationAddress(proxyGateway); diff --git a/contracts/tasks/getEthereumAddress.ts b/contracts/tasks/getEthereumAddress.ts new file mode 100644 index 00000000..2a84e178 --- /dev/null +++ b/contracts/tasks/getEthereumAddress.ts @@ -0,0 +1,34 @@ +import dotenv from 'dotenv'; +import { ethers } from 'ethers'; +import { task } from 'hardhat/config'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; + +dotenv.config(); + +const getEthereumAddress = + (index: number = 0) => + async (_taskArgs: unknown, _: HardhatRuntimeEnvironment) => { + const words = process.env.MNEMONIC!; + const mnemonic = ethers.Mnemonic.fromPhrase(words); + if (!mnemonic) { + throw new Error('No MNEMONIC in .env file'); + } + const wallet = ethers.HDNodeWallet.fromMnemonic(mnemonic, `m/44'/60'/0'/0`); + console.log(wallet.deriveChild(index).address); + }; + +task( + 'task:getEthereumAddress', + 'Gets the first address derived from a mnemonic phrase defined in .env', + getEthereumAddress(0), +); + +const accounts = ['Alice', 'Bob', 'Carol', 'Dave', 'Eve']; + +accounts.forEach((name, index) => { + task( + `task:getEthereumAddress${name}`, + 'Gets the first address derived from a mnemonic phrase defined in .env', + getEthereumAddress(index), + ); +}); diff --git a/contracts/tasks/taskDeploy.ts b/contracts/tasks/taskDeploy.ts index 4a8c4b32..2bc3ebb7 100644 --- a/contracts/tasks/taskDeploy.ts +++ b/contracts/tasks/taskDeploy.ts @@ -3,6 +3,8 @@ import fs from 'fs'; import { task, types } from 'hardhat/config'; import type { TaskArguments } from 'hardhat/types'; +import { KMSVerifier } from '../types'; + task('task:deployGateway') .addParam('privateKey', 'The deployer private key') .addParam('ownerAddress', 'The owner address') @@ -28,11 +30,11 @@ task('task:deployACL') .addParam('privateKey', 'The deployer private key') .setAction(async function (taskArguments: TaskArguments, { ethers, upgrades }) { const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); - const factory = await ethers.getContractFactory('ACL', deployer); + const factory = await ethers.getContractFactory('fhevmTemp/contracts/ACL.sol:ACL', deployer); const acl = await upgrades.deployProxy(factory, [deployer.address], { initializer: 'initialize', kind: 'uups' }); await acl.waitForDeployment(); const address = await acl.getAddress(); - const envConfigAcl = dotenv.parse(fs.readFileSync('addresses/.env.acl')); + const envConfigAcl = dotenv.parse(fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.acl')); if (address !== envConfigAcl.ACL_CONTRACT_ADDRESS) { throw new Error( `The nonce of the deployer account is not correct. Please relaunch a clean instance of the fhEVM`, @@ -47,14 +49,14 @@ task('task:deployTFHEExecutor') const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); let factory; if (process.env.HARDHAT_TFHEEXECUTOR_EVENTS !== '1') { - factory = await ethers.getContractFactory('contracts/TFHEExecutor.sol:TFHEExecutor', deployer); + factory = await ethers.getContractFactory('fhevmTemp/contracts/TFHEExecutor.sol:TFHEExecutor', deployer); } else { factory = await ethers.getContractFactory('contracts/TFHEExecutorWithEvents.sol:TFHEExecutorWithEvents', deployer); } const exec = await upgrades.deployProxy(factory, [deployer.address], { initializer: 'initialize', kind: 'uups' }); await exec.waitForDeployment(); const address = await exec.getAddress(); - const envConfig = dotenv.parse(fs.readFileSync('addresses/.env.exec')); + const envConfig = dotenv.parse(fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.exec')); if (address !== envConfig.TFHE_EXECUTOR_CONTRACT_ADDRESS) { throw new Error( `The nonce of the deployer account is not correct. Please relaunch a clean instance of the fhEVM`, @@ -67,11 +69,11 @@ task('task:deployKMSVerifier') .addParam('privateKey', 'The deployer private key') .setAction(async function (taskArguments: TaskArguments, { ethers, upgrades }) { const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); - const factory = await ethers.getContractFactory('KMSVerifier', deployer); + const factory = await ethers.getContractFactory('fhevmTemp/contracts/KMSVerifier.sol:KMSVerifier', deployer); const kms = await upgrades.deployProxy(factory, [deployer.address], { initializer: 'initialize', kind: 'uups' }); await kms.waitForDeployment(); const address = await kms.getAddress(); - const envConfig = dotenv.parse(fs.readFileSync('addresses/.env.kmsverifier')); + const envConfig = dotenv.parse(fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.kmsverifier')); if (address !== envConfig.KMS_VERIFIER_CONTRACT_ADDRESS) { throw new Error( `The nonce of the deployer account is not correct. Please relaunch a clean instance of the fhEVM`, @@ -86,14 +88,17 @@ task('task:deployInputVerifier') const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); let factory; if (process.env.IS_COPROCESSOR === 'true') { - factory = await ethers.getContractFactory('contracts/InputVerifier.coprocessor.sol:InputVerifier', deployer); + factory = await ethers.getContractFactory( + 'fhevmTemp/contracts/InputVerifier.coprocessor.sol:InputVerifier', + deployer, + ); } else { - factory = await ethers.getContractFactory('contracts/InputVerifier.native.sol:InputVerifier', deployer); + factory = await ethers.getContractFactory('fhevmTemp/contracts/InputVerifier.native.sol:InputVerifier', deployer); } const kms = await upgrades.deployProxy(factory, [deployer.address], { initializer: 'initialize', kind: 'uups' }); await kms.waitForDeployment(); const address = await kms.getAddress(); - const envConfig = dotenv.parse(fs.readFileSync('addresses/.env.inputverifier')); + const envConfig = dotenv.parse(fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.inputverifier')); if (address !== envConfig.INPUT_VERIFIER_CONTRACT_ADDRESS) { throw new Error( `The nonce of the deployer account is not correct. Please relaunch a clean instance of the fhEVM`, @@ -106,14 +111,14 @@ task('task:deployFHEPayment') .addParam('privateKey', 'The deployer private key') .setAction(async function (taskArguments: TaskArguments, { ethers, upgrades }) { const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); - const factory = await ethers.getContractFactory('FHEPayment', deployer); + const factory = await ethers.getContractFactory('fhevmTemp/contracts/FHEPayment.sol:FHEPayment', deployer); const payment = await upgrades.deployProxy(factory, [deployer.address], { initializer: 'initialize', kind: 'uups', }); await payment.waitForDeployment(); const address = await payment.getAddress(); - const envConfig = dotenv.parse(fs.readFileSync('addresses/.env.fhepayment')); + const envConfig = dotenv.parse(fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.fhepayment')); if (address !== envConfig.FHE_PAYMENT_CONTRACT_ADDRESS) { throw new Error( `The nonce of the deployer account is not correct. Please relaunch a clean instance of the fhEVM`, @@ -131,10 +136,21 @@ task('task:addSigners') false, types.boolean, ) + .addOptionalParam( + 'customKmsVerifierAddress', + 'Use a custom address for the KMSVerifier contract instead of the default one - ie stored inside .env.kmsverifier', + ) .setAction(async function (taskArguments: TaskArguments, { ethers }) { const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); - const factory = await ethers.getContractFactory('KMSVerifier', deployer); - const kmsAdd = dotenv.parse(fs.readFileSync('addresses/.env.kmsverifier')).KMS_VERIFIER_CONTRACT_ADDRESS; + const factory = await ethers.getContractFactory('fhevmTemp/contracts/KMSVerifier.sol:KMSVerifier', deployer); + let kmsAdd; + if (taskArguments.customKmsVerifierAddress) { + kmsAdd = taskArguments.customKmsVerifierAddress; + } else { + kmsAdd = dotenv.parse( + fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.kmsverifier'), + ).KMS_VERIFIER_CONTRACT_ADDRESS; + } const kmsVerifier = await factory.attach(kmsAdd); for (let idx = 0; idx < taskArguments.numSigners; idx++) { if (!taskArguments.useAddress) { @@ -151,3 +167,47 @@ task('task:addSigners') } } }); + +task('task:getAllSigners') + .addOptionalParam( + 'customKmsVerifierAddress', + 'Use a custom address for the KMSVerifier contract instead of the default one - ie stored inside .env.kmsverifier', + ) + .setAction(async function (taskArguments: TaskArguments, { ethers }) { + const factory = await ethers.getContractFactory('fhevmTemp/contracts/KMSVerifier.sol:KMSVerifier'); + let kmsAdd; + if (taskArguments.customKmsVerifierAddress) { + kmsAdd = taskArguments.customKmsVerifierAddress; + } else { + kmsAdd = dotenv.parse( + fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.kmsverifier'), + ).KMS_VERIFIER_CONTRACT_ADDRESS; + } + const kmsVerifier = (await factory.attach(kmsAdd).connect(ethers.provider)) as KMSVerifier; + const listCurrentKMSSigners = await kmsVerifier.getSigners(); + console.log('The list of current KMS Signers stored inside KMSVerifier contract is: ', listCurrentKMSSigners); + }); + +task('task:removeSigner') + .addParam('privateKey', 'The KMSVerifier owner private key') + .addParam('kmsSignerAddress', 'The KMS Signer address you wish to remove') + .addOptionalParam( + 'customKmsVerifierAddress', + 'Use a custom address for the KMSVerifier contract instead of the default one - ie stored inside .env.kmsverifier', + ) + .setAction(async function (taskArguments: TaskArguments, { ethers }) { + const deployer = new ethers.Wallet(taskArguments.privateKey).connect(ethers.provider); + const factory = await ethers.getContractFactory('fhevmTemp/contracts/KMSVerifier.sol:KMSVerifier', deployer); + let kmsAdd; + if (taskArguments.customKmsVerifierAddress) { + kmsAdd = taskArguments.customKmsVerifierAddress; + } else { + kmsAdd = dotenv.parse( + fs.readFileSync('node_modules/fhevm-core-contracts/addresses/.env.kmsverifier'), + ).KMS_VERIFIER_CONTRACT_ADDRESS; + } + const kmsVerifier = (await factory.attach(kmsAdd)) as KMSVerifier; + const tx = await kmsVerifier.removeSigner(taskArguments.kmsSignerAddress); + await tx.wait(); + console.log(`KMS signer with address (${taskArguments.kmsSignerAddress}) was removed from KMSVerifier contract`); + }); diff --git a/contracts/tasks/taskTFHE.ts b/contracts/tasks/taskTFHE.ts index 2ed15c2c..d27d5e26 100644 --- a/contracts/tasks/taskTFHE.ts +++ b/contracts/tasks/taskTFHE.ts @@ -11,7 +11,7 @@ task('task:computeACLAddress') from: deployer, nonce: 1, // using nonce of 1 for the ACL contract (0 for original implementation, +1 for proxy) }); - const envFilePath = path.join(__dirname, '../addresses/.env.acl'); + const envFilePath = path.join(__dirname, '../node_modules/fhevm-core-contracts/addresses/.env.acl'); const content = `ACL_CONTRACT_ADDRESS=${aclAddress}\n`; try { fs.writeFileSync(envFilePath, content, { flag: 'w' }); @@ -27,10 +27,13 @@ pragma solidity ^0.8.24; address constant aclAdd = ${aclAddress};\n`; try { - fs.writeFileSync('./addresses/ACLAddress.sol', solidityTemplate, { encoding: 'utf8', flag: 'w' }); - console.log('./addresses/ACLAddress.sol file generated successfully!'); + fs.writeFileSync('./node_modules/fhevm-core-contracts/addresses/ACLAddress.sol', solidityTemplate, { + encoding: 'utf8', + flag: 'w', + }); + console.log('./node_modules/fhevm-core-contracts/addresses/ACLAddress.sol file generated successfully!'); } catch (error) { - console.error('Failed to write ./addresses/ACLAddress.sol', error); + console.error('Failed to write ./node_modules/fhevm-core-contracts/addresses/ACLAddress.sol', error); } }); @@ -42,7 +45,7 @@ task('task:computeTFHEExecutorAddress') from: deployer, nonce: 3, // using nonce of 3 for the TFHEExecutor contract (2 for original implementation, +1 for proxy) }); - const envFilePath = path.join(__dirname, '../addresses/.env.exec'); + const envFilePath = path.join(__dirname, '../node_modules/fhevm-core-contracts/addresses/.env.exec'); const content = `TFHE_EXECUTOR_CONTRACT_ADDRESS=${execAddress}\n`; try { fs.writeFileSync(envFilePath, content, { flag: 'w' }); @@ -58,13 +61,14 @@ pragma solidity ^0.8.24; address constant tfheExecutorAdd = ${execAddress};\n`; try { - fs.writeFileSync('./addresses/TFHEExecutorAddress.sol', solidityTemplateCoprocessor, { - encoding: 'utf8', - flag: 'w', - }); - console.log('./addresses/TFHEExecutorAddress.sol file generated successfully!'); + fs.writeFileSync( + './node_modules/fhevm-core-contracts/addresses/TFHEExecutorAddress.sol', + solidityTemplateCoprocessor, + { encoding: 'utf8', flag: 'w' }, + ); + console.log('./node_modules/fhevm-core-contracts/addresses/TFHEExecutorAddress.sol file generated successfully!'); } catch (error) { - console.error('Failed to write ./addresses/TFHEExecutorAddress.sol', error); + console.error('Failed to write ./node_modules/fhevm-core-contracts/addresses/TFHEExecutorAddress.sol', error); } }); @@ -76,7 +80,7 @@ task('task:computeKMSVerifierAddress') from: deployer, nonce: 5, // using nonce of 5 for the KMSVerifier contract (4 for original implementation, +1 for proxy) }); - const envFilePath = path.join(__dirname, '../addresses/.env.kmsverifier'); + const envFilePath = path.join(__dirname, '../node_modules/fhevm-core-contracts/addresses/.env.kmsverifier'); const content = `KMS_VERIFIER_CONTRACT_ADDRESS=${kmsVerfierAddress}\n`; try { fs.writeFileSync(envFilePath, content, { flag: 'w' }); @@ -92,10 +96,13 @@ pragma solidity ^0.8.24; address constant kmsVerifierAdd = ${kmsVerfierAddress};\n`; try { - fs.writeFileSync('./addresses/KMSVerifierAddress.sol', solidityTemplate, { encoding: 'utf8', flag: 'w' }); - console.log('./addresses/KMSVerifierAddress.sol file generated successfully!'); + fs.writeFileSync('./node_modules/fhevm-core-contracts/addresses/KMSVerifierAddress.sol', solidityTemplate, { + encoding: 'utf8', + flag: 'w', + }); + console.log('./node_modules/fhevm-core-contracts/addresses/KMSVerifierAddress.sol file generated successfully!'); } catch (error) { - console.error('Failed to write ./addresses/KMSVerifierAddress.sol', error); + console.error('Failed to write ./node_modules/fhevm-core-contracts/addresses/KMSVerifierAddress.sol', error); } }); @@ -114,7 +121,7 @@ task('task:computeInputVerifierAddress') from: deployer, nonce: 7, // using nonce of 7 for the InputVerifier contract (6 for original implementation, +1 for proxy) }); - const envFilePath = path.join(__dirname, '../addresses/.env.inputverifier'); + const envFilePath = path.join(__dirname, '../node_modules/fhevm-core-contracts/addresses/.env.inputverifier'); const content = `INPUT_VERIFIER_CONTRACT_ADDRESS=${inputVerfierAddress}\n`; try { fs.writeFileSync(envFilePath, content, { flag: 'w' }); @@ -130,10 +137,15 @@ pragma solidity ^0.8.24; address constant inputVerifierAdd = ${inputVerfierAddress};\n`; try { - fs.writeFileSync('./addresses/InputVerifierAddress.sol', solidityTemplate, { encoding: 'utf8', flag: 'w' }); - console.log('./addresses/InputVerifierAddress.sol file generated successfully!'); + fs.writeFileSync('./node_modules/fhevm-core-contracts/addresses/InputVerifierAddress.sol', solidityTemplate, { + encoding: 'utf8', + flag: 'w', + }); + console.log( + './node_modules/fhevm-core-contracts/addresses/InputVerifierAddress.sol file generated successfully!', + ); } catch (error) { - console.error('Failed to write ./addresses/InputVerifierAddress.sol', error); + console.error('Failed to write ./node_modules/fhevm-core-contracts/addresses/InputVerifierAddress.sol', error); } let coprocAddress; if (!taskArguments.useAddress) { @@ -141,7 +153,7 @@ address constant inputVerifierAdd = ${inputVerfierAddress};\n`; } else { coprocAddress = process.env.ADDRESS_COPROCESSOR_ACCOUNT; } - const envFilePath2 = path.join(__dirname, '../addresses/.env.coprocessor'); + const envFilePath2 = path.join(__dirname, '../node_modules/fhevm-core-contracts/addresses/.env.coprocessor'); const content2 = `COPROCESSOR_ADDRESS=${coprocAddress}\n`; try { fs.writeFileSync(envFilePath2, content2, { flag: 'w' }); @@ -157,10 +169,13 @@ pragma solidity ^0.8.24; address constant coprocessorAdd = ${coprocAddress};\n`; try { - fs.writeFileSync('./addresses/CoprocessorAddress.sol', solidityTemplate2, { encoding: 'utf8', flag: 'w' }); - console.log('./addresses/CoprocessorAddress.sol file generated successfully!'); + fs.writeFileSync('./node_modules/fhevm-core-contracts/addresses/CoprocessorAddress.sol', solidityTemplate2, { + encoding: 'utf8', + flag: 'w', + }); + console.log('./node_modules/fhevm-core-contracts/addresses/CoprocessorAddress.sol file generated successfully!'); } catch (error) { - console.error('Failed to write ./addresses/CoprocessorAddress.sol', error); + console.error('Failed to write ./node_modules/fhevm-core-contracts/addresses/CoprocessorAddress.sol', error); } }); @@ -172,7 +187,7 @@ task('task:computeFHEPaymentAddress') from: deployer, nonce: 9, // using nonce of 9 for the FHEPayment contract (8 for original implementation, +1 for proxy) }); - const envFilePath = path.join(__dirname, '../addresses/.env.fhepayment'); + const envFilePath = path.join(__dirname, '../node_modules/fhevm-core-contracts/addresses/.env.fhepayment'); const content = `FHE_PAYMENT_CONTRACT_ADDRESS=${fhePaymentAddress}\n`; try { fs.writeFileSync(envFilePath, content, { flag: 'w' }); @@ -188,9 +203,12 @@ pragma solidity ^0.8.24; address constant fhePaymentAdd = ${fhePaymentAddress};\n`; try { - fs.writeFileSync('./addresses/FHEPaymentAddress.sol', solidityTemplate, { encoding: 'utf8', flag: 'w' }); - console.log('./addresses/FHEPaymentAddress.sol file generated successfully!'); + fs.writeFileSync('./node_modules/fhevm-core-contracts/addresses/FHEPaymentAddress.sol', solidityTemplate, { + encoding: 'utf8', + flag: 'w', + }); + console.log('./node_modules/fhevm-core-contracts/addresses/FHEPaymentAddress.sol file generated successfully!'); } catch (error) { - console.error('Failed to write ./addresses/FHEPaymentAddress.sol', error); + console.error('Failed to write ./node_modules/fhevm-core-contracts/addresses/FHEPaymentAddress.sol', error); } });