ManaGovernance.t.sol
Обзор файла
Файл ManaGovernance.t.sol содержит тестовый контракт ManaGovernanceTest, написанный на языке Solidity с использованием фреймворка Forge (библиотека forge-std). Этот файл предназначен для комплексного тестирования контракта управления децентрализованным голосованием и стейкингом токенов MANA в системе, реализованной в контракте ManaGovernance.sol.
В тестах проверяются ключевые сценарии использования системы управления:
Стейкинг и вывод токенов MANA
Создание, голосование, отмена, очередь и исполнение предложений
Проверка различных состояний предложений
Управление параметрами голосования и конфигурацией управления
Особенности работы с экстренными предложениями и паузой контракта
Файл тесно интегрирован с контрактами ManaToken.sol, GameManager.sol и моком SettlementMock.sol, что позволяет эмулировать взаимодействие с токеном, экономической логикой и игровым окружением.
Класс ManaGovernanceTest
Основной класс данного файла — это тестовый контракт ManaGovernanceTest, который наследует функциональность из Test (библиотека Forge).
Свойства класса
Свойство | Тип | Описание |
|---|---|---|
governance | ManaGovernance | Тестируемый контракт управления голосованием |
manaToken | ManaToken | Контракт токена MANA |
gameManager | GameManager | Контракт управления экономикой и игровыми параметрами |
settlement | SettlementMock | Мок-контракт для эмуляции игрового окружения |
admin | address | Адрес администратора системы |
staker1 | address | Адрес первого стейкера |
staker2 | address | Адрес второго стейкера |
proposer | address | Адрес пользователя, создающего предложения |
События (Events)
В тестах используются события для проверки корректного эмиттинга событий контрактом ManaGovernance:
ProposalCreatedVoteCastProposalQueuedProposalExecutedProposalCancelledStakeDepositedStakeWithdrawnGovernanceConfigUpdated
Основные методы и их описание
setUp()
Инициализация тестовой среды:
Создаёт аккаунты
admin,staker1,staker2,proposerДеплоит контракты
ManaToken,SettlementMock,GameManager,ManaGovernanceНазначает роли между контрактами для взаимодействия
Распределяет начальные балансы MANA для стейкеров и предложения
Пример использования: вызывается автоматически перед каждым тестом
testStakeTokens()
Проверяет успешное депонирование токенов в качестве стейка:
Утверждает правильное обновление информации о стейкере
Проверяет корректное изменение общего стейка и голосующей силы
testStakeZeroAmount()
Проверяет, что попытка застейкать 0 токенов вызывает ошибку ZeroAmount.
testWithdrawTokens()
Тестирует вывод части застейканных токенов:
Проверяет обновление баланса стейкера и общего стейка
Проверяет корректный эмит событий
StakeWithdrawn
testWithdrawInsufficientStake()
Проверяет, что вывод токенов сверх застейканного количества приводит к ошибке InsufficientStake.
testCreateProposal()
Тест создания предложения с валидным стейком и после минимального периода стейкинга:
Проверяет корректное создание и хранение предложения
Проверяет эмит события
ProposalCreated
testCreateProposalInsufficientStake()
Проверяет ошибку при попытке создать предложение с недостаточным стейком (меньше 1% от общего предложения).
testCreateProposalTooEarly()
Проверяет ошибку при создании предложения до истечения минимального времени стейкинга.
testCastVote()
Тестирует процесс голосования за предложение:
Проверяет обновление голосов за/против/воздержание
Проверяет запись голосующего в реестре голосов
testCastVoteAlreadyVoted()
Проверяет невозможность проголосовать дважды за одно предложение.
testCastVoteInsufficientStake()
Проверяет ошибку при попытке проголосовать без стейка.
testProposalStates()
Проверяет переход состояний предложения:
Активно
Проиграло (нет голосов после окончания периода)
testSuccessfulProposalFlow()
Полный тест успешного создания, голосования, очереди и исполнения предложения с обновлением экономических параметров в GameManager.
testCancelProposal()
Проверяет отмену предложения инициатором.
testCancelProposalUnauthorized()
Проверяет, что отмена предложения недопустима для посторонних адресов.
testEmergencyProposal()
Тестирует создание и исполнение экстренного предложения с сокращённым таймлоком.
testGovernanceParameterUpdate()
Проверяет изменение параметров управления через предложение.
testCanCreateProposal()
Проверяет функцию доступности создания предложения с учётом минимального времени стейкинга.
testUpdateGovernanceConfigAdmin()
Тестирует обновление конфигурации управления администратором с проверкой события.
testUpdateGovernanceConfigInvalidParameters()
Проверяет ошибку при попытке установить некорректные параметры конфигурации.
testPauseUnpause()
Тестирует паузу и разпаузу контракта, а также блокировку операций во время паузы.
Вспомогательные функции
_createTestProposal()— создаёт стандартное предложение для большинства тестов._createGovernanceProposal()— создаёт предложение на изменение параметров управления._voteAndExecuteProposal(proposalId)— голосует и исполняет предложение.
Важные детали реализации
Используется библиотека
forge-stdдля облегчения тестирования и имитации (например,vm.startPrank,vm.warp).Процесс голосования и стейкинга интегрирован с ERC20 токеном MANA.
Система голосования поддерживает разные типы предложений (
EconomicParameters,GovernanceParameters,Emergencyи др.).Время и статусы предложений проверяются с помощью манипуляций времени
vm.warp.Контракт управляет ролями и разрешениями через
grantRole.Проверяются события для валидации корректной работы функций контракта.
Взаимодействие с другими частями системы
ManaToken — стандартный ERC20 токен, используемый для стейкинга и голосования.
GameManager — контракт, управляющий экономическими параметрами игры, которые могут обновляться через предложения.
SettlementMock — мок-контракт для имитации игрового окружения в тестах.
ManaGovernance — основной контракт управления голосованием, который тестируется этим файлом.
Тесты обеспечивают проверку взаимодействия ManaGovernance с токеном и GameManager через создание и исполнение предложений.
Пример использования (сокращённый)
// Стейкинг токенов
manaToken.approve(address(governance), amount);
governance.stake(amount);
// Создание предложения
uint256 proposalId = governance.propose(
ManaGovernance.ProposalType.EconomicParameters,
"Изменение параметров",
abi.encode(newEconomicConfig)
);
// Голосование за предложение
governance.castVote(proposalId, ManaGovernance.VoteType.For, "Поддерживаю");
// Очередь и исполнение
governance.queue(proposalId);
governance.execute(proposalId);
Диаграмма структуры класса ManaGovernanceTest
classDiagram
class ManaGovernanceTest {
+ManaGovernance governance
+ManaToken manaToken
+GameManager gameManager
+SettlementMock settlement
+address admin
+address staker1
+address staker2
+address proposer
+function setUp()
+function testStakeTokens()
+function testStakeZeroAmount()
+function testWithdrawTokens()
+function testWithdrawInsufficientStake()
+function testCreateProposal()
+function testCreateProposalInsufficientStake()
+function testCreateProposalTooEarly()
+function testCastVote()
+function testCastVoteAlreadyVoted()
+function testCastVoteInsufficientStake()
+function testProposalStates()
+function testSuccessfulProposalFlow()
+function testCancelProposal()
+function testCancelProposalUnauthorized()
+function testEmergencyProposal()
+function testGovernanceParameterUpdate()
+function testCanCreateProposal()
+function testUpdateGovernanceConfigAdmin()
+function testUpdateGovernanceConfigInvalidParameters()
+function testPauseUnpause()
+function _createTestProposal()
+function _createGovernanceProposal()
+function _voteAndExecuteProposal(uint256)
+function testFuzzStakeAmount(uint256)
+function testFuzzVotingPower(uint256,uint256)
}
Итог
Файл ManaGovernance.t.sol обеспечивает всестороннее тестирование логики управления децентрализованным голосованием и стейкингом токенов MANA в экосистеме проекта. Он покрывает как позитивные сценарии, так и негативные кейсы (ошибки), гарантируя корректность бизнес-логики и интеграции с другими контрактами. Такой подход повышает надёжность и безопасность системы управления протоколом.