Rewards economy
points, caps, levels.
Every number that decides how many points an action gives, and how often. All of it is set in the console (Rewards economy and Features) and written to config/public. Defaults below come from docs/CONTRACT.md and admin/src/manifest.ts.
01Ground rules
- The server decides. Every credit goes through one server transaction (
credit()infirebase/functions/src/credit.ts) that writes a ledger row with the balance after it. Wheel and scratch results are drawn on the server; the scratch animation is cosmetic. - Whole points only. No decimals in the ledger. The VIP multiplier is rounded down.
- The day is UTC. Daily caps, streaks and the daily leaderboard reset at 00:00 UTC; the weekly leaderboard uses the ISO week in UTC.
- Points have no cash value. The console's Legal → Points notice is shown under every balance in the app. Keep its meaning.

02Rewards economy settings
| Setting | Field in config/public | Default | Allowed |
|---|---|---|---|
| Points per rewarded video | economy.pointsPerAd | 10 | 1 to 10000 |
| Rewarded videos per day (per user) | economy.adDailyCap | 20 | 1 to 500 |
| Seconds between rewarded videos | economy.adCooldownSeconds | 30 | 0 to 3600 |
| Daily streak rewards | economy.streakRewards | 5, 10, 15, 20, 25, 30, 50 | One number per line, day 1, day 2… After the last day the last value repeats; a missed day restarts at day 1. |
| Free wheel spins per day | economy.spinDailyFree | 1 | 0 to 20 |
| Extra spins per day for watching an ad | economy.spinExtraViaAdDaily | 2 | 0 to 20 |
| Wheel segments | economy.wheel | 5|5|30, 10|10|25, 20|20|18, 50|50|8, 2|2|30, 100|100|2, 15|15|20, 0|0|10 | One per line as label|points|weight. 4 to 12 segments, weight above 0 (higher = more likely). |
| Free scratch cards per day | economy.scratchDailyFree | 2 | 0 to 20 |
| Extra scratch cards per day for watching an ad | economy.scratchExtraViaAdDaily | 3 | 0 to 20 |
| Scratch card prizes | economy.scratchPrizes | 0|20, 5|35, 10|25, 25|12, 50|6, 200|2 | One per line as points|weight. 1 to 12 prizes. |
| Points per correct quiz answer | economy.quizPointsPerCorrect | 5 | 0 to 1000. A quiz can override it with its own points value. |
| Quizzes per day (per user) | economy.quizDailyCap | 5 | 0 to 100 |
| Inviter bonus (points) | economy.referralInviterPoints | 100 | Paid once the invited user has earned the unlock amount. |
| Welcome bonus for the invited user | economy.referralInviteePoints | 50 | 0 to 100000 |
| Points the invited user must earn first | economy.referralUnlockPoints | 100 | 0 to 1000000 |
| Days after sign-up to enter an invite code | economy.referralWindowDays | 7 | 0 to 365 |
| Level thresholds | economy.levels | 0, 100, 300, 700, 1500, 3000, 6000, 10000, 16000, 25000 | Lifetime points for level 1, 2, 3… Starting at 0, strictly ascending. |
| VIP multiplier | economy.vipMultiplier | 1.5 | 1 to 5. Applied to ad, spin, scratch, quiz and task credits while VIP is active. |
| Offer completions credited per day (per user) | economy.offerDailyCap | 10 | 0 to 100 |
A wheel segment without a weight, for example, is left out. The console's Status page lists every skipped line.
03Features on and off
Console → Features. A switched-off feature disappears from the app and the Functions refuse its calls. All are on by default.
| Switch | Field |
|---|---|
| Lucky wheel | features.spin |
| Scratch cards | features.scratch |
| Quizzes | features.quiz |
| Daily tasks | features.tasks |
| Offers | features.offers |
| Leaderboard | features.leaderboard |
| Invite friends | features.referral |
| Daily streak | features.streak |
04Levels, badges and leaderboards
The level follows lifetime points, which never go down. Badges are awarded by the server: first_ad, ads_50, ads_250, streak_7, streak_30, quiz_10, quiz_master (100% on a quiz with 5 or more questions), spinner_25, inviter_1, inviter_10, level_5, level_10 and vip. Their names are in app/lib/l10n/app_en.arb.
Leaderboards exist for today, this week and all time. Points you add by hand in the console do not change leaderboards.
05Built-in protection
- Caps and cooldown per user and day, as above.
- Rate limits on every callable function, per user, over a one-minute window (
firebase/functions/src/guard.ts). - One-time ad sessions: each verified callback credits once; mismatches open a fraud flag.
- App Check on every callable in production.
- Banned users are refused by every function except account deletion.