
Attacks and defences
The exploits a WoW realm with a real token attracts, and exactly what stops each one: spending money in flight, double withdrawals, dupes, forged requests, bot farms and more.
How to read this page
A realm where the money is a token is a target. Everything people tried on vanilla servers (dupes, speed hacks, bots) is still tried here, plus everything people try on a token (draining a treasury, replaying a signature, phishing a wallet). This page lists the attacks we design against and, for each, what stops it and which layer enforces it:
| Layer | What it is |
|---|---|
| Game | the realm server and its database, which own every character's money |
| Bridge | the service that turns the game's money changes into Solana transactions |
| Program | the economy program on Solana, whose rules nobody can skip, including us |
| Web | the sign-in service, the relay and the website |
The program is the last line: even if the game or the bridge is fooled, the program refuses what its rules don't allow. How it's built explains the parts, and Onchain mechanics the money rules in detail.
This page lists what's closed. Anything still open is tracked privately and closed before launch; if you find one, see Report a problem.
Money in flight
Spending Mithril while it's being withdrawn
The attack. Ask to withdraw 100,000 Mithril, and while the request is in flight, spend the same 100,000: buy from a vendor, trade it away, mail it to an alt. Then you'd keep the goods and get the tokens.
What stops it (game). A withdrawal checks your balance again when it runs, on the same thread that handles your purchases and trades, and takes the Mithril out of your bags in the same database transaction that records the withdrawal. Only then can the bridge see it. If you spent the money first, the withdrawal is refused. If the withdrawal ran first, the money is already gone from your bags. There is no moment where both are possible.
Withdrawing twice
The attack. Fire two withdrawals at once, from two characters on the same account, two browser tabs, or a script.
What stops it (game, program). One withdrawal per account at a time, then a 15-minute cooldown, checked in memory and again in the database. On chain, every withdrawal carries the wallet's next sequence number, and the program accepts each number exactly once.
Crashing the server mid-withdrawal
The attack. Withdraw, then crash the server (or wait for a crash) before the transaction lands, hoping the game forgets the debit or the bridge sends it twice.
What stops it (game, bridge). The debit, its record and your saved balance commit together, so a crash either keeps all three or none. After a restart, the bridge first resolves every transaction it had in flight, by its batch id, before sending anything new. Nothing is paid twice and nothing is lost. We test this on every bridge upgrade; the books have matched to the copper every time.
Refund and payment both
The attack. Get a withdrawal refused (say, the chain rejects it), collect the refund, and have the original land anyway.
What stops it (bridge, program). A refusal is final on chain before the refund is written, and a withdrawal that landed is never refunded. Both are keyed to the same transfer id.
Duplication bugs
The attack. Every old server has its dupes: mail tricks, trade timing, crash timing. Duplicate gold, then cash it out.
What stops it (program). The chain can't be duped. When the game says a vault spends Mithril it doesn't have, the program skips the move instead of covering it from the Vault, so a dupe can never create tokens. Cashing out duplicated Mithril runs into the daily allowance and the realm budget, and the reconciliation that compares every character with its vault flags the account. One thing a dupe could still reach is Mithril in transit: what sits in the mail and on the auction house is held in a shared escrow vault. The reconciliation watches that escrow too, and the bridge holds escrow payouts whenever the escrow comes up short. In the economy simulation, a 2,500,000,000 MITH dupe paid its author 600,000 MITH over two days before it was stopped.
Money in the mail or on the auction house
The attack. Spend the same Mithril twice while it's "in the mail": once by the sender, once by the receiver.
What stops it (program). Money in transit sits in an escrow vault on chain, owned by the program with no private key. It leaves the sender when the mail is sent or the bid placed, and reaches the receiver when they take it. It's never in two places.
Emptying a vault from outside the game
The attack. Your game vault is derived from your wallet. Sign a transaction that moves tokens out of it directly, while the game still thinks you have them.
What stops it (program). Owner-signed withdrawal from a game vault is switched off. A vault only moves when the game moves its money, through the bridge.
Withdraw and deposit
Withdrawing to someone else's wallet
What stops it (program, game). A withdrawal has one input, the amount. The destination is the wallet linked to your account, fixed by the program; nothing in a request can change it.
Relinking a wallet
The attack. Link your wallet to a second account, or someone else's wallet to yours.
What stops it (web). A wallet belongs to one game account, for good. Signing in with a known wallet always opens its own account.
Crafted amounts in the Exchange
The attack. Type something clever in the Mithril Exchange's amount box: a negative number, a huge number, 1e9, thousands of digits, from a modified client.
What stops it (game). The amount reader accepts digits, k and m (25k, 2m), the old g s c form, spaces and commas, and nothing else; anything else, a minus sign included, means "not an amount". Every number is checked against the game's money limit, and the result again. Even then, the withdrawal checks your real balance.
Replaying a web withdrawal
The attack. Capture the message you signed for a web withdrawal and send it again.
What stops it (bridge). Each signed withdrawal carries a one-time challenge and an expiry. Once used, it's spent.
Depositing twice, or depositing nothing
What stops it (bridge). The bridge builds the deposit transaction, you sign it, the bridge submits it and credits your character once, after the chain confirms it. A deposit has one id and moves from built to submitted to credited, failed or expired, never backwards.
Phishing your signature
The attack. A fake site asks Phantom to sign a "withdrawal" that is really something else.
What stops it (web, your wallet). Sign-in and withdrawals are short text messages that name the site, and Phantom shows you the site that asks. Deposits are transactions the bridge built, and Phantom shows the amount. Only sign on wowonchain.com. The game never asks for your seed phrase, and neither will we.
NPCs and shops
Free Mithril from the old test helper
During testing, a goblin handed out Mithril, cheap gear and free kits, which a vendor would buy back for real Mithril: an endless loop. He's now Trade Prince Mithrix, who only sells things for Mithril. His test tools are switched off on the live realm for every account, staff included, and the check runs when his menu is drawn and again on every click.
Reaching staff menus
What stops it (game). The server takes the menu and option from its own copy of the menu, not from your client, and checks your account's rank on every click.
Buying low and selling back high
What stops it (game). Anything an NPC sells for Mithril costs more than any vendor pays for it, so no loop of buying and selling makes Mithril.
Accounts and bots
Playing without the wallet
What stops it (web). The only way in is the Phantom sign-in. The realm's own ports aren't reachable from the internet; the page talks to the realm through our relay.
Faking your address
What stops it (web). Per-network limits use the address our own front door saw. A client that claims to be someone else in a header is ignored.
Bot farms
What stops it (program, game). A wallet can earn at most its daily allowance from the Vault, and the realm as a whole at most its daily budget, shared out pro rata when it runs short. A bot farming around the clock earns no more per day than a busy player. New accounts are limited per network, and data-center, VPN and Tor addresses are blocked at sign-in.
The Vault and the token
| Attack | What stops it |
|---|---|
| Draining the Vault in one go | Per-wallet allowance, realm budget per 24 h, circuit breaker on spikes (program) |
| Printing MITH | Impossible: the mint authority is removed right after the genesis mint, so nobody, the program included, can create MITH |
| Freezing holders' tokens | The token has no freeze authority |
| Raising a hidden transfer fee | The fee is 0%, and only the program's configuration can set it, within hard bounds |
| A stolen admin key | One key isn't enough: the admin is a multisig with a time lock, its powers have hard bounds compiled into the program, and every change is public |
| A stolen server key | Boxed in: the daily allowance, the realm budget and hourly caps on vault moves and withdrawals, withdrawals only to each owner's own wallet, and a pause |
The website and services
- Admin routes. Reconciliation and other internal endpoints aren't reachable from outside; the public front forwards only the routes the pages use.
- Path tricks. File routes accept plain file names only, so
../gets you nothing. - Injected names. Every name and note from the server is shown as text on the site, never run as code.
- Secrets in the page. The page never sees the bridge's keys, our RPC address or any API key.
- Cross-site requests. Anyone can write their own client, so the server checks everything itself. On top of that, the sign-in service and the relay accept browsers only when they come from our own site.
The client
- Speed hacks and teleports. The realm is the authority on where you are and what you can do. A modified client can lie, so the server checks every move against what is possible and disconnects clients that cheat.
- Fake system messages. System lines and the deposit window come from the server and the real Mithril Exchange only.
- Automation. It's our own client, so automation leaves traces we can look for.
How we test
- Exactly once, for real. Three bridge upgrades and a full token migration in testing, each followed by a reconciliation of every character against its vault: no drift.
- Load. An RPC stress test of the settlement pipeline (about 250 concurrent players per RPC plan, settlement in about a second).
- A separate test realm for every money feature before it reaches the public realm.
- Simulation. An agent-based model of the whole economy, with bots, churn and deliberate dupes, which set the limits above.
Report a problem
If you find a bug that touches money or security, report it privately to the team rather than in public chat or on the forums. Contact details are published here at launch. Please give us time to fix it before you talk about it.