ваше сообщение коммита
This commit is contained in:
360
backend/contracts/DLEReader.sol
Normal file
360
backend/contracts/DLEReader.sol
Normal 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user