A MEMECOIN
WITH A MECHANIC.
Meme Wars is a two-faction war fought once a day. Players stake $WAR on DOGS or CATS; the winning side splits the day's mint, the losing side's stake is partially burned, and the winner captures a tile on a 25-cell map. After 30 days the faction holding the most tiles takes a slice of the treasury. Every parameter is set at launch and readable on-chain.
A memecoin with only a price chart
Most memecoins have no reason to come back tomorrow. There is no ritual, no team, no consequence, and the supply is usually a promise from a backend.
A war you can verify
A NEP-141 token whose supply is a function of staking, winning and losing. Enlist once a day, build a streak, flip tiles, and watch the mint/burn ledger update on-chain.
Cheap enough to play daily
Fast finality, low fees, human-readable accounts and a clean NEP-141/NEP-297 toolchain. The whole game is one Rust contract; there is no backend to switch off.
What the judge can verify
| Requirement | Implementation | Evidence |
|---|---|---|
| NEP-141 token | ft_transfer, ft_transfer_call, ft_balance_of, ft_total_supply, metadata, NEP-145 storage. | get_config / ft_metadata view; contract source; a transfer transaction. |
| Mechanic on-chain | join_faction, enlist, settle_day, claims and seasons are contract methods. No backend. | get_log; event log; any testnet explorer page. |
| Parameters fixed at launch | new(config) is the only initializer. No set_config, pause, upgrade or withdraw method. | get_config returns the same values forever; source search for setters is empty. |
| Sybil resistance, limits disclosed | Stake cost, min/max stake, fixed daily pool, streak multiplier, underdog bonus, season power. | 60-day simulation; README limitations; this page. |
| Streak / progress / log page | Battle page shows the countdown, tug bar, streak strip, claims and the event log. | Connect a wallet and enlist; the log updates from get_log_tail. |
| 60-day simulation | sim/simulate.py, fixed seed, five scenarios, sensitivity runs, SVG charts. | sim/results/*.svg and summary.json, committed to the repository. |
The math
All amounts are integers; ratios use basis points. Settlement is O(1) over aggregate amounts, and each claim is O(1) over the player's own enlistment. The contract never iterates over all participants.
This demo deployment
Reading parameters from the contract…
What the simulation chose
The daily mint is deliberately small relative to total supply (100k WAR/day on a 1B genesis = 0.01%/day). The losing-side burn is larger than the mint in the balanced scenario, so the supply is a sink, not a faucet: −1.90% over 60 days in the committed run, and worse when turnout is cold.
The 2.00× underdog bonus is the maximum allowed by the config. It reduces a 70/30 player split from a 100% sweep to roughly 80/20 day wins in the stress test, but it cannot make an extremely lopsided community fair. That limitation is disclosed rather than hidden.
The season bonus is 2% of the remaining treasury, split by season power among the faction that owns the most tiles on the final map. It is the long-horizon prize; the daily mint is the rhythm.
Supply, treasury, turnout
Fixed seed 42, pure standard library, reproducible with python3 sim/simulate.py. The 30-seed robustness run behind the sybil number is documented in docs/PARAMS.md.
What is actually enforced
- Every enlistment locks real WAR; the losing side burns 20% of its stake.
- A per-account daily maximum caps how much one wallet can move the day.
- The daily mint is fixed. More accounts do not create more rewards; they split the same pool.
- The streak multiplier starts at 1.05× and takes 20 consecutive days to reach 2.00×. Fresh accounts start behind.
- The weaker faction gets a 2.00× underdog bonus in production, so adding accounts to the larger side does not automatically buy the day.
- Season power is proportional to stake × streak, not headcount. Minimum-stake sock puppets earn minimum shares.
What it does not do
- A chain cannot tell whether 30 accounts belong to one person. These mechanisms raise the cost and dilute the payout; they do not prove personhood.
- Sybils can hedge both factions. The losing side still pays the burn, so it is not risk-free, but it can smooth outcomes.
- A capital-rich player can still move a day. The daily cap limits one account; it does not limit many funded accounts.
- The MVP has no faction switching. An extreme 70/30 player split still favors the majority; the simulation shows roughly 80/20 day wins. The season/map reset limits long-term lock-in, not daily math.
- The demo faucet exists only in demo_mode. The production recipe has no free tokens; staking costs real balance.
- Sybil ROI is negative on average in the simulation (−4.52% over 30 seeds), but individual seeds can be positive. It is a deterrent, not a guarantee.
Explored, not faked
The mechanic needs native mint/burn, so the demo uses a self-deployed NEP-141. A launchpad import can be added without changing the contract.
Cross-chain buy flow is a frontend adapter. The MVP is testnet-only and the 1Click API has no testnet, so no fake swap is shown.
Wallet Selector with MyNearWallet and Meteor is the current onboarding path. HOT can be added as another module.
No mainnet liquidity was created for this testnet demo. A production launch can point the buy button at a Rhea/Ref pool.
A War Prophet analyst can be built off-chain; it would be a player, not an admin. Nothing in the game depends on it.
Optional community/ops treasury tooling. It never controls game parameters or the contract treasury.
No partner can pause the game, change a parameter or withdraw the treasury. Partner outages cannot affect enlist, settle or claim.
What is deployed
Contract: war-demo.testnet
There is no admin method: no set_config, no pause, no upgrade, no withdraw_treasury. Parameters live only in the constructor. The contract account has a deployer key during the hackathon for testnet iteration; the production checklist removes every full-access key after deploy and records the transaction.
The contract keeps a bounded 200-entry event log and emits NEP-297 EVENT_JSON for every mint, burn, capture and claim.
This demo is testnet only. Tokens have no monetary value. Do not send mainnet funds.
Do X, see Y
- 1Connect a testnet wallet with a little testnet NEAR for gas and the 0.01 NEAR storage deposit.
- 2Pick DOGS or CATS. The join transaction registers storage and, when the faucet is eligible, claims 100,000 test WAR in the same batch. The demo faucet gives WAR, not NEAR.
- 3Enlist 1,000 WAR; the tug bar, your locked stake and the streak strip update.
- 4Wait for the 60-second day to end and click Settle; a winner, a mint/burn row and a map tile appear.
- 5Claim the stake + reward; your balance and the ledger update.
- 6Open Map and Season; the tile and the season progress are live.
- 7Run python3 sim/simulate.py; open sim/results/supply.svg.