PEERPLAY MENU
Download PeerPlay
Home / Blog / My App Trusted the Phone With Money. Twice.

My App Trusted the Phone With Money. Twice.

Short answer

PeerPlay, a Flutter and Firebase app I run alone, made the same mistake twice. A developer's wallet balance was writable straight from their own device with no server check, and the tester bonus on paid campaigns was paid by the phone. The fix in both cases was the same: the device reports what happened, the server decides what it is worth, and early payouts get a human review.

Money in an app has a simple rule that every backend developer has heard: never trust the client. I knew the rule. PeerPlay still broke it twice, in two different features.

PeerPlay is a Flutter and Firebase app that I build and run on my own. Developers test each other's apps in tracked 14-day rounds, and there is a small wallet for referral rewards and tester bonuses. Both of the mistakes below lived in that money layer, and neither one showed up as a visible bug. Everything looked fine on screen. That is exactly why this kind of mistake survives so long in a small app.

Mistake one: a balance anyone could edit

I found that a developer's wallet balance was writable directly from their own device, with no check on the server. The app talks to the database straight from the phone, so anyone who can write to their own record can write any field in it, balance included.

This is an easy trap in a Firebase app. The client SDK makes it pleasant to read and write data from the phone, and a common starting rule is "a user may write their own document". That rule sounds safe. It quietly means the user owns every field in that document, including the ones that represent money or status.

The balance did not matter much while nothing paid out of it. It started to matter the moment I planned a feature whose whole job was to put money into it.

Why referral payouts go through a person first

That feature was the referral program. The reward is $2, and it only reaches review after the referred developer registers their own app, gets five separate other testers with at least three qualified days of use each, and puts in three days of testing themselves.

Because of the wallet discovery, I did not credit referrals automatically. The first three payouts for any referrer are reviewed by hand. Auto-approval only kicks in after that, and a risk score can still pull a case back into manual review, for example when devices look shared or payout details are reused.

Manual review sounds old-fashioned for an app. For a solo developer it is the cheapest fraud system there is. A few minutes of looking at early payouts costs far less than discovering later that a reward was being farmed.

Mistake two: the phone paid the bonus

The second time came with PeerPlay's first paid campaign. It was for Nada, a women's health and cycle tracking app, on the Starter Pro package with 15 verified testers. It ran from September 16 to October 6, 2026. 18 testers joined, 11 completed all 14 days, and 217 tester-days were logged, all of them qualified. Google then granted Nada production access.

While that campaign was running, I rebuilt the paid-campaign logic. Paid campaigns had used per-tester rounds, and the tester bonus was paid by the phone. Now a paid campaign has one calendar for everyone, the bonus needs at least 12 qualified days out of 14, and the server pays it instead of the device.

It was the same mistake as the wallet in a new costume. The app was letting the device decide that a reward had been earned. With free test swaps it was easy to overlook. A paying customer made it impossible to ignore, because now the rules had to hold up for someone who had paid for them.

The rule I follow now

The device reports what happened. The server decides what it is worth. A phone can say "this tester opened the app today". It should never be the one that says "so add a bonus to this wallet".

In practice that means a few concrete checks for any small app with a wallet, credits or rewards. Money and status fields should not be writable by the user they belong to, so lock them down in your security rules and let only server code change them. Rewards should be computed from records of what happened, not from a number the client sends. Early payouts should be reviewed by a person until you trust the numbers. And any feature that pays out deserves a quick look at who can write each field it reads.

None of this needs a big backend. It needs you to ask one question about every field that touches money: who can write this? If the answer is "the phone", that is your next fix.

FAQ

Is it safe to update a wallet balance from a Flutter client in Firebase?

Not on its own. If the user can write the field, they can set it to anything. Keep balances read-only for the user in your security rules and change them only from trusted server code.

Why review referral payouts by hand?

Early on you do not know what abuse looks like in your app. Reviewing the first few payouts per person is cheap, and it catches patterns like shared devices or reused payout details before they cost money.

How does PeerPlay pay tester bonuses on paid campaigns now?

A paid campaign runs on one calendar for all testers, a tester needs at least 12 qualified days out of 14 to earn the bonus, and the server pays it rather than the tester's phone.

What counts as a qualified day on PeerPlay?

PeerPlay checks that a tester actually opened the app for a real minimum session that day, not just that it was installed. Testers who go quiet are removed from a round.

Ready to Pass Your Closed Testing Requirement?

Join PeerPlay's peer-to-peer network and get your 12 verified testers for 14 days - free.

Download PeerPlay