ManaSettlement.t.sol
Обзор файла
ManaSettlement.t.sol — это тестовый контракт, написанный на Solidity с использованием фреймворка Forge (часть Foundry). Он предназначен для комплексного модульного тестирования смарт-контракта ManaSettlement.sol, который управляет состоянием игроков в игре, связанной с токеном Mana (ManaToken.sol).
Данный файл реализует тесты для проверки:
Инициализации и корректной работы ролей доступа.
Регистрации игроков и управления их игровыми профилями.
Обновления балансов маны и состояний игроков как в одиночном, так и в пакетном режиме.
Добавления достижений игрокам.
Паузы и возобновления работы контракта.
Правильности интерфейсов и констант.
Безопасности и ограничений доступа.
Используемые библиотеки:
forge-std/Test.sol— базовый тестовый функционал Forge.ManaSettlement.sol — тестируемый контракт.
ManaToken.sol — контракт игрового токена Mana.
IAccessControl— интерфейс для управления ролями доступа (OpenZeppelin).
Классы и основные функции
Контракт ManaSettlementTest
Главный тестовый контракт, расширяет Test из Forge для использования встроенных тестовых возможностей.
Переменные
ManaSettlement public manaSettlement — экземпляр тестируемого контракта.
ManaToken public manaToken — тестовый токен Mana.
Адреса для ролей и игроков:
admin,gameManager,pauser,player1,player2,player3.
События (для проверки эмиссии событий в тестах)
PlayerStateUpdated(address player, uint256 newManaBalance, ManaSettlement.PlayerProfile newProfile)BatchPlayerStateUpdated(uint256 batchId, uint256 playersUpdated)ManaBalanceUpdated(address player, uint256 oldBalance, uint256 newBalance)PlayerProfileUpdated(address player, ManaSettlement.PlayerProfile newProfile)
Основные методы
setUp()
Инициализация тестовой среды:
Генерирует адреса для ролей и игроков.
Разворачивает контракты
ManaTokenиManaSettlement.Инициализирует
ManaSettlementс ролямиadminиgameManager.Выдаёт роль PAUSER_ROLE адреса
pauser.
Использование: вызывается автоматически перед каждым тестом.
Тесты конструктора
test_Constructor()— проверка правильного указания адреса токена, начальных значений счетчиков.test_Constructor_ZeroAddress()— проверка ошибки при передаче нулевого адреса токена.
Тесты инициализации ролей
test_InitializeWithGameManager() — проверка присвоения ролей
GAME_MANAGER_ROLE, PAUSER_ROLE и DEFAULT_ADMIN_ROLE.
Тесты регистрации игрока
test_RegisterPlayer()— проверяет успешную регистрацию игрока с корректным созданием профиля.test_RegisterPlayer_AlreadyRegistered() — повторная регистрация не увеличивает счётчик.
test_RegisterPlayer_ZeroAddress() — ошибка при регистрации нулевого адреса.
test_RegisterPlayer_UnauthorizedUser() — ошибка при попытке регистрации от неавторизованного адреса.
Тесты обновления состояния игрока
test_UpdatePlayerState()— обновление баланса маны и профиля игрока с проверкой эмиссии события.test_UpdatePlayerState_ZeroAddress() — ошибка при обновлении состояния нулевого адреса.
test_UpdatePlayerState_InvalidProfile() — ошибка при передаче некорректного профиля (например, уровень 0 с опытом).
test_UpdatePlayerState_UnauthorizedUser() — ошибка при вызове неавторизованным пользователем.
Тесты пакетного обновления состояний
test_BatchUpdatePlayerStates()— обновление состояний нескольких игроков за один вызов с проверкой счётчика батчей и эмиссии события.
Тесты управления балансом маны
test_UpdatePlayerManaBalance()— обновление баланса отдельного игрока с проверкой события.test_UpdatePlayerManaBalance_PlayerNotFound() — ошибка при обновлении баланса незарегистрированного игрока.
Тесты управления достижениями
test_AddPlayerAchievement()— добавление нового достижения игроку.test_AddPlayerAchievement_PlayerNotFound() — ошибка при добавлении достижения незарегистрированному игроку.
Тесты функций просмотра состояния
test_GetPlayerState()— получение полного состояния игрока.test_GetPlayerManaBalances() — получение балансов маны игрока в контракте и на токене.
test_GetMultiplePlayerStates() — получение состояний нескольких игроков.
test_GetTotalStats() — получение общей статистики (число игроков и батчей).
Тесты паузы и возобновления
test_Pause()— успешная постановка контракта на паузу.test_Pause_UnauthorizedUser() — ошибка при попытке паузы неавторизованным пользователем.
test_Unpause() — успешное снятие паузы.
test_UpdatePlayerState_WhenPaused() — запрет обновления состояния при паузе.
Fuzz тесты
testFuzz_UpdatePlayerManaBalance(uint256 balance) — проверка обновления баланса на случайных значениях.
testFuzz_RegisterMultiplePlayers(uint8 numPlayers) — массовая регистрация игроков с проверкой счётчика.
Тесты поддержки интерфейсов и констант
test_SupportsInterface()— проверка поддержки интерфейсаIAccessControl.test_RoleConstants()— проверка констант ролейGAME_MANAGER_ROLEи PAUSER_ROLE.
Важные детали реализации и алгоритмы
Используется механизм ролей (OpenZeppelin
AccessControl) для разграничения прав:GAME_MANAGER_ROLE— для управления состоянием игроков.PAUSER_ROLE — для управления паузой контракта.
DEFAULT_ADMIN_ROLE — администратор с расширенными правами.
Игроки регистрируются с дефолтным профилем: уровень 1, рейтинг 1000, без опыта и достижений.
Обновление состояний и балансов сопровождается эмиссией событий, что облегчает мониторинг в off-chain системах.
Пакетное обновление оптимизирует массовые операции над состояниями игроков.
Валидация профиля игрока исключает неконсистентные данные (например, уровень 0 при наличии опыта).
Пауза контракта блокирует операции изменения состояний, повышая безопасность при необходимости.
Тесты тщательно проверяют не только позитивные сценарии, но и негативные — с ошибками, неправильными входными данными и неавторизованным доступом.
Взаимодействие с другими частями системы
Контракт
ManaSettlementтесно связан сManaToken— внутренний баланс маны вManaSettlementсинхронизируется с балансом токена.Тесты имитируют взаимодействие между этими двумя контрактами, а также с ролями и пользователями.
Роли управления и безопасности обеспечивают интеграцию с системой управления правами (OpenZeppelin AccessControl).
События, эмитируемые
ManaSettlement, позволяют внешним сервисам (например, игровым серверам или аналитическим платформам) отслеживать изменения состояния игроков.
Пример использования (фрагмент из теста регистрации игрока)
function test_RegisterPlayer() public {
assertFalse(manaSettlement.isPlayerRegistered(player1));
vm.prank(gameManager); // Эмуляция вызова от gameManager
manaSettlement.registerPlayer(player1);
assertTrue(manaSettlement.isPlayerRegistered(player1));
assertEq(manaSettlement.totalPlayers(), 1);
ManaSettlement.PlayerProfile memory profile = manaSettlement.getPlayerProfile(player1);
assertEq(profile.level, 1);
assertEq(profile.experience, 0);
assertEq(profile.rating, 1000);
assertEq(profile.lastActionTimestamp, uint48(block.timestamp));
}
Mermaid диаграмма: структура класса ManaSettlementTest
classDiagram
class ManaSettlementTest {
+ManaSettlement manaSettlement
+ManaToken manaToken
+address admin
+address gameManager
+address pauser
+address player1
+address player2
+address player3
+setUp()
+test_Constructor()
+test_RegisterPlayer()
+test_UpdatePlayerState()
+test_BatchUpdatePlayerStates()
+test_UpdatePlayerManaBalance()
+test_AddPlayerAchievement()
+test_GetPlayerState()
+test_Pause()
+testFuzz_UpdatePlayerManaBalance(uint256)
+testFuzz_RegisterMultiplePlayers(uint8)
+test_SupportsInterface()
+test_RoleConstants()
}
Итоги
Файл ManaSettlement.t.sol — это полный набор тестов для контракта ManaSettlement, обеспечивающий надёжность, безопасность и корректность управления состояниями игроков в игровой экосистеме с токеном Mana. Тесты охватывают широкий спектр сценариев, включая авторизацию, обработку ошибок, массовые обновления и интеграцию с токеном, что делает их ключевым элементом в процессе разработки и поддержки смарт-контракта.