ваше сообщение коммита

This commit is contained in:
2025-08-29 18:37:57 +03:00
parent 8e50c6c4d8
commit 4e4cb611a1
53 changed files with 4380 additions and 5902 deletions

View File

@@ -0,0 +1,360 @@
// SPDX-License-Identifier: PROPRIETARY AND MIT
// Copyright (c) 2024-2025 Тарабанов Александр Викторович
// All rights reserved.
pragma solidity ^0.8.20;
interface IDLEReader {
// Структуры из основного контракта
struct DLEInfo {
string name;
string symbol;
string location;
string coordinates;
uint256 jurisdiction;
string[] okvedCodes;
uint256 kpp;
uint256 creationTimestamp;
bool isActive;
}
struct Proposal {
uint256 id;
string description;
uint256 forVotes;
uint256 againstVotes;
bool executed;
bool canceled;
uint256 deadline;
address initiator;
bytes operation;
uint256 governanceChainId;
uint256[] targetChains;
uint256 snapshotTimepoint;
}
// Основные функции чтения
function getDLEInfo() external view returns (DLEInfo memory);
function proposals(uint256) external view returns (
uint256 id,
string memory description,
uint256 forVotes,
uint256 againstVotes,
bool executed,
bool canceled,
uint256 deadline,
address initiator,
bytes memory operation,
uint256 governanceChainId,
uint256 snapshotTimepoint
);
function allProposalIds(uint256) external view returns (uint256);
function supportedChainIds(uint256) external view returns (uint256);
function quorumPercentage() external view returns (uint256);
function currentChainId() external view returns (uint256);
function totalSupply() external view returns (uint256);
function getPastTotalSupply(uint256) external view returns (uint256);
function getPastVotes(address, uint256) external view returns (uint256);
function checkProposalResult(uint256) external view returns (bool, bool);
function getProposalState(uint256) external view returns (uint8);
function balanceOf(address) external view returns (uint256);
function isChainSupported(uint256) external view returns (bool);
function isModuleActive(bytes32) external view returns (bool);
function getModuleAddress(bytes32) external view returns (address);
}
/**
* @title DLEReader
* @dev Read-only контракт для API функций DLE
*
* БЕЗОПАСНОСТЬ:
* - Только чтение данных (view/pure функции)
* - Не изменяет состояние основного контракта
* - Можно безопасно обновлять независимо от DLE
* - Нет доступа к приватным данным
*/
contract DLEReader {
address public immutable dleContract;
constructor(address _dleContract) {
require(_dleContract != address(0), "DLE contract cannot be zero");
require(_dleContract.code.length > 0, "DLE contract must exist");
dleContract = _dleContract;
}
// ===== АГРЕГИРОВАННЫЕ ДАННЫЕ =====
/**
* @dev Получить полную сводку по предложению
*/
function getProposalSummary(uint256 _proposalId) external view returns (
uint256 id,
string memory description,
uint256 forVotes,
uint256 againstVotes,
bool executed,
bool canceled,
uint256 deadline,
address initiator,
uint256 governanceChainId,
uint256 snapshotTimepoint,
uint256[] memory targetChains,
uint8 state,
bool passed,
bool quorumReached
) {
IDLEReader dle = IDLEReader(dleContract);
// Получаем основные данные предложения
(
id,
description,
forVotes,
againstVotes,
executed,
canceled,
deadline,
initiator,
, // operation не нужна для сводки
governanceChainId,
snapshotTimepoint
) = dle.proposals(_proposalId);
// Получаем дополнительные данные
state = dle.getProposalState(_proposalId);
(passed, quorumReached) = dle.checkProposalResult(_proposalId);
// TODO: targetChains требует отдельной функции в основном контракте
targetChains = new uint256[](0);
}
/**
* @dev Получить параметры governance
*/
function getGovernanceParams() external view returns (
uint256 quorumPct,
uint256 chainId,
uint256 supportedCount,
uint256 totalSupply,
uint256 proposalsCount
) {
IDLEReader dle = IDLEReader(dleContract);
quorumPct = dle.quorumPercentage();
chainId = dle.currentChainId();
totalSupply = dle.totalSupply();
// Считаем поддерживаемые сети
supportedCount = 0;
for (uint256 i = 0; i < 50; i++) { // Ограничиваем итерации
try dle.supportedChainIds(i) returns (uint256) {
supportedCount++;
} catch {
break;
}
}
// Считаем предложения
proposalsCount = 0;
for (uint256 i = 0; i < 1000; i++) { // Ограничиваем итерации
try dle.allProposalIds(i) returns (uint256) {
proposalsCount++;
} catch {
break;
}
}
}
/**
* @dev Получить список поддерживаемых сетей
*/
function listSupportedChains() external view returns (uint256[] memory chains) {
IDLEReader dle = IDLEReader(dleContract);
// Сначала считаем количество
uint256 count = 0;
for (uint256 i = 0; i < 50; i++) {
try dle.supportedChainIds(i) returns (uint256) {
count++;
} catch {
break;
}
}
// Затем заполняем массив
chains = new uint256[](count);
for (uint256 i = 0; i < count; i++) {
chains[i] = dle.supportedChainIds(i);
}
}
/**
* @dev Получить список предложений с пагинацией
*/
function listProposals(uint256 offset, uint256 limit) external view returns (
uint256[] memory proposalIds,
uint256 total
) {
IDLEReader dle = IDLEReader(dleContract);
// Считаем общее количество
total = 0;
for (uint256 i = 0; i < 10000; i++) { // Увеличиваем лимит для предложений
try dle.allProposalIds(i) returns (uint256) {
total++;
} catch {
break;
}
}
// Проверяем границы
if (offset >= total) {
return (new uint256[](0), total);
}
uint256 end = offset + limit;
if (end > total) end = total;
// Заполняем страницу
proposalIds = new uint256[](end - offset);
for (uint256 i = offset; i < end; i++) {
proposalIds[i - offset] = dle.allProposalIds(i);
}
}
/**
* @dev Получить голосующую силу на определённый момент времени
*/
function getVotingPowerAt(address voter, uint256 timepoint) external view returns (uint256) {
return IDLEReader(dleContract).getPastVotes(voter, timepoint);
}
/**
* @dev Получить размер кворума на определённый момент времени
*/
function getQuorumAt(uint256 timepoint) external view returns (uint256) {
IDLEReader dle = IDLEReader(dleContract);
uint256 supply = dle.getPastTotalSupply(timepoint);
uint256 quorumPct = dle.quorumPercentage();
return (supply * quorumPct) / 100;
}
/**
* @dev Получить детали голосования по предложению
*/
function getProposalVotes(uint256 _proposalId) external view returns (
uint256 forVotes,
uint256 againstVotes,
uint256 totalVotes,
uint256 quorumRequired,
uint256 quorumCurrent,
bool quorumReached
) {
IDLEReader dle = IDLEReader(dleContract);
// Получаем основные данные предложения
uint256 snapshotTimepoint;
(
, // id
, // description
forVotes,
againstVotes,
, // executed
, // canceled
, // deadline
, // initiator
, // operation
, // governanceChainId
snapshotTimepoint
) = dle.proposals(_proposalId);
totalVotes = forVotes + againstVotes;
// Вычисляем кворум
uint256 supply = dle.getPastTotalSupply(snapshotTimepoint);
uint256 quorumPct = dle.quorumPercentage();
quorumRequired = (supply * quorumPct) / 100;
quorumCurrent = totalVotes;
quorumReached = totalVotes >= quorumRequired;
}
/**
* @dev Получить статистику по адресу
*/
function getAddressStats(address user) external view returns (
uint256 tokenBalance,
uint256 currentVotingPower,
uint256 delegatedTo,
bool hasTokens
) {
IDLEReader dle = IDLEReader(dleContract);
tokenBalance = dle.balanceOf(user);
currentVotingPower = dle.getPastVotes(user, block.number - 1);
hasTokens = tokenBalance > 0;
// delegatedTo требует дополнительных функций в основном контракте
delegatedTo = 0; // Placeholder
}
/**
* @dev Получить информацию о модулях
*/
function getModulesInfo(bytes32[] memory moduleIds) external view returns (
address[] memory addresses,
bool[] memory active
) {
IDLEReader dle = IDLEReader(dleContract);
addresses = new address[](moduleIds.length);
active = new bool[](moduleIds.length);
for (uint256 i = 0; i < moduleIds.length; i++) {
addresses[i] = dle.getModuleAddress(moduleIds[i]);
active[i] = dle.isModuleActive(moduleIds[i]);
}
}
/**
* @dev Получить состояние DLE
*/
function getDLEStatus() external view returns (
IDLEReader.DLEInfo memory info,
uint256 totalSupply,
uint256 currentChain,
uint256 quorumPct,
uint256 totalProposals,
uint256 supportedChains
) {
IDLEReader dle = IDLEReader(dleContract);
info = dle.getDLEInfo();
totalSupply = dle.totalSupply();
currentChain = dle.currentChainId();
quorumPct = dle.quorumPercentage();
// Считаем предложения и сети
(,, supportedChains, totalSupply, totalProposals) = this.getGovernanceParams();
}
/**
* @dev Batch получение состояний предложений
*/
function getProposalStates(uint256[] memory proposalIds) external view returns (
uint8[] memory states,
bool[] memory passed,
bool[] memory quorumReached
) {
IDLEReader dle = IDLEReader(dleContract);
states = new uint8[](proposalIds.length);
passed = new bool[](proposalIds.length);
quorumReached = new bool[](proposalIds.length);
for (uint256 i = 0; i < proposalIds.length; i++) {
states[i] = dle.getProposalState(proposalIds[i]);
(passed[i], quorumReached[i]) = dle.checkProposalResult(proposalIds[i]);
}
}
}