Protecting the economy from dupes

How trades, loadouts, and reward redemptions are guarded against item duplication, and why trade-up avoids the problem entirely.

Item duplication is the worst bug class a server with a real economy can have. One reliable dupe doesn’t just inconvenience players, it floods the economy, tanks the value of everything in the store, and erodes trust the moment word gets out. So the systems that move valuable items are built defensively, on the assumption that a player will eventually try to race them.

Guard the item-moving paths

The flows that hand a player an item, take one, or swap one are where dupes hide: loadouts, deposits, and voucher redemptions. A few of the guards in place:

  • An anti-dupe controller sits over loadout changes, and applying a loadout rerolls the worn item’s id so the same swap can’t be replayed to mint a second copy. The anti-dupe skip is held across a full loadout menu session rather than re-granted per click, so a player can’t open and close the menu to slip through the gap.
  • Deposits hold a guard until the duplicated item is actually removed. A robot deposit, for example, doesn’t credit the player until the source item is gone, so a deposit-then-cancel race can’t leave them with both the item and the credit.
  • Redemptions are guarded against false positives too. Pickaxe voucher redemption was hardened so a legitimate redeem doesn’t trip the dupe detector, because an anti-dupe system that punishes real players is its own kind of failure.

A recurring theme is that several of these started as bugs that looked like dupes (a loadout switch wiping desynced armor, a loadout apply deleting a worn item) and were fixed so the system neither duplicates nor destroys a player’s gear when state is briefly out of sync.

Trade-up sidesteps the problem

The skin trade-up system takes a different approach: it never handles item stacks at all. There are no items to drag, drop, or desync, because the whole contract is in-memory and reads and writes balances directly.

  • One in-flight execution per player. When a player commits a contract, an exclusive lock is taken (tryStartExecuting). A second click during execution is dropped, so a double-submit can’t run the roll twice.
  • Consume, then roll, then award, all or nothing. Each input is consumed against its source; if any consumption fails (most often because the player’s balance changed on another server mid-contract), every already-consumed input is refunded and the whole thing aborts. The player is never left having spent inputs with no output.
  • Graceful degradation. If a roll succeeds but no source has a skin of the target rarity to award, it refunds everything and tells the player to contact staff rather than silently eating the inputs.

That refund-on-partial-failure path is the load-bearing detail. Without it, a cross-server race during the consume phase would quietly destroy part of the player’s inputs. With it, the system keeps the player whole whenever it can’t safely deliver, at the cost of slightly more bookkeeping.