Files
DLE/backend/scripts/verify-with-hardhat-v2.js

422 lines
17 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Верификация контрактов с Hardhat V2 API
*/
const { execSync } = require('child_process');
const DeployParamsService = require('../services/deployParamsService');
const deploymentWebSocketService = require('../services/deploymentWebSocketService');
async function verifyWithHardhatV2(params = null, deployedNetworks = null) {
console.log('🚀 Запуск верификации с Hardhat V2...');
try {
// Если параметры не переданы, получаем их из базы данных
if (!params) {
const DeployParamsService = require('../services/deployParamsService');
const deployParamsService = new DeployParamsService();
const latestParams = await deployParamsService.getLatestDeployParams(1);
if (latestParams.length === 0) {
throw new Error('Нет параметров деплоя в базе данных');
}
params = latestParams[0];
}
if (!params.etherscan_api_key) {
throw new Error('Etherscan API ключ не найден в параметрах');
}
console.log('📋 Параметры деплоя:', {
deploymentId: params.deployment_id,
name: params.name,
symbol: params.symbol
});
// Получаем адреса контрактов
let networks = [];
if (deployedNetworks && Array.isArray(deployedNetworks)) {
// Используем переданные данные о сетях
networks = deployedNetworks;
console.log('📊 Используем переданные данные о развернутых сетях');
} else if (params.deployedNetworks && Array.isArray(params.deployedNetworks)) {
networks = params.deployedNetworks;
} else if (params.dle_address && params.supportedChainIds) {
// Создаем deployedNetworks на основе dle_address и supportedChainIds
networks = params.supportedChainIds.map(chainId => ({
chainId: chainId,
address: params.dle_address
}));
console.log('📊 Создали deployedNetworks на основе dle_address и supportedChainIds');
} else {
throw new Error('Нет данных о развернутых сетях или адресе контракта');
}
console.log(`🌐 Найдено ${networks.length} развернутых сетей`);
// Маппинг chainId на названия сетей
const networkMap = {
1: 'mainnet',
11155111: 'sepolia',
17000: 'holesky',
137: 'polygon',
42161: 'arbitrumOne',
421614: 'arbitrumSepolia',
56: 'bsc',
8453: 'base',
84532: 'baseSepolia'
};
// Подготавливаем аргументы конструктора
const constructorArgs = [
{
name: params.name || '',
symbol: params.symbol || '',
location: params.location || '',
coordinates: params.coordinates || '',
jurisdiction: params.jurisdiction || 0,
oktmo: params.oktmo || '',
okvedCodes: params.okvedCodes || [],
kpp: params.kpp ? params.kpp : 0,
quorumPercentage: params.quorumPercentage || 51,
initialPartners: params.initialPartners || [],
initialAmounts: (params.initialAmounts || []).map(amount => (parseFloat(amount) * 10**18).toString()),
supportedChainIds: (params.supportedChainIds || []).map(id => id.toString())
},
(params.currentChainId || params.supportedChainIds?.[0] || 1).toString(),
params.initializer || params.initialPartners?.[0] || "0x0000000000000000000000000000000000000000"
];
console.log('📊 Аргументы конструктора подготовлены');
// Верифицируем контракт в каждой сети
const verificationResults = [];
for (const network of networks) {
const { chainId, address } = network;
if (!address || address === '0x0000000000000000000000000000000000000000') {
console.log(`⚠️ Пропускаем сеть ${chainId} - нет адреса контракта`);
verificationResults.push({
success: false,
network: chainId,
error: 'No contract address'
});
continue;
}
const networkName = networkMap[chainId];
if (!networkName) {
console.log(`⚠️ Неизвестная сеть ${chainId}, пропускаем верификацию`);
verificationResults.push({
success: false,
network: chainId,
error: 'Unknown network'
});
continue;
}
console.log(`\n🔍 Верификация в сети ${networkName} (chainId: ${chainId})`);
console.log(`📍 Адрес: ${address}`);
// Добавляем задержку между верификациями
if (verificationResults.length > 0) {
console.log('⏳ Ждем 5 секунд перед следующей верификацией...');
await new Promise(resolve => setTimeout(resolve, 5000));
}
// Создаем временный файл с аргументами конструктора
const fs = require('fs');
const path = require('path');
const argsFile = path.join(__dirname, `constructor-args-${Date.now()}.json`);
try {
fs.writeFileSync(argsFile, JSON.stringify(constructorArgs, null, 2));
// Формируем команду верификации с файлом аргументов
const command = `ETHERSCAN_API_KEY="${params.etherscan_api_key}" npx hardhat verify --network ${networkName} ${address} --constructor-args ${argsFile}`;
console.log(`💻 Выполняем команду: npx hardhat verify --network ${networkName} ${address} --constructor-args ${argsFile}`);
const output = execSync(command, {
cwd: '/app',
encoding: 'utf8',
stdio: 'pipe'
});
console.log('✅ Верификация успешна:');
console.log(output);
verificationResults.push({
success: true,
network: networkName,
chainId: chainId
});
// Удаляем временный файл
try {
fs.unlinkSync(argsFile);
} catch (e) {
console.log(`⚠️ Не удалось удалить временный файл: ${argsFile}`);
}
} catch (error) {
// Удаляем временный файл в случае ошибки
try {
fs.unlinkSync(argsFile);
} catch (e) {
console.log(`⚠️ Не удалось удалить временный файл: ${argsFile}`);
}
const errorOutput = error.stdout || error.stderr || error.message;
console.log('📥 Вывод команды:');
console.log(errorOutput);
if (errorOutput.includes('Already Verified')) {
console.log(' Контракт уже верифицирован');
verificationResults.push({
success: true,
network: networkName,
chainId: chainId,
alreadyVerified: true
});
} else if (errorOutput.includes('Successfully verified')) {
console.log('✅ Контракт успешно верифицирован!');
verificationResults.push({
success: true,
network: networkName,
chainId: chainId
});
} else {
console.log('❌ Ошибка верификации');
verificationResults.push({
success: false,
network: networkName,
chainId: chainId,
error: errorOutput
});
}
}
}
// Выводим итоговые результаты
console.log('\n📊 Итоговые результаты верификации:');
const successful = verificationResults.filter(r => r.success).length;
const failed = verificationResults.filter(r => !r.success).length;
const alreadyVerified = verificationResults.filter(r => r.alreadyVerified).length;
console.log(`✅ Успешно верифицировано: ${successful}`);
console.log(` Уже было верифицировано: ${alreadyVerified}`);
console.log(`❌ Ошибки: ${failed}`);
verificationResults.forEach(result => {
const status = result.success
? (result.alreadyVerified ? '' : '✅')
: '❌';
console.log(`${status} ${result.network} (${result.chainId}): ${result.success ? 'OK' : result.error?.substring(0, 100) + '...'}`);
});
console.log('\n🎉 Верификация завершена!');
} catch (error) {
console.error('💥 Ошибка верификации:', error.message);
console.error(error.stack);
process.exit(1);
}
}
// Запускаем верификацию если скрипт вызван напрямую
if (require.main === module) {
// Проверяем аргументы командной строки
const args = process.argv.slice(2);
if (args.includes('--modules')) {
// Верификация модулей
verifyModules()
.then(() => {
console.log('\n🏁 Верификация модулей завершена');
process.exit(0);
})
.catch((error) => {
console.error('💥 Верификация модулей завершилась с ошибкой:', error);
process.exit(1);
});
} else {
// Верификация основного DLE контракта
verifyWithHardhatV2()
.then(() => {
console.log('\n🏁 Скрипт завершен');
process.exit(0);
})
.catch((error) => {
console.error('💥 Скрипт завершился с ошибкой:', error);
process.exit(1);
});
}
}
// Функция для верификации модулей
async function verifyModules() {
console.log('🚀 Запуск верификации модулей...');
try {
// Загружаем параметры из базы данных
const deployParamsService = new DeployParamsService();
const paramsArray = await deployParamsService.getLatestDeployParams(1);
if (paramsArray.length === 0) {
throw new Error('Нет параметров деплоя в базе данных');
}
const params = paramsArray[0];
const dleAddress = params.dle_address;
if (!dleAddress) {
throw new Error('Адрес DLE не найден в параметрах');
}
// Уведомляем WebSocket клиентов о начале верификации
deploymentWebSocketService.addDeploymentLog(dleAddress, 'info', 'Начало верификации модулей');
console.log('📋 Параметры верификации модулей:', {
dleAddress: dleAddress,
name: params.name,
symbol: params.symbol
});
// Читаем файлы модулей
const fs = require('fs');
const path = require('path');
const modulesDir = path.join(__dirname, 'contracts-data/modules');
if (!fs.existsSync(modulesDir)) {
console.log('📁 Папка модулей не найдена:', modulesDir);
return;
}
const moduleFiles = fs.readdirSync(modulesDir).filter(file => file.endsWith('.json'));
console.log(`📁 Найдено ${moduleFiles.length} файлов модулей`);
// Конфигурация модулей для верификации
const MODULE_CONFIGS = {
treasury: {
contractName: 'TreasuryModule',
constructorArgs: (dleAddress, chainId, walletAddress) => [
dleAddress,
chainId,
walletAddress
]
},
timelock: {
contractName: 'TimelockModule',
constructorArgs: (dleAddress, chainId, walletAddress) => [
dleAddress
]
},
reader: {
contractName: 'DLEReader',
constructorArgs: (dleAddress, chainId, walletAddress) => [
dleAddress
]
},
hierarchicalVoting: {
contractName: 'HierarchicalVotingModule',
constructorArgs: (dleAddress, chainId, walletAddress) => [
dleAddress
]
}
};
// Маппинг chainId на названия сетей для Hardhat
const networkMap = {
11155111: 'sepolia',
17000: 'holesky',
421614: 'arbitrumSepolia',
84532: 'baseSepolia'
};
// Верифицируем каждый модуль
for (const file of moduleFiles) {
const filePath = path.join(modulesDir, file);
const moduleData = JSON.parse(fs.readFileSync(filePath, 'utf8'));
const moduleConfig = MODULE_CONFIGS[moduleData.moduleType];
if (!moduleConfig) {
console.log(`⚠️ Неизвестный тип модуля: ${moduleData.moduleType}`);
continue;
}
console.log(`🔍 Верификация модуля: ${moduleData.moduleType}`);
// Верифицируем в каждой сети
for (const network of moduleData.networks) {
if (!network.success || !network.address) {
console.log(`⚠️ Пропускаем сеть ${network.chainId} - модуль не задеплоен`);
continue;
}
const networkName = networkMap[network.chainId];
if (!networkName) {
console.log(`⚠️ Неизвестная сеть: ${network.chainId}`);
continue;
}
try {
console.log(`🔍 Верификация ${moduleData.moduleType} в сети ${networkName} (${network.chainId})`);
// Подготавливаем аргументы конструктора
const constructorArgs = moduleConfig.constructorArgs(
dleAddress,
network.chainId,
params.initializer || "0x0000000000000000000000000000000000000000"
);
// Создаем временный файл с аргументами
const argsFile = path.join(__dirname, `temp-args-${Date.now()}.json`);
fs.writeFileSync(argsFile, JSON.stringify(constructorArgs, null, 2));
// Выполняем верификацию
const command = `ETHERSCAN_API_KEY="${params.etherscan_api_key}" npx hardhat verify --network ${networkName} ${network.address} --constructor-args ${argsFile}`;
console.log(`📝 Команда верификации: npx hardhat verify --network ${networkName} ${network.address} --constructor-args ${argsFile}`);
try {
const output = execSync(command, {
cwd: '/app',
encoding: 'utf8',
stdio: 'pipe'
});
console.log(`${moduleData.moduleType} успешно верифицирован в ${networkName}`);
console.log(output);
// Уведомляем WebSocket клиентов о успешной верификации
deploymentWebSocketService.addDeploymentLog(dleAddress, 'success', `Модуль ${moduleData.moduleType} верифицирован в ${networkName}`);
deploymentWebSocketService.notifyModuleVerified(dleAddress, moduleData.moduleType, networkName);
} catch (verifyError) {
console.log(`❌ Ошибка верификации ${moduleData.moduleType} в ${networkName}: ${verifyError.message}`);
} finally {
// Удаляем временный файл
if (fs.existsSync(argsFile)) {
fs.unlinkSync(argsFile);
}
}
} catch (error) {
console.error(`❌ Ошибка при верификации ${moduleData.moduleType} в сети ${network.chainId}:`, error.message);
}
}
}
console.log('\n🏁 Верификация модулей завершена');
// Уведомляем WebSocket клиентов о завершении верификации
deploymentWebSocketService.addDeploymentLog(dleAddress, 'success', 'Верификация всех модулей завершена');
deploymentWebSocketService.notifyModulesUpdated(dleAddress);
} catch (error) {
console.error('❌ Ошибка при верификации модулей:', error.message);
throw error;
}
}
module.exports = { verifyWithHardhatV2, verifyContracts: verifyWithHardhatV2, verifyModules };