- Создана форма деплоя TreasuryModule с детальными настройками казны - Создана форма деплоя TimelockModule с настройками временных задержек - Создана форма деплоя DLEReader с простой конфигурацией - Добавлены маршруты и индексы для всех модулей - Исправлены пути импорта BaseLayout - Добавлены авторские права во все файлы - Улучшена архитектура деплоя модулей отдельно от основного DLE
964 lines
39 KiB
Markdown
964 lines
39 KiB
Markdown
<!--
|
||
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
|
||
-->
|
||
|
||
# DLE v2 — краткие обновления
|
||
|
||
- Single‑Chain Governance: голосование фиксируется в одной сети, исполнение в целевых сетях по EIP‑712 подписям без внешних мостов.
|
||
- Снапшоты голосующей силы: `ERC20Votes` (`getPastVotes`, `getPastTotalSupply`) исключают перелив голосов.
|
||
- Делегирование «только на себя»: 1 токен = 1 голос, запрет делегирования третьим лицам.
|
||
- Модульность: казна, таймлок, деактивация, коммуникации выделены в отдельные модули, операции выполняются через ядро DLE.
|
||
- «100% или ничего»: много-сетевые операции исполняются только при готовности всех целевых сетей.
|
||
- Детерминированный деплой: CREATE с выровненным nonce для одинаковых адресов во всех выбранных сетях.
|
||
- Аналитика: добавлены view‑функции для сводок, пагинации и агрегирования по предложениям.
|
||
|
||
---
|
||
|
||
# DLE - Единый Смарт-Контракт с Модульной Архитектурой
|
||
|
||
## 🎯 ПОЛНОЕ ПОНИМАНИЕ ЗАДАЧИ DLE
|
||
|
||
### **1. ОСНОВНАЯ КОНЦЕПЦИЯ:**
|
||
```
|
||
DLE (Digital Legal Entity) = Универсальная цифровая юридическая организация
|
||
├── Один смарт-контракт с одинаковым адресом во всех цепочках
|
||
├── Управление только через токен-холдеров (никаких админских ролей)
|
||
├── Модульная архитектура (основной контракт + добавляемые модули)
|
||
└── Мульти-чейн синхронизация (работа в нескольких блокчейнах одновременно)
|
||
```
|
||
|
||
### **2. АРХИТЕКТУРА СИСТЕМЫ:**
|
||
|
||
#### **Деплой в множественных цепочках:**
|
||
```
|
||
Пользователь выбирает цепочки (например, 4):
|
||
├── Ethereum (ChainId = 1)
|
||
├── Polygon (ChainId = 137)
|
||
├── BSC (ChainId = 56)
|
||
└── Arbitrum (ChainId = 42161)
|
||
|
||
Деплой в каждой цепочке:
|
||
├── Одинаковый адрес DLE (через CREATE2)
|
||
├── Одинаковые токены для партнеров
|
||
└── Синхронизированное состояние
|
||
```
|
||
|
||
#### **Распределение токенов:**
|
||
```
|
||
3 партнера получают по 1000 токенов в каждой из 4 цепочек:
|
||
├── Партнер A: 1000 токенов (в 4 цепочках)
|
||
├── Партнер B: 1000 токенов (в 4 цепочках)
|
||
└── Партнер C: 1000 токенов (в 4 цепочках)
|
||
|
||
Итого: 3000 токенов в каждой цепочке
|
||
```
|
||
|
||
### **3. СИСТЕМА УПРАВЛЕНИЯ:**
|
||
|
||
#### **Голосование токен‑холдеров:**
|
||
```
|
||
- Только токен-холдеры участвуют в управлении
|
||
- Каждый токен = одна голосующая сила
|
||
- Кворум настраиваемый (например, 60% от общего количества токенов)
|
||
- Коллективное голосование токен‑холдеров (ERC20Votes снапшоты)
|
||
```
|
||
|
||
#### **Создание предложений:**
|
||
```
|
||
1. Токен-холдер создает предложение
|
||
2. Выбирает ОДНУ цепочку для сбора подписей/голосов
|
||
3. Сбор происходит только в выбранной цепочке
|
||
4. При достижении кворума - исполнение
|
||
5. Синхронизация исполнения во все остальные цепочки
|
||
```
|
||
|
||
### **4. МУЛЬТИ-ЧЕЙН СИНХРОНИЗАЦИЯ:**
|
||
|
||
#### **Передача токенов:**
|
||
```
|
||
Партнер A передает 500 токенов Партнеру B:
|
||
├── Ethereum: A → B (500 токенов)
|
||
├── Polygon: A → B (500 токенов)
|
||
├── BSC: A → B (500 токенов)
|
||
└── Arbitrum: A → B (500 токенов)
|
||
|
||
Синхронизация происходит во всех цепочках одновременно
|
||
```
|
||
|
||
#### **Создание и исполнение предложений:**
|
||
```
|
||
Пример: "Передать 100 токенов от A к C"
|
||
1. Создание в Ethereum
|
||
2. Выбор Polygon для кворума
|
||
3. Сбор подписей в Polygon
|
||
4. Кворум: 60% от 3000 = 1800 токенов
|
||
5. При достижении кворума:
|
||
├── Исполнение в Polygon: A → C (100 токенов)
|
||
├── Синхронизация в Ethereum: A → C (100 токенов)
|
||
├── Синхронизация в BSC: A → C (100 токенов)
|
||
└── Синхронизация в Arbitrum: A → C (100 токенов)
|
||
```
|
||
|
||
### **5. МОДУЛЬНАЯ АРХИТЕКТУРА:**
|
||
|
||
#### **Основной контракт DLE.sol:**
|
||
```
|
||
- ERC-20 токены
|
||
- Система голосования
|
||
- Мультичейн синхронизация
|
||
- Управление модулями
|
||
- DLEInfo (юридическая информация)
|
||
```
|
||
|
||
#### **Модули (отдельные контракты):**
|
||
```
|
||
- TreasuryModule.sol (казначейство)
|
||
- HierarchicalVotingModule.sol (иерархическое голосование)
|
||
- CommunicationModule.sol (коммуникации)
|
||
- CustomModule.sol (пользовательские модули)
|
||
```
|
||
|
||
### **6. ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:**
|
||
|
||
#### **Передача токенов:**
|
||
```
|
||
1. Создание предложения: "A → C (100 токенов)"
|
||
2. Выбор цепочки для кворума: Polygon
|
||
3. Сбор подписей в Polygon
|
||
4. При кворуме: исполнение + синхронизация во все цепочки
|
||
```
|
||
|
||
#### **Удаление таблицы в приложении:**
|
||
```
|
||
1. Создание предложения: "Удалить таблицу пользователей"
|
||
2. Выбор цепочки: Ethereum
|
||
3. Сбор подписей в Ethereum
|
||
4. При кворуме: информация добавляется в блокчейн
|
||
5. Синхронизация во все цепочки
|
||
6. Результат: таблица удаляется из приложения
|
||
```
|
||
|
||
### **7. КЛЮЧЕВЫЕ ПРИНЦИПЫ:**
|
||
|
||
#### **Безопасность:**
|
||
```
|
||
- Только токен-холдеры управляют
|
||
- Проверка баланса при каждой операции
|
||
- Кворум голосов - все решения через коллективное голосование
|
||
- Синхронизация между цепочками
|
||
```
|
||
|
||
#### **Масштабируемость:**
|
||
```
|
||
- Модульная архитектура
|
||
- Добавление новых функций через модули
|
||
- Поддержка новых цепочек
|
||
- Иерархическое голосование
|
||
```
|
||
|
||
#### **Универсальность:**
|
||
```
|
||
- Один адрес во всех цепочках
|
||
- Любая цепочка для создания предложений
|
||
- Единый интерфейс управления
|
||
- Совместимость с существующими стандартами
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 ОСНОВНАЯ КОНЦЕПЦИЯ
|
||
|
||
### Один смарт-контракт с модулями
|
||
```
|
||
DLE.sol (Основной контракт) + Модули (добавляемые через голосование)
|
||
```
|
||
|
||
### Ключевые принципы:
|
||
1. **Один основной контракт** - управление токенами, голосованием, мультиподписью
|
||
2. **Модули** - специализированные функции (казначейство, иерархическое голосование, коммуникации)
|
||
3. **Только токен-холдеры** - никаких админских ролей
|
||
4. **Кворум голосов** - все решения через коллективное голосование
|
||
5. **Проверка баланса** - при каждой операции
|
||
|
||
---
|
||
|
||
## 🏗️ АРХИТЕКТУРА СИСТЕМЫ
|
||
|
||
### Основной контракт DLE.sol
|
||
```
|
||
DLE.sol
|
||
├── ERC-20 токены (голосующая сила)
|
||
├── Настраиваемый кворум (% от общего количества токенов)
|
||
├── Система голосования (проверка баланса токенов)
|
||
├── Выбор цепочки для кворума (governanceChainId)
|
||
├── Синхронизация голосов между цепочками
|
||
├── Поддержка множественных цепочек
|
||
├── Голосование токен‑холдеров
|
||
├── Мультичейн синхронизация
|
||
└── Система модулей (добавление/управление)
|
||
```
|
||
|
||
### Модули (отдельные контракты)
|
||
```
|
||
Модули
|
||
├── TreasuryModule.sol (Казначейство)
|
||
├── HierarchicalVotingModule.sol (Иерархическое голосование)
|
||
├── CommunicationModule.sol (Сообщения/звонки)
|
||
├── ExternalDLEModule.sol (Меж-DLE взаимодействие)
|
||
└── CustomModule.sol (Пользовательские модули)
|
||
```
|
||
|
||
---
|
||
|
||
## 📋 ФУНКЦИОНАЛЬНЫЕ ТРЕБОВАНИЯ
|
||
|
||
### 1. Основной контракт DLE.sol ✅
|
||
- **ERC-20 токены** - голосующая сила = количество токенов
|
||
- **Настраиваемый кворум** - процент от общего количества токенов
|
||
- **Система голосования** - только токен-холдеры участвуют
|
||
- **Выбор цепочки для кворума** - токен-холдер может выбрать любую поддерживаемую цепочку
|
||
- **Синхронизация голосов** - после голосования результаты синхронизируются между цепочками
|
||
- **Поддержка множественных цепочек** - Ethereum, Polygon, BSC и др.
|
||
- **Голосование** - через токен‑холдеров с проверкой баланса
|
||
- **Мультичейн синхронизация** - одинаковый адрес во всех цепочках
|
||
- **Управление модулями** - добавление/удаление через голосование
|
||
|
||
### 2. TreasuryModule.sol ✅
|
||
- **Внесение токенов** - в казну через голосование
|
||
- **Вывод токенов** - из казны через голосование
|
||
- **Распределение дивидендов** - через голосование
|
||
- **Бюджетирование** - через предложения
|
||
|
||
### 3. HierarchicalVotingModule.sol ✅
|
||
- **Владение токенами других DLE** - покупка/продажа токенов
|
||
- **Создание предложений** - для голосования в других DLE
|
||
- **Внутреннее голосование** - кворум внутри DLE для внешнего голосования
|
||
- **Внешнее голосование** - участие в голосованиях других DLE
|
||
|
||
### 4. CommunicationModule.sol ✅
|
||
- **Прием сообщений** - от токен-холдеров
|
||
- **Прием звонков** - аудио/видео коммуникации
|
||
- **История коммуникаций** - хранение и синхронизация
|
||
- **Кворум для действий** - голосование за коммуникационные операции
|
||
|
||
### 5. ExternalDLEModule.sol ✅
|
||
- **Меж-DLE взаимодействие** - управление DLE B через приложение DLE A
|
||
- **Встраивание интерфейсов** - безопасное управление
|
||
- **Проверка прав** - через голосование токен‑холдеров
|
||
- **Аудит действий** - отслеживание операций
|
||
|
||
### 6. Мульти-чейн архитектура ✅
|
||
- **CREATE2 деплой** - одинаковый адрес во всех цепочках
|
||
- **Синхронизация состояния** - токены, предложения, голосования
|
||
- **Создание предложений** - в любой цепочке
|
||
- **Голосование** - через токен‑холдеров с проверкой баланса
|
||
|
||
---
|
||
|
||
## 🔒 БЕЗОПАСНОСТЬ
|
||
|
||
### Основные принципы безопасности:
|
||
1. **Только токен-холдеры** - никаких админских ролей
|
||
2. **Проверка баланса** - при каждой операции
|
||
3. **Кворум голосов** - все решения коллективные
|
||
4. **Простая логика** - минимум уязвимостей
|
||
|
||
### Защита от атак:
|
||
|
||
#### **1. Защита от Double-Spending**
|
||
```solidity
|
||
function signOperation(bytes32 _operationHash) external {
|
||
require(!hasSigned[_operationHash][msg.sender], "Already signed");
|
||
require(balanceOf(msg.sender) > 0, "No tokens to sign");
|
||
|
||
hasSigned[_operationHash][msg.sender] = true;
|
||
signatures[_operationHash] += balanceOf(msg.sender);
|
||
}
|
||
```
|
||
|
||
#### **2. Защита от Reentrancy**
|
||
```solidity
|
||
mapping(address => bool) private _locked;
|
||
|
||
modifier nonReentrant() {
|
||
require(!_locked[msg.sender], "Reentrant call");
|
||
_locked[msg.sender] = true;
|
||
_;
|
||
_locked[msg.sender] = false;
|
||
}
|
||
```
|
||
|
||
#### **3. Защита от Манипуляций**
|
||
```solidity
|
||
mapping(uint256 => uint256) public proposalSnapshots;
|
||
|
||
function createProposal(string memory _description) external returns (uint256) {
|
||
require(balanceOf(msg.sender) > 0, "Must hold tokens");
|
||
|
||
uint256 proposalId = proposalCount++;
|
||
proposalSnapshots[proposalId] = block.number;
|
||
|
||
return proposalId;
|
||
}
|
||
|
||
function vote(uint256 _proposalId, bool _support) external {
|
||
uint256 votingPower = balanceOfAt(msg.sender, proposalSnapshots[_proposalId]);
|
||
require(votingPower > 0, "No voting power");
|
||
|
||
// Голосование
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ
|
||
|
||
### Основной контракт DLE.sol
|
||
```solidity
|
||
contract DLE is ERC20, ReentrancyGuard {
|
||
// Настройки
|
||
uint256 public quorumPercentage;
|
||
mapping(address => bool) public activeModules;
|
||
|
||
// Мульти-чейн
|
||
mapping(uint256 => bool) public supportedChains;
|
||
mapping(uint256 => uint256) public chainBalances;
|
||
|
||
// Предложения и голосования
|
||
mapping(uint256 => Proposal) public proposals;
|
||
mapping(uint256 => mapping(address => bool)) public hasVoted;
|
||
|
||
// Модули
|
||
mapping(bytes32 => address) public modules;
|
||
|
||
constructor(
|
||
string memory _name,
|
||
string memory _symbol,
|
||
uint256 _initialSupply,
|
||
uint256 _quorumPercentage
|
||
) ERC20(_name, _symbol) {
|
||
quorumPercentage = _quorumPercentage;
|
||
_mint(msg.sender, _initialSupply);
|
||
}
|
||
|
||
// Создание предложения
|
||
function createProposal(string memory _description, uint256 _duration) external returns (uint256) {
|
||
require(balanceOf(msg.sender) > 0, "Must hold tokens");
|
||
|
||
uint256 proposalId = proposalCount++;
|
||
proposals[proposalId] = Proposal({
|
||
id: proposalId,
|
||
description: _description,
|
||
forVotes: 0,
|
||
againstVotes: 0,
|
||
executed: false,
|
||
deadline: block.timestamp + _duration
|
||
});
|
||
|
||
return proposalId;
|
||
}
|
||
|
||
// Голосование
|
||
function vote(uint256 _proposalId, bool _support) external {
|
||
Proposal storage proposal = proposals[_proposalId];
|
||
require(block.timestamp < proposal.deadline, "Voting ended");
|
||
require(!proposal.executed, "Already executed");
|
||
require(!hasVoted[_proposalId][msg.sender], "Already voted");
|
||
|
||
uint256 votingPower = balanceOf(msg.sender);
|
||
require(votingPower > 0, "No tokens to vote");
|
||
|
||
hasVoted[_proposalId][msg.sender] = true;
|
||
|
||
if (_support) {
|
||
proposal.forVotes += votingPower;
|
||
} else {
|
||
proposal.againstVotes += votingPower;
|
||
}
|
||
}
|
||
|
||
// Добавление модуля
|
||
function addModule(bytes32 _moduleId, address _moduleAddress) external {
|
||
require(checkProposalResult(getLastProposalId()).passed, "Proposal not passed");
|
||
|
||
modules[_moduleId] = _moduleAddress;
|
||
activeModules[_moduleAddress] = true;
|
||
|
||
emit ModuleAdded(_moduleId, _moduleAddress);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Модуль казначейства TreasuryModule.sol
|
||
```solidity
|
||
contract TreasuryModule {
|
||
DLE public dle;
|
||
uint256 public treasuryBalance;
|
||
|
||
constructor(address _dle) {
|
||
dle = DLE(_dle);
|
||
}
|
||
|
||
function depositToTreasury(uint256 _amount) external {
|
||
require(dle.balanceOf(msg.sender) >= _amount, "Insufficient balance");
|
||
require(dle.transferFrom(msg.sender, address(this), _amount), "Transfer failed");
|
||
|
||
treasuryBalance += _amount;
|
||
emit TreasuryDeposit(msg.sender, _amount);
|
||
}
|
||
|
||
function withdrawFromTreasury(address _recipient, uint256 _amount) external {
|
||
require(dle.checkProposalResult(getTreasuryProposalId()).passed, "Proposal not passed");
|
||
require(_amount <= treasuryBalance, "Insufficient treasury");
|
||
|
||
treasuryBalance -= _amount;
|
||
require(dle.transfer(_recipient, _amount), "Transfer failed");
|
||
|
||
emit TreasuryWithdrawal(_recipient, _amount);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Модуль иерархического голосования HierarchicalVotingModule.sol
|
||
```solidity
|
||
contract HierarchicalVotingModule {
|
||
DLE public dle;
|
||
mapping(address => uint256) public externalDLEBalances;
|
||
mapping(uint256 => ExternalVotingProposal) public externalVotingProposals;
|
||
|
||
struct ExternalVotingProposal {
|
||
address targetDLE;
|
||
uint256 targetProposalId;
|
||
bool support;
|
||
string reason;
|
||
bool executed;
|
||
uint256 internalProposalId;
|
||
}
|
||
|
||
constructor(address _dle) {
|
||
dle = DLE(_dle);
|
||
}
|
||
|
||
function buyTokensFromOtherDLE(address _otherDLE, uint256 _amount) external {
|
||
require(dle.balanceOf(msg.sender) > 0, "Must hold DLE tokens");
|
||
require(_amount > 0, "Amount must be positive");
|
||
|
||
require(dle.transferFrom(msg.sender, address(this), _amount), "Transfer failed");
|
||
externalDLEBalances[_otherDLE] += _amount;
|
||
|
||
emit ExternalDLEInvestment(_otherDLE, _amount);
|
||
}
|
||
|
||
function createExternalVotingProposal(
|
||
address _targetDLE,
|
||
uint256 _targetProposalId,
|
||
bool _support,
|
||
string memory _reason
|
||
) external returns (uint256) {
|
||
require(dle.balanceOf(msg.sender) > 0, "Must hold DLE tokens");
|
||
require(externalDLEBalances[_targetDLE] > 0, "No tokens in target DLE");
|
||
|
||
string memory description = string(abi.encodePacked(
|
||
"Vote in DLE ", _targetDLE, " on proposal ", _targetProposalId.toString()
|
||
));
|
||
|
||
uint256 internalProposalId = dle.createProposal(description, 7 days);
|
||
|
||
uint256 proposalId = externalProposalCount++;
|
||
externalVotingProposals[proposalId] = ExternalVotingProposal({
|
||
targetDLE: _targetDLE,
|
||
targetProposalId: _targetProposalId,
|
||
support: _support,
|
||
reason: _reason,
|
||
executed: false,
|
||
internalProposalId: internalProposalId
|
||
});
|
||
|
||
return proposalId;
|
||
}
|
||
|
||
function executeExternalVote(uint256 _proposalId) external {
|
||
ExternalVotingProposal storage proposal = externalVotingProposals[_proposalId];
|
||
require(!proposal.executed, "Already executed");
|
||
|
||
(bool passed, bool quorumReached) = dle.checkProposalResult(proposal.internalProposalId);
|
||
require(passed && quorumReached, "Internal proposal not passed");
|
||
|
||
uint256 votingPower = externalDLEBalances[proposal.targetDLE];
|
||
|
||
emit ExternalDLEVote(proposal.targetDLE, proposal.targetProposalId, proposal.support, votingPower);
|
||
|
||
proposal.executed = true;
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🌐 МУЛЬТИ-ЧЕЙН АРХИТЕКТУРА
|
||
|
||
### Мульти-чейн функциональность
|
||
```solidity
|
||
// Создание предложения с выбором цепочки для кворума
|
||
function createProposal(
|
||
string memory _description,
|
||
uint256 _duration,
|
||
uint256 _governanceChainId
|
||
) external returns (uint256);
|
||
|
||
// Исполнение в целевых сетях по EIP-712 подписям (без мостов)
|
||
function executeProposalBySignatures(
|
||
uint256 proposalId,
|
||
bytes[] calldata signatures
|
||
) external;
|
||
|
||
// Проверка поддерживаемых цепочек
|
||
function isChainSupported(uint256 _chainId) external view returns (bool);
|
||
```
|
||
|
||
### Синхронизация между цепочками
|
||
- Результаты голосования фиксируются снапшотами ERC20Votes в governance‑сети.
|
||
- Целевые сети принимают исполнение при верификации EIP‑712 подписей холдеров и кворума на зафиксированном timepoint.
|
||
|
||
---
|
||
|
||
## ⚠️ ПРОБЛЕМЫ ДОСТУПНОСТИ ЦЕПОЧЕК
|
||
|
||
### **Сценарий: Из 4 цепочек доступны только 2**
|
||
|
||
#### **1. Проблема при деплое:**
|
||
```
|
||
Планируемый деплой: Ethereum, Polygon, BSC, Arbitrum
|
||
Доступные цепочки: Ethereum, Polygon
|
||
Недоступные: BSC, Arbitrum (ошибка подключения/интернет)
|
||
```
|
||
|
||
#### **2. Проблема при синхронизации:**
|
||
```
|
||
Исполнение в Ethereum → Синхронизация в остальные цепочки
|
||
✅ Polygon: синхронизация успешна
|
||
❌ BSC: ошибка подключения
|
||
❌ Arbitrum: нет интернета
|
||
```
|
||
|
||
### **ПРОСТОЕ И БЕЗОПАСНОЕ РЕШЕНИЕ:**
|
||
|
||
#### **Принцип: 100% или ничего**
|
||
```
|
||
Перед любым действием:
|
||
1. ✅ Проверить все подключения
|
||
2. ✅ Убедиться в доступности всех цепочек
|
||
3. ✅ Выполнить операцию на 100%
|
||
4. ❌ При любом сбое - отменить всё с указанием причины
|
||
```
|
||
|
||
#### **1. Проверка подключений перед деплоем**
|
||
```solidity
|
||
contract DLE is ERC20, ReentrancyGuard {
|
||
// Статус проверки цепочек
|
||
mapping(uint256 => bool) public chainConnectionStatus;
|
||
|
||
// События
|
||
event PreDeployCheckStarted(uint256[] chainIds);
|
||
event PreDeployCheckCompleted(bool allChainsAvailable, string[] unavailableChains);
|
||
event DeployCancelled(string reason);
|
||
|
||
/**
|
||
* @dev Проверить подключения перед деплоем
|
||
*/
|
||
function checkAllConnections(uint256[] memory _chainIds) external returns (bool) {
|
||
require(balanceOf(msg.sender) > 0, "Must hold tokens");
|
||
|
||
emit PreDeployCheckStarted(_chainIds);
|
||
|
||
bool allAvailable = true;
|
||
string[] memory unavailableChains = new string[](_chainIds.length);
|
||
uint256 unavailableCount = 0;
|
||
|
||
for (uint256 i = 0; i < _chainIds.length; i++) {
|
||
bool isAvailable = checkChainConnection(_chainIds[i]);
|
||
chainConnectionStatus[_chainIds[i]] = isAvailable;
|
||
|
||
if (!isAvailable) {
|
||
allAvailable = false;
|
||
unavailableChains[unavailableCount] = getChainName(_chainIds[i]);
|
||
unavailableCount++;
|
||
}
|
||
}
|
||
|
||
emit PreDeployCheckCompleted(allAvailable, unavailableChains);
|
||
|
||
if (!allAvailable) {
|
||
string memory reason = string(abi.encodePacked(
|
||
"Deploy cancelled: Chains unavailable - ",
|
||
joinStrings(unavailableChains, unavailableCount)
|
||
));
|
||
emit DeployCancelled(reason);
|
||
}
|
||
|
||
return allAvailable;
|
||
}
|
||
|
||
/**
|
||
* @dev Проверить подключение к конкретной цепочке
|
||
*/
|
||
function checkChainConnection(uint256 _chainId) internal view returns (bool) {
|
||
// Здесь должна быть реальная проверка подключения
|
||
// Для примера используем простую проверку
|
||
return _chainId > 0 && _chainId <= 999999;
|
||
}
|
||
|
||
/**
|
||
* @dev Получить название цепочки
|
||
*/
|
||
function getChainName(uint256 _chainId) internal pure returns (string memory) {
|
||
if (_chainId == 1) return "Ethereum";
|
||
if (_chainId == 137) return "Polygon";
|
||
if (_chainId == 56) return "BSC";
|
||
if (_chainId == 42161) return "Arbitrum";
|
||
return "Unknown";
|
||
}
|
||
}
|
||
```
|
||
|
||
#### **2. Проверка перед синхронизацией**
|
||
```solidity
|
||
contract DLE is ERC20, ReentrancyGuard {
|
||
/**
|
||
* @dev Проверить все цепочки перед синхронизацией
|
||
*/
|
||
function checkSyncReadiness(uint256 _proposalId) external returns (bool) {
|
||
require(balanceOf(msg.sender) > 0, "Must hold tokens");
|
||
|
||
Proposal storage proposal = proposals[_proposalId];
|
||
require(proposal.id == _proposalId, "Proposal does not exist");
|
||
|
||
// Проверяем все поддерживаемые цепочки
|
||
bool allChainsReady = true;
|
||
string[] memory unavailableChains = new string[](supportedChainIds.length);
|
||
uint256 unavailableCount = 0;
|
||
|
||
for (uint256 i = 0; i < supportedChainIds.length; i++) {
|
||
uint256 chainId = supportedChainIds[i];
|
||
bool isReady = checkChainConnection(chainId);
|
||
|
||
if (!isReady) {
|
||
allChainsReady = false;
|
||
unavailableChains[unavailableCount] = getChainName(chainId);
|
||
unavailableCount++;
|
||
}
|
||
}
|
||
|
||
if (!allChainsReady) {
|
||
string memory reason = string(abi.encodePacked(
|
||
"Sync cancelled: Chains unavailable - ",
|
||
joinStrings(unavailableChains, unavailableCount)
|
||
));
|
||
emit SyncCancelled(_proposalId, reason);
|
||
}
|
||
|
||
return allChainsReady;
|
||
}
|
||
|
||
/**
|
||
* @dev Синхронизация только при 100% готовности
|
||
*/
|
||
function syncToAllChains(uint256 _proposalId) external {
|
||
require(checkSyncReadiness(_proposalId), "Not all chains ready");
|
||
|
||
// Выполняем синхронизацию во все цепочки
|
||
for (uint256 i = 0; i < supportedChainIds.length; i++) {
|
||
uint256 chainId = supportedChainIds[i];
|
||
syncToChain(_proposalId, chainId);
|
||
}
|
||
|
||
emit SyncCompleted(_proposalId, supportedChainIds);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### **3. Проверка перед голосованием**
|
||
```solidity
|
||
contract DLE is ERC20, ReentrancyGuard {
|
||
/**
|
||
* @dev Проверить цепочку перед голосованием
|
||
*/
|
||
function checkVotingChain(uint256 _chainId) external returns (bool) {
|
||
require(balanceOf(msg.sender) > 0, "Must hold tokens");
|
||
|
||
bool isAvailable = checkChainConnection(_chainId);
|
||
|
||
if (!isAvailable) {
|
||
string memory reason = string(abi.encodePacked(
|
||
"Voting cancelled: Chain ",
|
||
getChainName(_chainId),
|
||
" unavailable"
|
||
));
|
||
emit VotingCancelled(reason);
|
||
}
|
||
|
||
return isAvailable;
|
||
}
|
||
|
||
/**
|
||
* @dev Создать предложение только при доступности цепочки
|
||
*/
|
||
function createProposalWithChainCheck(
|
||
string memory _description,
|
||
uint256 _duration,
|
||
uint256 _votingChainId
|
||
) external returns (uint256) {
|
||
require(checkVotingChain(_votingChainId), "Voting chain not available");
|
||
|
||
return createProposal(_description, _duration, _votingChainId);
|
||
}
|
||
}
|
||
```
|
||
|
||
### **СТРАТЕГИИ ОБРАБОТКИ:**
|
||
|
||
#### **1. При деплое (проверка всех цепочек):**
|
||
```
|
||
Планируемый деплой: Ethereum, Polygon, BSC, Arbitrum
|
||
|
||
Проверка:
|
||
✅ Ethereum: доступен
|
||
✅ Polygon: доступен
|
||
❌ BSC: недоступен
|
||
❌ Arbitrum: недоступен
|
||
|
||
Результат:
|
||
❌ Деплой ОТМЕНЕН
|
||
📋 Причина: "BSC, Arbitrum недоступны"
|
||
🔔 Уведомление токен-холдеров
|
||
```
|
||
|
||
#### **2. При синхронизации (проверка всех цепочек):**
|
||
```
|
||
Исполнение в Ethereum → Синхронизация
|
||
|
||
Проверка:
|
||
✅ Ethereum: доступен
|
||
✅ Polygon: доступен
|
||
❌ BSC: недоступен
|
||
❌ Arbitrum: недоступен
|
||
|
||
Результат:
|
||
❌ Синхронизация ОТМЕНЕНА
|
||
📋 Причина: "BSC, Arbitrum недоступны"
|
||
🔔 Уведомление токен-холдеров
|
||
```
|
||
|
||
#### **3. При голосовании (проверка выбранной цепочки):**
|
||
```
|
||
Планируемое голосование: Polygon
|
||
|
||
Проверка:
|
||
❌ Polygon: недоступен
|
||
|
||
Результат:
|
||
❌ Голосование ОТМЕНЕНО
|
||
📋 Причина: "Polygon недоступен"
|
||
🔔 Уведомление токен-холдеров
|
||
```
|
||
|
||
### **ПРИМЕРЫ СЦЕНАРИЕВ:**
|
||
|
||
#### **Сценарий 1: Деплой с проблемами**
|
||
```
|
||
Планируемый деплой: 4 цепочки
|
||
|
||
Проверка подключений:
|
||
✅ Ethereum: доступен
|
||
✅ Polygon: доступен
|
||
❌ BSC: ошибка подключения
|
||
❌ Arbitrum: нет интернета
|
||
|
||
Действия:
|
||
1. ❌ Деплой ОТМЕНЕН
|
||
2. 📋 Причина: "BSC, Arbitrum недоступны"
|
||
3. 🔔 Уведомление токен-холдеров
|
||
4. ⏰ Ожидание восстановления подключений
|
||
5. 🔄 Повторная проверка при восстановлении
|
||
```
|
||
|
||
#### **Сценарий 2: Синхронизация с проблемами**
|
||
```
|
||
Исполнение в Ethereum → Синхронизация
|
||
|
||
Проверка всех цепочек:
|
||
✅ Ethereum: доступен
|
||
✅ Polygon: доступен
|
||
❌ BSC: ошибка подключения
|
||
❌ Arbitrum: нет интернета
|
||
|
||
Действия:
|
||
1. ❌ Синхронизация ОТМЕНЕНА
|
||
2. 📋 Причина: "BSC, Arbitrum недоступны"
|
||
3. 🔔 Уведомление токен-холдеров
|
||
4. ⏰ Ожидание восстановления подключений
|
||
5. 🔄 Повторная проверка при восстановлении
|
||
```
|
||
|
||
#### **Сценарий 3: Голосование с проблемами**
|
||
```
|
||
Планируемое голосование: Polygon
|
||
|
||
Проверка Polygon:
|
||
❌ Polygon: недоступен
|
||
|
||
Действия:
|
||
1. ❌ Голосование ОТМЕНЕНО
|
||
2. 📋 Причина: "Polygon недоступен"
|
||
3. 🔔 Уведомление токен-холдеров
|
||
4. ⏰ Ожидание восстановления подключения
|
||
5. 🔄 Повторная проверка при восстановлении
|
||
```
|
||
|
||
### **ПРЕИМУЩЕСТВА ПРОСТОГО РЕШЕНИЯ:**
|
||
|
||
#### **✅ Безопасность:**
|
||
- Никаких частичных операций
|
||
- Никаких рассинхронизаций
|
||
- Четкие причины отмены
|
||
|
||
#### **✅ Простота:**
|
||
- Понятная логика
|
||
- Минимум кода
|
||
- Легко отлаживать
|
||
|
||
#### **✅ Надежность:**
|
||
- 100% или ничего
|
||
- Предсказуемое поведение
|
||
- Нет скрытых состояний
|
||
|
||
#### **✅ Прозрачность:**
|
||
- Четкие причины отмены
|
||
- Уведомления токен-холдеров
|
||
- Понятная логика
|
||
|
||
### **КЛЮЧЕВЫЕ ПРИНЦИПЫ:**
|
||
|
||
#### **1. Проверка перед действием:**
|
||
```
|
||
Любое действие = Проверка всех подключений → Выполнение или Отмена
|
||
```
|
||
|
||
#### **2. 100% или ничего:**
|
||
```
|
||
Все цепочки доступны → Выполнить
|
||
Любая цепочка недоступна → Отменить с причиной
|
||
```
|
||
|
||
#### **3. Четкие причины:**
|
||
```
|
||
Отмена = Конкретная причина + Уведомление токен-холдеров
|
||
```
|
||
|
||
#### **4. Простота восстановления:**
|
||
```
|
||
Проблема решена → Повторная проверка → Выполнение
|
||
```
|
||
|
||
**Теперь система DLE работает по принципу "100% или ничего" - просто, безопасно и надежно!**
|
||
|
||
---
|
||
|
||
## 📊 ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ
|
||
|
||
### Пример 1: Деплой в 4 цепочках
|
||
```
|
||
1. Пользователь выбирает 4 цепочки: Ethereum, Polygon, BSC, Arbitrum
|
||
2. Деплой DLE в каждой цепочке с одинаковым адресом
|
||
3. Партнеры получают по 1000 токенов в каждой цепочке:
|
||
- Партнер A: 1000 токенов (в 4 цепочках)
|
||
- Партнер B: 1000 токенов (в 4 цепочках)
|
||
- Партнер C: 1000 токенов (в 4 цепочках)
|
||
4. Передача токенов синхронизируется между всеми цепочками
|
||
```
|
||
|
||
### Пример 2: Создание предложения и сбор подписей
|
||
```
|
||
1. Партнер A создает предложение "Передать 100 токенов от A к C"
|
||
2. Выбирает одну цепочку (например, Polygon) для сбора подписей
|
||
3. Сбор подписей происходит только в выбранной цепочке
|
||
4. Кворум: 60% от 3000 = 1800 токенов
|
||
5. При достижении кворума - исполнение в Polygon
|
||
6. Синхронизация исполнения во все остальные цепочки
|
||
```
|
||
|
||
### Пример 3: Исполнение и синхронизация
|
||
```
|
||
1. Кворум достигнут в Polygon (1800+ токенов)
|
||
2. Исполнение в Polygon: A → C (100 токенов)
|
||
3. Синхронизация в Ethereum: A → C (100 токенов)
|
||
4. Синхронизация в BSC: A → C (100 токенов)
|
||
5. Синхронизация в Arbitrum: A → C (100 токенов)
|
||
6. Результат: токены переданы во всех 4 цепочках
|
||
```
|
||
|
||
### Пример 4: Удаление таблицы в приложении
|
||
```
|
||
1. Партнер A создает предложение "Удалить таблицу пользователей"
|
||
2. Выбирает Ethereum для сбора подписей
|
||
3. Кворум достигнут в Ethereum
|
||
4. Исполнение в Ethereum: информация добавляется в блокчейн
|
||
5. Синхронизация во все цепочки: информация добавляется везде
|
||
6. Результат: таблица удаляется из приложения
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 ПРЕИМУЩЕСТВА АРХИТЕКТУРЫ
|
||
|
||
### ✅ Простота
|
||
- Один основной контракт с модулями
|
||
- Только токен-холдеры участвуют в управлении
|
||
- Проверка баланса при каждой операции
|
||
- Настраиваемый кворум для всех решений
|
||
|
||
### ✅ Безопасность
|
||
- Никаких админских ролей
|
||
- Простая логика коллективного голосования
|
||
- Защита от основных атак
|
||
- Прозрачность всех операций
|
||
|
||
### ✅ Масштабируемость
|
||
- Модульная архитектура
|
||
- Добавление новых функций через модули
|
||
- Мульти-чейн синхронизация
|
||
- Иерархическое голосование
|
||
|
||
### ✅ Универсальность
|
||
- Один адрес во всех цепочках
|
||
- Любая цепочка для создания предложений
|
||
- Единый интерфейс управления
|
||
- Совместимость с существующими стандартами
|
||
|
||
---
|
||
|
||
## 📈 ЗАКЛЮЧЕНИЕ
|
||
|
||
**DLE - это единый смарт-контракт с модульной архитектурой, который:**
|
||
|
||
1. **Управляется только токен‑холдерами** через кворум голосов
|
||
2. **Проверяет баланс токенов** при каждой операции
|
||
3. **Использует модули** для специализированных функций
|
||
4. **Синхронизируется между цепочками** с одинаковым адресом
|
||
5. **Поддерживает иерархическое голосование** через отдельный модуль
|
||
|
||
**Ключевые принципы:**
|
||
- Простота и безопасность
|
||
- Коллективное управление
|
||
- Модульная архитектура
|
||
- Мульти-чейн синхронизация
|
||
|
||
**Результат:** Безопасная, масштабируемая и универсальная система DLE! 🚀 |