How to Test a Mobile Game's Economy and Catch Cheaters
In an F2P game the economy is the business: coins, gems, energy, loot boxes, IAP. Which makes it the prime target. One currency duplication bug or an “infinite coins” cheat and the in-game store your revenue rests on becomes pointless — why pay if you can farm it with a cheat. You don’t test the economy as “does the buy button work”; you test it as abuse resistance. Below are the attacks QA must run itself.
The golden rule: the client lies
Any value coming from the device is potentially forged. Balance, “I bought it,” “I cleared the level,” “grant me the reward” — all of it must be validated and computed on the server, with the client only displaying. The key test: intercept the request (Proxyman/Charles/mitmproxy) and change it — send coins += 1000, level = 99, reward = legendary. The server must reject it (403/validation error), not happily grant it. If it grants it, the economy is leaky, and no client-side checks will save it.
Duplication bugs and idempotency
The classic is doubling a reward/currency at the “action → network → confirmation” seam:
- Double tap on Buy / Claim reward — two requests. Exactly one operation must go through (idempotency by transaction key), not charge twice or grant the reward twice.
- Network drop mid-transaction: paid → connection dropped before the response → retry. It must neither duplicate the purchase nor “eat” it without delivery.
- Rollback/recovery: kill the app during a grant, relaunch — state must reconcile, no duplicates and no losses.
Test: run purchases/rewards with artificial drops and double-clicks (network throttling, killing the app) — the outcome is always “exactly once.”
Device-clock manipulation
Anything tied to time — “wait 8h or pay” timers, daily rewards, energy, cooldowns, time-limited offers — is attacked by changing the system clock. Test: move the device time forward (timer “elapsed,” reward “available”) and back (claim the daily again). Correct: the server tracks time itself; the device is not the source of truth. Check the seam too: change the clock, claim locally, go offline, come back — the server must reject it.
Save-file editing
Local progress in PlayerPrefs, SharedPreferences, a plist, or a save file is editable in a minute (rooted/jailbroken, or just an editor). Test: find where currency/progress is stored, change it to “999999” — what happens? Sensitive values must live on the server or be signed/encrypted so that editing breaks the signature and gets rolled back. If the game honestly trusts a local file, that’s a one-click cheat.
Negative balance, overflow, races
- Spend more than you have: buy for 100 coins with 50 — must be rejected, not go negative.
- Overflow: farm/reward currency past
2^31(or whatever the type is) — must not overflow into negative. - Race condition: two parallel debits from one balance (two devices, rapid taps) — the sum must not “split.” The classic: spend the same coins twice simultaneously.
Fake IAP receipts
A real-money purchase is verified by server-side receipt validation via the App Store Server API / Google Play. Without it, a fake or replayed receipt = a free purchase. Test: feed an invalid/someone else’s/replayed receipt — it must not grant the item. (More on IAP in a dedicated purchase breakdown.)
Cheat tools
Players use GameGuardian, memory editors, Lucky Patcher, modified clients. You can’t stop this purely on the client — which is exactly why you need server authority. What to check: critical state (currency, progress, match results) is recomputed/validated by the server; anomalies (impossible gains, impossible scores) are detected; client-side anti-cheat and obfuscation are speed bumps, not protection.
Checklist: attacks on the economy
- Tampering “+currency / +level / +reward” request → server rejects it.
- Double tap on buy/reward → exactly one operation.
- Network drop during a transaction → no duplicates, no losses.
- Kill the app during a grant → state reconciles.
- Clock forward/back → timers and dailies computed by the server.
- Editing the local save (currency/progress) → rolled back / not applied.
- Purchase above balance → rejected, no going negative.
- Currency overflow → doesn’t go negative.
- Parallel debits (2 devices/rapid taps) → no split.
- Invalid/replayed IAP receipt → item not granted.
- Critical state validated on the server, not the client.
In short — what to take with you
- The economy is money, so test it as abuse resistance, not as a “buy button.”
- Don’t trust the client — compute and validate on the server; the key test is request tampering.
- Duplication bugs are caught with idempotency: drops, double-taps, kills → “exactly once.”
- Clock changes and save edits are mandatory attacks; the server owns time and value.
- Negative balance, overflow, races — check the boundaries.
- IAP — only with server-side receipt validation.
Further reading: OWASP MASVS — Mobile App Security · Apple — App Store Server API (purchase validation) · Google Play — Billing security