Skip to content

Detection Signals

joogiebear edited this page Jul 14, 2026 · 1 revision

Detection Signals

EconGuard runs four signals over the unified ledger. Two of them only fire on young accounts; one fires on all accounts; one is informational. All are configured under detection: in config.

The young-account gate (the core idea)

An account is young if it joined within young-account.max-age-days OR has under young-account.max-playtime-hours playtime. Either qualifies.

This gate is deliberate. A veteran who legitimately sells a lucky drop for 200M is not suspicious, and flagging them is how an anti-abuse system trains staff to ignore it. What is suspicious is wealth arriving with no time invested — the one thing an RMT buyer can't fake without actually playing the game. So the two value-arrival signals below only look at young accounts.

The four signals

1. Large transaction — informational, all accounts

Fires when any single movement is at or above detection.large-transaction.

This is an alert, not a flag — it says "something big happened," worth an eyeball, without asserting abuse. Applies to everyone regardless of age.

2. Young incoming transfer — flag, young only

Fires when a young account receives a single incoming transfer (a /pay, an auction sale, etc.) at or above detection.young-incoming-transfer.

A new account taking a large single payment is the simplest RMT shape: someone hands the buyer their purchased coins in one lump. This catches it directly.

3. Velocity — flag, young only

Fires when a young account gains at or above detection.velocity.threshold (incoming) within detection.velocity.window-minutes.

Where signal 2 catches one big payment, velocity catches the same total spread across several smaller ones to duck the single-transfer threshold. Money arriving fast at a new account is the laundering fingerprint.

4. Counterparty correlation — flag, all ages

Fires when the same payer funds the same receiver for a combined total at or above detection.counterparty.threshold within detection.counterparty.window-minutes. Both parties are flagged. Set the threshold to 0 to disable.

This one deliberately ignores account age, because it catches the ring — and the seller in an RMT ring is usually an established account, not a young one. It's also the signal a per-plugin anti-abuse layer structurally cannot replicate, because the transfers are spread across the bank, the auction house, and /pay — no single plugin sees the correlation. EconGuard does, because everything reports into one ledger.

Alerts vs flags

  • Alert — a console/chat/Discord message. Informational. Nothing is stored to act on later. (Signal 1.)
  • Flag — recorded for review and listed by /eg flags. Heavier. It's asserting "this looks like abuse; a human should look." (Signals 2, 3, 4.)

Where they go

  • The server console.
  • Online staff with econguard.alerts (if notify-staff is true) — they also get the pending flag count on join.
  • An optional Discord webhook (discord-webhook).

Tuning

The shipped thresholds are high, sized for a large-currency-supply server, and on a small economy they may never fire.

Calibrate against your own numbers rather than the defaults:

  • Look at what an established player's balance actually is.
  • Set large-transaction around what an unusual-but-legitimate single trade looks like on your server.
  • Run for a week, then read /eg flags.

A system that flags twenty accounts a day gets ignored within a week — and an ignored flag is worth exactly as much as no flag. Fewer, higher-confidence flags beat a noisy net.

What EconGuard cannot do

It surfaces patterns; it does not prevent RMT. The in-game half of an RMT deal looks identical to a legitimate gift, and nothing running on your server can tell them apart with certainty — which is why EconGuard flags for review and never auto-punishes. A false ban costs far more than a missed flag. To actually cap the damage, pair it with a currency maximum and friction (limits/cooldowns/tax) on player-to-player transfers.

Clone this wiki locally