diff --git a/scripts/deploy-investor-vesting.js b/scripts/deploy-investor-vesting.js index ce6b013..f8b723d 100755 --- a/scripts/deploy-investor-vesting.js +++ b/scripts/deploy-investor-vesting.js @@ -3,6 +3,7 @@ const fs = require('fs'); const csv = require('csv-parse/sync'); const chalk = require('chalk'); + // This script will deploy many investor contract, it takes as input a CSV "investors.csv" which is required to have // these headers: beneficiary,revoker,start,end,transferableBeneficiary,amount // @@ -16,6 +17,10 @@ const seshAddress = "0x7D7fD4E91834A96cD9Fb2369E7f4EB72383bbdEd"; const rewardsAddress = "0x9d8aB00880CBBdc2Dcd29C179779469A82E7be35"; const multiContributorAddress = "0x36Ee2Da54a7E727cC996A441826BBEdda6336B71"; +// Configuration constants +const SHOULD_VERIFY_CONTRACTS = true; +const SHOULD_TRANSFER_FUNDS = false; + async function verifyContract(address, constructorArgs) { console.log(chalk.yellow("\nVerifying contract on Etherscan...")); try { @@ -88,6 +93,8 @@ async function main() { } const deployedContracts = []; + + const seshContract = await hre.ethers.getContractAt("SESH", seshAddress); // Deploy contracts for each investor for (const record of records) { @@ -130,17 +137,19 @@ async function main() { console.log(chalk.green("Vesting contract deployed to:"), chalk.yellow(vestingAddress)); - console.log("Waiting for deployment to be confirmed..."); - await vestingContract.deploymentTransaction().wait(5); - - await verifyContract(vestingAddress, constructorArgs); + if (SHOULD_VERIFY_CONTRACTS) { + console.log("Waiting for deployment to be confirmed..."); + await vestingContract.deploymentTransaction().wait(5); + await verifyContract(vestingAddress, constructorArgs); + } - const seshContract = await hre.ethers.getContractAt("SESH", seshAddress); - const amount = hre.ethers.parseUnits(record.amount, 9); // Assuming 9 decimals for SESH - const transferTx = await seshContract.transfer(vestingAddress, amount); - await transferTx.wait(); - - console.log(chalk.green("Tokens transferred:"), chalk.yellow(record.amount), "SESH"); + if (SHOULD_TRANSFER_FUNDS) { + const amount = hre.ethers.parseUnits(record.amount, 9); // Assuming 9 decimals for SESH + const transferTx = await seshContract.transfer(vestingAddress, amount); + await transferTx.wait(); + + console.log(chalk.green("Tokens transferred:"), chalk.yellow(record.amount), "SESH"); + } deployedContracts.push({ beneficiary: record.beneficiary, diff --git a/scripts/transfer-investor-tokens.js b/scripts/transfer-investor-tokens.js new file mode 100644 index 0000000..2dc6a1e --- /dev/null +++ b/scripts/transfer-investor-tokens.js @@ -0,0 +1,98 @@ +const hre = require("hardhat"); +const fs = require('fs'); +const chalk = require('chalk'); + +// Constants +const seshAddress = "0x6C9D6d6FB69927e3CED37374d820121c7c5b77e1"; +// Load this jsonFilePath based on what is output when running deploy-investor-vesting.js script. Its default +// output path is: `deployments/vesting-${networkName}-${Date.now()}.json` +const jsonFilePath = "./deployments/vesting-sepolia-1747608242040.json"; + +async function main() { + const [deployer] = await hre.ethers.getSigners(); + console.log("Transferring tokens with account:", chalk.yellow(deployer.address)); + + const networkName = hre.network.name; + console.log("Network:", chalk.cyan(networkName)); + console.log("SESH token address:", chalk.yellow(seshAddress)); + console.log("JSON file:", chalk.yellow(jsonFilePath)); + + if (!fs.existsSync(jsonFilePath)) { + console.error(chalk.red(`Error: JSON file not found at ${jsonFilePath}`)); + process.exit(1); + } + + if (!hre.ethers.isAddress(seshAddress)) { + console.error(chalk.red(`Error: Invalid SESH token address: ${seshAddress}`)); + process.exit(1); + } + + const fileContent = fs.readFileSync(jsonFilePath, 'utf8'); + let deployments; + + try { + deployments = JSON.parse(fileContent); + } catch (error) { + console.error(chalk.red(`Error parsing JSON file: ${error.message}`)); + process.exit(1); + } + + if (!deployments || !Array.isArray(deployments['contracts']) || deployments['contracts'].length === 0) { + console.error(chalk.red("Error: JSON file is empty or invalid")); + process.exit(1); + } + + const seshContract = await hre.ethers.getContractAt("SESH", seshAddress); + + const deployerBalance = await seshContract.balanceOf(deployer.address); + const totalRequired = deployments['contracts'].reduce((sum, deployment) => { + return sum + hre.ethers.parseUnits(deployment.amount, 9); // Assuming 9 decimals for SESH + }, 0n); + + console.log("Your balance:", chalk.yellow(hre.ethers.formatUnits(deployerBalance, 9)), "SESH"); + console.log("Total required:", chalk.yellow(hre.ethers.formatUnits(totalRequired, 9)), "SESH"); + + if (deployerBalance < totalRequired) { + console.error(chalk.red("Error: Insufficient SESH balance for transfers")); + console.error(`You have ${hre.ethers.formatUnits(deployerBalance, 9)} SESH, but need ${hre.ethers.formatUnits(totalRequired, 9)} SESH`); + process.exit(1); + } + + console.log(chalk.yellow("Starting transfers...\n")); + + let successful = 0; + let failed = 0; + + for (const deployment of deployments['contracts']) { + try { + if (!hre.ethers.isAddress(deployment['vestingAddress'])) { + throw new Error(`Invalid vesting contract address: ${deployment['vestingAddress']}`); + } + + const amount = hre.ethers.parseUnits(deployment['amount'], 9); // Assuming 9 decimals for SESH + console.log(chalk.cyan(`Transferring ${deployment['amount']} SESH to ${deployment['vestingAddress']}...`)); + + const transferTx = await seshContract.transfer(deployment['vestingAddress'], amount); + await transferTx.wait(); + + console.log(chalk.green("✓ Transfer successful! Tx hash:"), transferTx.hash); + successful++; + } catch (error) { + console.error(chalk.red(`Error transferring to ${deployment['vestingAddress']}:`), error.message); + failed++; + } + } + + console.log(chalk.cyan("\nTransfer Summary:")); + console.log("Total contracts:", chalk.yellow(deployments['contracts'].length)); + console.log("Successful:", chalk.green(successful)); + console.log("Failed:", failed > 0 ? chalk.red(failed) : chalk.green(failed)); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(chalk.red("Unhandled error:")); + console.error(error); + process.exit(1); + });