Files
DLE/docs/MODULE_ARCHITECTURE.md
Alex de0f8aecf2 feat: Добавлены формы деплоя модулей DLE с полными настройками
- Создана форма деплоя TreasuryModule с детальными настройками казны
- Создана форма деплоя TimelockModule с настройками временных задержек
- Создана форма деплоя DLEReader с простой конфигурацией
- Добавлены маршруты и индексы для всех модулей
- Исправлены пути импорта BaseLayout
- Добавлены авторские права во все файлы
- Улучшена архитектура деплоя модулей отдельно от основного DLE
2025-09-23 02:57:59 +03:00

5.7 KiB
Raw Blame History

Архитектура модулей DLE

Обзор

DLE использует модульную архитектуру, где каждый модуль может иметь свои правила доступа и функциональность.

Типы модулей

1. Простые модули (Вариант 1)

Модули сами проверяют права доступа токен-холдеров.

contract SimpleModule {
    address public dleContract;
    
    modifier onlyDLEHolders() {
        require(IERC20(dleContract).balanceOf(msg.sender) > 0, "Must hold DLE tokens");
        _;
    }
    
    function someFunction() external onlyDLEHolders {
        // Логика функции
    }
}

2. Сложные модули (Вариант 3)

Модули работают через основной контракт DLE.

contract ComplexModule {
    address public dleContract;
    
    function executeOperation(address caller, bytes calldata operation) external {
        require(msg.sender == dleContract, "Only DLE can call");
        require(IERC20(dleContract).balanceOf(caller) > 0, "Must hold tokens");
        
        // Выполняем операцию
        _executeOperation(caller, operation);
    }
}

Рекомендации по выбору

Используйте Вариант 1 для:

  • Простых операций (чтение данных)
  • Модулей с минимальной логикой
  • Быстрых операций

Используйте Вариант 3 для:

  • Сложных финансовых операций
  • Модулей с критической логикой
  • Операций, требующих аудита

Примеры модулей

TreasuryModule (Казна)

contract TreasuryModule {
    address public dleContract;
    mapping(address => bool) public supportedTokens;
    
    modifier onlyDLEHolders() {
        require(IERC20(dleContract).balanceOf(msg.sender) > 0, "Must hold DLE tokens");
        _;
    }
    
    function depositToken(address token, uint256 amount) external onlyDLEHolders {
        require(supportedTokens[token], "Token not supported");
        IERC20(token).transferFrom(msg.sender, address(this), amount);
    }
    
    function withdrawToken(address token, uint256 amount) external onlyDLEHolders {
        require(supportedTokens[token], "Token not supported");
        IERC20(token).transfer(msg.sender, amount);
    }
}

GovernanceModule (Управление)

contract GovernanceModule {
    address public dleContract;
    
    function executeOperation(address caller, bytes calldata operation) external {
        require(msg.sender == dleContract, "Only DLE can call");
        require(IERC20(dleContract).balanceOf(caller) > 0, "Must hold tokens");
        
        // Выполняем операцию управления
        _executeGovernanceOperation(caller, operation);
    }
}

Безопасность

Общие принципы:

  1. Всегда проверяйте баланс токенов DLE
  2. Валидируйте входные данные в модулях
  3. Используйте ReentrancyGuard для финансовых операций
  4. Логируйте важные операции через события

Аудит модулей:

  • Проверяйте права доступа
  • Тестируйте граничные случаи
  • Валидируйте входные параметры
  • Проверяйте обработку ошибок

Модульная архитектура (обновление для DLE v2)

  • Модули выносятся в отдельные контракты: TreasuryModule, TimelockModule, DeactivationModule, CommunicationModule.
  • Подключение/отключение модулей — строго через предложения DLE (ModuleAdded/ModuleRemoved).
  • Исполнение модульных операций инициируется основным DLE через _executeOperation по безопасному operationCalldata.
  • Денежные переводы из ядра исключены: все токено‑операции внутри TreasuryModule.
  • Таймлок применяется на уровне предложения: timelockHours хранится в Proposal и проверяется при исполнении.
  • Для оффчейн действий ядро эмитит событие OffchainAction, которое подписывает и обрабатывает бекенд/клиент.

Последовательность для казначейской операции:

  1. Создание предложения с типом операции и параметрами, указание governanceChainId, targetChains, timelockHours.
  2. Сбор голосов в выбранной сети (снапшоты ERC20Votes).
  3. По наступлению timelock — executeProposalBySignatures в целевых сетях с проверкой EIP712 подписей и «100% или ничего».
  4. Ядро вызывает TreasuryModule по abi.encodeWithSelector(...).