Как тестировать экономику мобильной игры и ловить читеров
В F2P-игре экономика — это и есть бизнес: монеты, кристаллы, энергия, лутбоксы, IAP. Поэтому она же — главная мишень. Один дюп-баг с валютой или чит на «бесконечные монеты» — и внутриигровой магазин, на котором держится выручка, теряет смысл: зачем платить, если можно нафармить читом. Тестировать экономику надо не как «работает ли кнопка купить», а как защиту от злоупотреблений. Ниже — атаки, которые QA обязан прогнать сам.
Золотое правило: клиент врёт
Любое значение, пришедшее с устройства, — потенциально подделано. Баланс, «я купил», «я прошёл уровень», «мне начислить награду» — всё это должно проверяться и считаться на сервере, а клиент лишь отображает. Главный тест: перехватываешь запрос (Proxyman/Charles/mitmproxy) и меняешь — шлёшь coins += 1000, level = 99, reward = legendary. Сервер должен отбить (403/ошибка валидации), а не радостно начислить. Если начисляет — экономика дырявая, и никакие клиентские проверки её не спасут.
Дюп-баги и идемпотентность
Классика — задвоение награды/валюты на стыке «действие → сеть → подтверждение»:
- Двойной тап по «Купить» / «Забрать награду» — два запроса. Должна отработать ровно одна операция (идемпотентность по ключу транзакции), а не списать деньги дважды или выдать награду дважды.
- Обрыв сети mid-transaction: заплатил → соединение упало до ответа → ретрай. Не должно ни задвоить покупку, ни «съесть» её без выдачи.
- Откат/восстановление: убил приложение в момент начисления, перезашёл — состояние должно сойтись, без дублей и без потерь.
Тест: гоняешь покупку/награду с искусственными обрывами и дабл-кликами (тротлинг сети, kill приложения) — итог всегда «ровно один раз».
Перевод часов устройства
Всё, что завязано на время, — таймеры «ждать 8ч или заплатить», ежедневные награды, энергия, кулдауны, ограниченные по времени офферы — атакуется переводом системных часов. Тест: крутишь время устройства вперёд (таймер «прошёл», награда «доступна») и назад (повторно забрать дейлик). Правильно — сервер считает время сам; устройство — не источник истины. Проверь и стык: перевёл часы, забрал награду локально, ушёл в оффлайн, вернулся — сервер должен отклонить.
Редактирование сейва
Локальный прогресс в PlayerPrefs, SharedPreferences, plist или файле сейва редактируется за минуту (rooted/jailbroken, или просто редактор). Тест: находишь, где хранится валюта/прогресс, меняешь на «999999» — что произойдёт? Чувствительные значения должны жить на сервере или быть подписаны/зашифрованы так, чтобы правка ломала подпись и откатывалась. Если игра честно поверила локальному файлу — это чит в один клик.
Отрицательный баланс, переполнение, гонки
- Потратить больше, чем есть: купить за 100 монет, имея 50 — должно отбиться, а не уйти в минус.
- Переполнение: зафармить/наградами загнать валюту за
2^31(или сколько там тип) — не должно переполниться в отрицательное. - Race condition: два параллельных списания с одного баланса (два девайса, быстрые тапы) — сумма не должна «раздвоиться». Классика: потратить одни и те же монеты дважды одновременно.
Фейковый IAP-чек
Покупка за реальные деньги проверяется валидацией чека на сервере через App Store Server API / Google Play. Без этого фейковый или переигранный чек = бесплатная покупка. Тест: подсунуть невалидный/чужой/повторный receipt — не должно выдать товар. (Подробнее про IAP — в отдельном разборе покупок.)
Тулы читеров
Игроки используют GameGuardian, редакторы памяти, Lucky Patcher, модифицированные клиенты. Полностью на клиенте это не остановить — поэтому и нужен сервер-авторитет. Что проверить: критичное состояние (валюта, прогресс, результаты матчей) сервер пересчитывает/валидирует; аномалии (нереальный прирост, невозможный счёт) детектятся; клиентские анти-чит и обфускация — это замедление, а не защита.
Чек-лист атак на экономику
- Подмена запроса «+валюта / +уровень / +награда» → сервер отбивает.
- Двойной тап по покупке/награде → ровно одна операция.
- Обрыв сети во время транзакции → без дублей и без потерь.
- Kill приложения в момент начисления → состояние сходится.
- Перевод часов вперёд/назад → таймеры и дейлики считает сервер.
- Правка локального сейва (валюта/прогресс) → откат/не применяется.
- Покупка дороже баланса → отказ, без ухода в минус.
- Переполнение валюты → не уходит в отрицательное.
- Параллельные списания (2 девайса/быстрые тапы) → без раздвоения.
- Невалидный/повторный IAP-чек → товар не выдаётся.
- Критичное состояние валидируется на сервере, не на клиенте.
Коротко — что забрать с собой
- Экономика = деньги, поэтому тестируется как защита от злоупотреблений, а не как «кнопка купить».
- Клиенту не верить — считать и валидировать на сервере; главный тест — подмена запроса.
- Дюп-баги ловятся идемпотентностью: обрывы, дабл-тапы, kill → «ровно один раз».
- Перевод часов и правка сейва — обязательные атаки; время и ценности держит сервер.
- Отрицательный баланс, переполнение, гонки — проверять на границах.
- IAP — только с серверной валидацией чека.
Почитать: OWASP MASVS — Mobile App Security · Apple — App Store Server API (валидация покупок) · Google Play — Billing security