Files
DLE/backend/routes/dleModules.js

929 lines
37 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

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.

/**
* Copyright (c) 2024-2025 Тарабанов Александр Викторович
* All rights reserved.
*
* This software is proprietary and confidential.
* Unauthorized copying, modification, or distribution is prohibited.
*
* For licensing inquiries: info@hb3-accelerator.com
* Website: https://hb3-accelerator.com
* GitHub: https://github.com/HB3-ACCELERATOR
*/
const express = require('express');
const router = express.Router();
const { ethers } = require('ethers');
const rpcProviderService = require('../services/rpcProviderService');
// Проверить активность модуля
router.post('/is-module-active', async (req, res) => {
try {
const { dleAddress, moduleId } = req.body;
if (!dleAddress || !moduleId) {
return res.status(400).json({
success: false,
error: 'Адрес DLE и ID модуля обязательны'
});
}
console.log(`[DLE Modules] Проверка активности модуля: ${moduleId} для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const dleAbi = [
"function isModuleActive(bytes32 _moduleId) external view returns (bool)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Проверяем активность модуля
const isActive = await dle.isModuleActive(moduleId);
console.log(`[DLE Modules] Активность модуля ${moduleId}: ${isActive}`);
res.json({
success: true,
data: {
isActive: isActive
}
});
} catch (error) {
console.error('[DLE Modules] Ошибка при проверке активности модуля:', error);
res.status(500).json({
success: false,
error: 'Ошибка при проверке активности модуля: ' + error.message
});
}
});
// Получить информацию о задеплоенных модулях для DLE
router.get('/deployed/:dleAddress', async (req, res) => {
try {
const { dleAddress } = req.params;
if (!dleAddress) {
return res.status(400).json({
success: false,
error: 'Адрес DLE обязателен'
});
}
console.log(`[DLE Modules] Получение информации о модулях для DLE: ${dleAddress}`);
// Получаем информацию о модулях из файлов деплоя
const modulesInfo = await getDeployedModulesInfo(dleAddress);
res.json({
success: true,
data: modulesInfo
});
} catch (error) {
console.error('[DLE Modules] Ошибка при получении информации о модулях:', error);
res.status(500).json({
success: false,
error: 'Ошибка при получении информации о модулях: ' + error.message
});
}
});
// Получить адрес модуля
router.post('/get-module-address', async (req, res) => {
try {
const { dleAddress, moduleId } = req.body;
if (!dleAddress || !moduleId) {
return res.status(400).json({
success: false,
error: 'Адрес DLE и ID модуля обязательны'
});
}
console.log(`[DLE Modules] Получение адреса модуля: ${moduleId} для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const dleAbi = [
"function getModuleAddress(bytes32 _moduleId) external view returns (address)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Получаем адрес модуля
const moduleAddress = await dle.getModuleAddress(moduleId);
console.log(`[DLE Modules] Адрес модуля ${moduleId}: ${moduleAddress}`);
res.json({
success: true,
data: {
moduleAddress: moduleAddress
}
});
} catch (error) {
console.error('[DLE Modules] Ошибка при получении адреса модуля:', error);
res.status(500).json({
success: false,
error: 'Ошибка при получении адреса модуля: ' + error.message
});
}
});
// Получить все модули
router.post('/get-all-modules', async (req, res) => {
try {
const { dleAddress } = req.body;
if (!dleAddress) {
return res.status(400).json({
success: false,
error: 'Адрес DLE обязателен'
});
}
console.log(`[DLE Modules] Получение всех модулей для DLE: ${dleAddress}`);
// Сначала пытаемся получить модули из файлов деплоя
console.log(`[DLE Modules] Вызываем getDeployedModulesInfo...`);
const modulesInfo = await getDeployedModulesInfo(dleAddress);
console.log(`[DLE Modules] Результат getDeployedModulesInfo:`, modulesInfo);
if (modulesInfo.modules && modulesInfo.modules.length > 0) {
console.log(`[DLE Modules] Модули найдены в файлах, количество: ${modulesInfo.modules.length}`);
// Преобразуем данные в нужный формат для frontend
// Группируем модули по типам, а не по сетям
const moduleGroups = {
treasury: {
moduleId: "0x747265617375727900000000000000000000000000000000000000000000000000",
moduleName: "TREASURY",
moduleDescription: "Казначейство DLE - управление финансами, депозиты, выводы, дивиденды",
addresses: [],
isActive: true,
deployedAt: modulesInfo.deployTimestamp
},
timelock: {
moduleId: "0x74696d656c6f636b000000000000000000000000000000000000000000000000",
moduleName: "TIMELOCK",
moduleDescription: "Модуль задержек исполнения - безопасность критических операций через таймлоки",
addresses: [],
isActive: true,
deployedAt: modulesInfo.deployTimestamp
},
reader: {
moduleId: "0x726561646572000000000000000000000000000000000000000000000000000000",
moduleName: "READER",
moduleDescription: "Модуль чтения данных DLE - получение информации о контракте",
addresses: [],
isActive: true,
deployedAt: modulesInfo.deployTimestamp
}
};
// Собираем адреса для каждого типа модуля из всех сетей
// Определяем реальные chainId для каждого адреса
for (let networkIndex = 0; networkIndex < modulesInfo.modules.length; networkIndex++) {
const networkModules = modulesInfo.modules[networkIndex];
console.log(`[DLE Modules] Обрабатываем сеть ${networkIndex + 1}:`, networkModules);
// Получаем информацию о сети из файла деплоя
let chainId = null;
let networkName = `Сеть ${networkIndex + 1}`;
// Если в файле есть информация о сетях, используем её
if (modulesInfo.networks && modulesInfo.networks[networkIndex]) {
chainId = modulesInfo.networks[networkIndex].chainId;
networkName = modulesInfo.networks[networkIndex].networkName || `Сеть ${networkIndex + 1}`;
}
if (networkModules.treasuryModule) {
moduleGroups.treasury.addresses.push({
address: networkModules.treasuryModule,
networkName: networkName,
networkIndex: networkIndex,
chainId: chainId,
verificationStatus: modulesInfo.verification?.[networkIndex]?.treasuryModule || 'pending'
});
}
if (networkModules.timelockModule) {
moduleGroups.timelock.addresses.push({
address: networkModules.timelockModule,
networkName: networkName,
networkIndex: networkIndex,
chainId: chainId,
verificationStatus: modulesInfo.verification?.[networkIndex]?.timelockModule || 'pending'
});
}
if (networkModules.dleReader) {
moduleGroups.reader.addresses.push({
address: networkModules.dleReader,
networkName: networkName,
networkIndex: networkIndex,
chainId: chainId,
verificationStatus: modulesInfo.verification?.[networkIndex]?.dleReader || 'pending'
});
}
}
// Преобразуем в массив модулей
const formattedModules = Object.values(moduleGroups).filter(module => module.addresses.length > 0);
console.log(`[DLE Modules] Сгруппированные модули:`, formattedModules);
console.log(`[DLE Modules] Найдено типов модулей: ${formattedModules.length}`);
res.json({
success: true,
data: {
modules: formattedModules,
modulesInitialized: true,
totalModules: formattedModules.length,
activeModules: formattedModules.length
}
});
} else {
console.log(`[DLE Modules] Файлы модулей не найдены или пусты, проверяем блокчейн для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const dleAbi = [
"function isModuleActive(bytes32 _moduleId) external view returns (bool)",
"function getModuleAddress(bytes32 _moduleId) external view returns (address)",
"function modulesInitialized() external view returns (bool)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Проверяем инициализацию модулей
let modulesInitialized = false;
try {
modulesInitialized = await dle.modulesInitialized();
} catch (error) {
console.log(`[DLE Modules] Ошибка при проверке инициализации модулей:`, error.message);
}
if (!modulesInitialized) {
console.log(`[DLE Modules] Модули для DLE ${dleAddress} не инициализированы`);
return res.json({
success: true,
data: {
modules: [],
modulesInitialized: false,
totalModules: 0,
activeModules: 0
}
});
}
// Список стандартных модулей DLE
const standardModuleIds = [
"0x7472656173757279000000000000000000000000000000000000000000000000", // "treasury"
"0x74696d656c6f636b000000000000000000000000000000000000000000000000", // "timelock"
"0x6d696e7400000000000000000000000000000000000000000000000000000000", // "mint"
"0x6275726e00000000000000000000000000000000000000000000000000000000", // "burn"
"0x6f7261636c650000000000000000000000000000000000000000000000000000", // "oracle"
"0x696e6865726974616e6365000000000000000000000000000000000000000000", // "inheritance"
"0x636f6d6d756e69636174696f6e00000000000000000000000000000000000000", // "communication"
"0x6170706c69636174696f6e000000000000000000000000000000000000000000" // "application"
];
const modules = [];
// Проверяем каждый модуль
for (const moduleId of standardModuleIds) {
try {
const isActive = await dle.isModuleActive(moduleId);
if (isActive) {
const moduleAddress = await dle.getModuleAddress(moduleId);
// Получаем человекочитаемое название модуля
const moduleName = getModuleName(moduleId);
const moduleDescription = getModuleDescription(moduleId);
modules.push({
moduleId: moduleId,
moduleName: moduleName,
moduleDescription: moduleDescription,
moduleAddress: moduleAddress,
isActive: isActive,
deployedAt: new Date().toISOString() // В реальности нужно брать из событий
});
console.log(`[DLE Modules] Найден активный модуль: ${moduleName} по адресу ${moduleAddress}`);
}
} catch (error) {
console.log(`[DLE Modules] Ошибка при проверке модуля ${getModuleName(moduleId)}:`, error.message);
}
}
console.log(`[DLE Modules] Всего найдено активных модулей в блокчейне: ${modules.length}`);
res.json({
success: true,
data: {
modules: modules,
modulesInitialized: modulesInitialized,
totalModules: standardModuleIds.length,
activeModules: modules.length
}
});
}
} catch (error) {
console.error('[DLE Modules] Ошибка при получении всех модулей:', error);
res.status(500).json({
success: false,
error: 'Ошибка при получении всех модулей: ' + error.message
});
}
});
// Создать предложение о добавлении модуля
router.post('/create-add-module-proposal', async (req, res) => {
try {
const { dleAddress, description, duration, moduleId, moduleAddress, chainId } = req.body;
if (!dleAddress || !description || !duration || !moduleId || !moduleAddress || !chainId) {
return res.status(400).json({
success: false,
error: 'Все поля обязательны'
});
}
console.log(`[DLE Modules] Создание предложения о добавлении модуля: ${moduleId} для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const dleAbi = [
"function createAddModuleProposal(string memory _description, uint256 _duration, bytes32 _moduleId, address _moduleAddress, uint256 _chainId) external returns (uint256)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Создаем предложение
const tx = await dle.createAddModuleProposal(description, duration, moduleId, moduleAddress, chainId);
const receipt = await tx.wait();
console.log(`[DLE Modules] Предложение о добавлении модуля создано:`, receipt);
res.json({
success: true,
data: {
proposalId: receipt.logs[0].args.proposalId,
transactionHash: receipt.hash
}
});
} catch (error) {
console.error('[DLE Modules] Ошибка при создании предложения о добавлении модуля:', error);
res.status(500).json({
success: false,
error: 'Ошибка при создании предложения о добавлении модуля: ' + error.message
});
}
});
// Создать предложение об удалении модуля
router.post('/create-remove-module-proposal', async (req, res) => {
try {
const { dleAddress, description, duration, moduleId, chainId } = req.body;
if (!dleAddress || !description || !duration || !moduleId || !chainId) {
return res.status(400).json({
success: false,
error: 'Все поля обязательны'
});
}
console.log(`[DLE Modules] Создание предложения об удалении модуля: ${moduleId} для DLE: ${dleAddress}`);
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(11155111);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
const provider = new ethers.JsonRpcProvider(rpcUrl);
const dleAbi = [
"function createRemoveModuleProposal(string memory _description, uint256 _duration, bytes32 _moduleId, uint256 _chainId) external returns (uint256)"
];
const dle = new ethers.Contract(dleAddress, dleAbi, provider);
// Создаем предложение
const tx = await dle.createRemoveModuleProposal(description, duration, moduleId, chainId);
const receipt = await tx.wait();
console.log(`[DLE Modules] Предложение об удалении модуля создано:`, receipt);
res.json({
success: true,
data: {
proposalId: receipt.logs[0].args.proposalId,
transactionHash: receipt.hash
}
});
} catch (error) {
console.error('[DLE Modules] Ошибка при создании предложения об удалении модуля:', error);
res.status(500).json({
success: false,
error: 'Ошибка при создании предложения об удалении модуля: ' + error.message
});
}
});
// Функция для получения информации о задеплоенных модулях
async function getDeployedModulesInfo(dleAddress) {
const fs = require('fs');
const path = require('path');
try {
// Ищем файл модулей в правильной директории
const tempDir = path.join(__dirname, '../scripts/temp');
const modulesFileName = `modules-${dleAddress.toLowerCase()}.json`;
const modulesFilePath = path.join(tempDir, modulesFileName);
if (!fs.existsSync(modulesFilePath)) {
console.log(`[DLE Modules] Файл модулей не найден: ${modulesFileName}`);
return { modules: [], verification: {} };
}
try {
const data = JSON.parse(fs.readFileSync(modulesFilePath, 'utf8'));
console.log(`[DLE Modules] Загружена информация о модулях для DLE: ${dleAddress}`);
// Получаем статус верификации для каждого модуля
const modulesWithVerification = [];
if (data.modules && Array.isArray(data.modules)) {
for (const networkModules of data.modules) {
if (networkModules.treasuryModule) {
modulesWithVerification.push({
...networkModules,
verificationStatus: data.verification?.[0]?.treasuryModule || 'pending'
});
}
}
}
return {
modules: data.modules || [],
verification: data.verification || {},
deployTimestamp: data.deployTimestamp,
networks: data.networks || [], // ✅ Добавляем поле networks
modulesWithVerification: modulesWithVerification
};
} catch (error) {
console.error(`Ошибка при чтении файла ${modulesFileName}:`, error);
return { modules: [], verification: {} };
}
} catch (error) {
console.error('Ошибка при получении информации о модулях:', error);
return { modules: [], verification: {} };
}
}
// Функция для определения названия сети по chainId
function getNetworkNameByChainId(chainId) {
const networkNames = {
1: 'Ethereum Mainnet',
5: 'Goerli',
11155111: 'Sepolia',
137: 'Polygon Mainnet',
80001: 'Mumbai',
56: 'BSC Mainnet',
97: 'BSC Testnet',
42161: 'Arbitrum One',
421614: 'Arbitrum Sepolia',
10: 'Optimism',
11155420: 'Optimism Sepolia',
8453: 'Base',
84532: 'Base Sepolia'
};
return networkNames[chainId] || `Chain ID ${chainId}`;
}
// Функция для получения модулей из файлов
async function getModulesFromFiles(dleAddress) {
const fs = require('fs');
const path = require('path');
try {
// Ищем файл модулей в правильной директории
const tempDir = path.join(__dirname, '../scripts/temp');
const modulesFileName = `modules-${dleAddress.toLowerCase()}.json`;
const modulesFilePath = path.join(tempDir, modulesFileName);
if (!fs.existsSync(modulesFilePath)) {
console.log(`[DLE Modules] Файл модулей не найден: ${modulesFileName}`);
return [];
}
try {
const data = JSON.parse(fs.readFileSync(modulesFilePath, 'utf8'));
console.log(`[DLE Modules] Загружена информация о модулях для DLE: ${dleAddress}`);
const modules = [];
// Обрабатываем модули из файла
if (data.modules && Array.isArray(data.modules)) {
for (const networkModules of data.modules) {
if (networkModules.treasuryModule) {
modules.push({
moduleId: "0x7472656173757279000000000000000000000000000000000000000000000000",
moduleName: "TREASURY",
moduleDescription: "Казначейство DLE - управление финансами, депозиты, выводы, дивиденды",
moduleAddress: networkModules.treasuryModule,
isActive: true,
deployedAt: data.deployTimestamp
});
}
if (networkModules.timelockModule) {
modules.push({
moduleId: "0x74696d656c6f636b000000000000000000000000000000000000000000000000",
moduleName: "TIMELOCK",
moduleDescription: "Модуль задержек исполнения - безопасность критических операций через таймлоки",
moduleAddress: networkModules.timelockModule,
isActive: true,
deployedAt: data.deployTimestamp
});
}
if (networkModules.dleReader) {
modules.push({
moduleId: "0x726561646572000000000000000000000000000000000000000000000000000000",
moduleName: "READER",
moduleDescription: "Модуль чтения данных DLE - получение информации о контракте",
moduleAddress: networkModules.dleReader,
isActive: true,
deployedAt: data.deployTimestamp
});
}
}
}
// Убираем дубликаты (модули могут быть в нескольких сетях)
const uniqueModules = modules.filter((module, index, self) =>
index === self.findIndex(m => m.moduleId === module.moduleId)
);
return uniqueModules;
} catch (error) {
console.error(`Ошибка при чтении файла ${modulesFileName}:`, error);
return [];
}
} catch (error) {
console.error('Ошибка при получении информации о модулях из файлов:', error);
return [];
}
}
// Вспомогательные функции для получения названий и описаний модулей
function getModuleName(moduleId) {
const moduleNames = {
"0x7472656173757279000000000000000000000000000000000000000000000000": "TREASURY",
"0x74696d656c6f636b000000000000000000000000000000000000000000000000": "TIMELOCK",
"0x6d696e7400000000000000000000000000000000000000000000000000000000": "MINT",
"0x6275726e00000000000000000000000000000000000000000000000000000000": "BURN",
"0x6f7261636c650000000000000000000000000000000000000000000000000000": "ORACLE",
"0x696e6865726974616e6365000000000000000000000000000000000000000000": "INHERITANCE",
"0x636f6d6d756e69636174696f6e00000000000000000000000000000000000000": "COMMUNICATION",
"0x6170706c69636174696f6e000000000000000000000000000000000000000000": "APPLICATION"
};
return moduleNames[moduleId] || "UNKNOWN";
}
function getModuleDescription(moduleId) {
const moduleDescriptions = {
"0x7472656173757279000000000000000000000000000000000000000000000000": "Казначейство DLE - управление финансами, депозиты, выводы, дивиденды",
"0x74696d656c6f636b000000000000000000000000000000000000000000000000": "Модуль задержек исполнения - безопасность критических операций через таймлоки",
"0x6d696e7400000000000000000000000000000000000000000000000000000000": "Модуль выпуска токенов - создание дополнительных токенов DLE через governance",
"0x6275726e00000000000000000000000000000000000000000000000000000000": "Модуль сжигания токенов - уменьшение общего предложения токенов DLE",
"0x6f7261636c650000000000000000000000000000000000000000000000000000": "Модуль оракулов - получение внешних данных для автоматизации DLE",
"0x696e6865726974616e6365000000000000000000000000000000000000000000": "Модуль наследования - передача прав и токенов между участниками DLE",
"0x636f6d6d756e69636174696f6e00000000000000000000000000000000000000": "Модуль коммуникации - уведомления и взаимодействие между участниками DLE",
"0x6170706c69636174696f6e000000000000000000000000000000000000000000": "Модуль заявок - обработка предложений и заявок участников DLE"
};
return moduleDescriptions[moduleId] || "Описание не найдено";
}
// Верификация модуля на Etherscan
router.post('/verify-module', async (req, res) => {
try {
const { dleAddress, moduleId, moduleAddress, moduleName } = req.body;
if (!dleAddress || !moduleId || !moduleAddress || !moduleName) {
return res.status(400).json({
success: false,
error: 'Все параметры обязательны: dleAddress, moduleId, moduleAddress, moduleName'
});
}
console.log(`[DLE Modules] Верификация модуля ${moduleName} по адресу ${moduleAddress}`);
// Получаем API ключ Etherscan из секретов
const { getSecret } = require('../services/secretStore');
let apiKey = await getSecret('ETHERSCAN_V2_API_KEY');
if (!apiKey) {
return res.status(500).json({
success: false,
error: 'API ключ Etherscan не найден в секретах'
});
}
// Определяем chainId (Sepolia)
const chainId = 11155111; // Sepolia testnet
// Определяем имя контракта на основе moduleId
let contractName;
if (moduleId === "0x7472656173757279000000000000000000000000000000000000000000000000") {
contractName = "TreasuryModule";
} else if (moduleId === "0x74696d656c6f636b000000000000000000000000000000000000000000000000") {
contractName = "TimelockModule";
} else if (moduleId === "0x726561646572000000000000000000000000000000000000000000000000000000") {
contractName = "DLEReader";
} else {
contractName = "UnknownModule";
}
console.log(`[DLE Modules] Верификация ${contractName} на Etherscan...`);
// Импортируем сервис верификации
const etherscanV2 = require('../services/etherscanV2VerificationService');
// Получаем RPC URL для Sepolia
const rpcProviderService = require('../services/rpcProviderService');
const rpcUrl = await rpcProviderService.getRpcUrlByChainId(chainId);
if (!rpcUrl) {
return res.status(500).json({
success: false,
error: 'RPC URL для Sepolia не найден'
});
}
// Получаем ABI и bytecode для модуля
const { ethers } = require('ethers');
const provider = new ethers.JsonRpcProvider(rpcUrl);
// Получаем код контракта для проверки существования
const code = await provider.getCode(moduleAddress);
if (code === '0x') {
return res.status(400).json({
success: false,
error: 'По указанному адресу нет контракта'
});
}
// Создаем стандартный JSON input для компиляции
const standardJsonInput = await createStandardJsonInput(contractName, moduleAddress, dleAddress, chainId);
// Отправляем верификацию на Etherscan
const verificationResult = await etherscanV2.submitVerification({
chainId: chainId,
contractAddress: moduleAddress,
contractName: `${contractName}.sol:${contractName}`, // Формат: filename.sol:contractname
compilerVersion: "v0.8.20+commit.a1b79de6", // Версия компилятора (точно как в основном контракте)
standardJsonInput: standardJsonInput.standardJsonInput,
constructorArgsHex: standardJsonInput.constructorArgsHex,
apiKey: apiKey
});
console.log(`[DLE Modules] Результат верификации:`, verificationResult);
// Обновляем статус верификации в файле модулей
await updateModuleVerificationStatus(dleAddress, moduleId, 'success');
res.json({
success: true,
data: {
message: `Модуль ${moduleName} успешно верифицирован`,
verificationResult: verificationResult,
contractName: contractName,
moduleAddress: moduleAddress
}
});
} catch (error) {
console.error('[DLE Modules] Ошибка верификации модуля:', error);
// Обновляем статус верификации в файле модулей
if (req.body.dleAddress && req.body.moduleId) {
await updateModuleVerificationStatus(req.body.dleAddress, req.body.moduleId, 'failed');
}
res.status(500).json({
success: false,
error: 'Ошибка верификации модуля: ' + error.message
});
}
});
// Функция для обновления статуса верификации в файле модулей
async function updateModuleVerificationStatus(dleAddress, moduleId, status) {
try {
const fs = require('fs');
const path = require('path');
const tempDir = path.join(__dirname, '../scripts/temp');
const modulesFileName = `modules-${dleAddress.toLowerCase()}.json`;
const modulesFilePath = path.join(tempDir, modulesFileName);
if (!fs.existsSync(modulesFilePath)) {
console.log(`[DLE Modules] Файл модулей не найден для обновления статуса: ${modulesFileName}`);
return;
}
const data = JSON.parse(fs.readFileSync(modulesFilePath, 'utf8'));
// Обновляем статус верификации для всех сетей
if (data.verification && Array.isArray(data.verification)) {
for (let i = 0; i < data.verification.length; i++) {
if (moduleId === "0x7472656173757279000000000000000000000000000000000000000000000000") {
data.verification[i].treasuryModule = status;
} else if (moduleId === "0x74696d656c6f636b000000000000000000000000000000000000000000000000") {
data.verification[i].timelockModule = status;
} else if (moduleId === "0x726561646572000000000000000000000000000000000000000000000000000000") {
data.verification[i].dleReader = status;
}
}
}
// Записываем обновленные данные обратно в файл
fs.writeFileSync(modulesFilePath, JSON.stringify(data, null, 2));
console.log(`[DLE Modules] Статус верификации обновлен для модуля ${moduleId}: ${status}`);
} catch (error) {
console.error('[DLE Modules] Ошибка обновления статуса верификации:', error);
}
}
// Функция для создания стандартного JSON input для верификации
async function createStandardJsonInput(contractName, moduleAddress, dleAddress, chainId) {
const fs = require('fs');
const path = require('path');
try {
// Читаем исходный код контракта
let contractSource = '';
let contractPath = '';
if (contractName === 'TreasuryModule') {
contractPath = path.join(__dirname, '../contracts/TreasuryModule.sol');
} else if (contractName === 'TimelockModule') {
contractPath = path.join(__dirname, '../contracts/TimelockModule.sol');
} else if (contractName === 'DLEReader') {
contractPath = path.join(__dirname, '../contracts/DLEReader.sol');
} else {
throw new Error(`Неизвестный контракт: ${contractName}`);
}
if (!fs.existsSync(contractPath)) {
throw new Error(`Файл контракта не найден: ${contractPath}`);
}
contractSource = fs.readFileSync(contractPath, 'utf8');
// Определяем конструктор аргументы на основе типа контракта
let constructorArgs = [];
if (contractName === 'TreasuryModule') {
// TreasuryModule: [dleAddress, chainId, emergencyAdmin]
// Нужно получить реальный emergencyAdmin из транзакции деплоя
let emergencyAdmin = dleAddress; // fallback
try {
// Получаем emergencyAdmin из транзакции деплоя
const provider = new ethers.JsonRpcProvider(await require('../services/rpcProviderService').getRpcUrlByChainId(chainId));
const history = await provider.getHistory(moduleAddress);
if (history.length > 0) {
const deployTx = history[0]; // Первая транзакция - это деплой
if (deployTx.from) {
emergencyAdmin = deployTx.from; // deployer становится emergencyAdmin
console.log(`[DLE Modules] Найден emergencyAdmin из транзакции деплоя: ${emergencyAdmin}`);
}
}
} catch (error) {
console.log(`[DLE Modules] Не удалось получить emergencyAdmin из транзакции: ${error.message}`);
}
constructorArgs = [dleAddress, chainId.toString(), emergencyAdmin];
} else if (contractName === 'TimelockModule') {
// TimelockModule: [dleAddress]
constructorArgs = [dleAddress];
} else if (contractName === 'DLEReader') {
// DLEReader: [dleAddress]
constructorArgs = [dleAddress];
}
// Кодируем конструктор аргументы
const { ethers } = require('ethers');
const abiCoder = new ethers.AbiCoder();
let constructorArgsHex = '0x';
if (constructorArgs.length > 0) {
// Определяем типы параметров для каждого контракта
let paramTypes = [];
if (contractName === 'TreasuryModule') {
paramTypes = ['address', 'uint256', 'address'];
} else if (contractName === 'TimelockModule' || contractName === 'DLEReader') {
paramTypes = ['address'];
}
constructorArgsHex = abiCoder.encode(paramTypes, constructorArgs);
}
// Создаем стандартный JSON input
const standardJsonInput = {
language: "Solidity",
sources: {
[contractName + '.sol']: {
content: contractSource
}
},
settings: {
optimizer: {
enabled: true,
runs: 200
},
evmVersion: "paris",
outputSelection: {
"*": {
"*": ["*"]
}
},
libraries: {},
remappings: [
"@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/"
]
}
};
console.log(`[DLE Modules] Создан standardJsonInput для ${contractName}:`, {
contractPath,
constructorArgs,
constructorArgsHex,
sourceLength: contractSource.length
});
return {
standardJsonInput: JSON.stringify(standardJsonInput),
constructorArgsHex: constructorArgsHex
};
} catch (error) {
console.error(`[DLE Modules] Ошибка создания standardJsonInput для ${contractName}:`, error);
throw error;
}
}
module.exports = router;