Skip to main content

Adversarial game economy red-team — arbitrage exploit detection for game economies

Project description

balancelab

Adversarial game economy red-team — detect arbitrage exploits before your players do.

balancelab

CI PyPI version Python 3.10+ Downloads License: MIT codecov Typed

Quick Start · How It Works · CLI Reference · MCP / Claude · vs. Alternatives · Contributing


Why

Game economies break in predictable ways. A crafting loop that converts gold → silver → gems → gold at a net gain of 24x will be found by players within hours of launch — not by QA. Manual balance spreadsheets don't scale. Playtesting can't enumerate all cycles. You need an automated red-team that treats your economy as a directed graph and mathematically proves whether arbitrage is possible.

balancelab does exactly that: encode your exchange rules, run balancelab scan, and get an exploit report showing every profitable cycle with exact gain ratios — before launch.

balancelab scan --format json   # CI-friendly, fails on exploits

How It Works

flowchart LR
    A[Define EconomyRule\nsource_item → target_item\nat source_qty:target_qty] --> B[Build EconomyGraph\ndirected exchange graph]
    B --> C[ExploitFinder\nBellman-Ford on\nlog-weight edges]
    C --> D{Negative cycle\ndetected?}
    D -->|Yes| E[ExploitPath\ngain_ratio > 1.0]
    D -->|No| F[Economy balanced\ntotal_found = 0]
    E --> G[ExploitReport\nall cycles ranked\nby gain_ratio]

Core primitives:

  • EconomyRule — an immutable, content-addressed exchange: give source_qty of source_item, receive target_qty of target_item. ID = SHA-256[:16] of the rule parameters. Same rule always produces the same ID.
  • EconomyGraph — a directed graph of EconomyRules. Supports neighbor traversal and serialization.
  • ExploitFinder — converts exchange rates to log-weights (weight = -log(rate)). A negative cycle in the log-weight graph corresponds to a positive-gain cycle in the economy. Uses Bellman-Ford for O(V·E) detection.
  • ExploitPath — a single circular trade path with its gain ratio (e.g., 24.0x).
  • ExploitReport — the full scan result: item count, rule count, all exploit paths, timestamp.

Facts are stored in a local SQLite database. No server required.


Features

Feature Details
Graph-based exploit detection Bellman-Ford on log-weight graph finds all profitable cycles
Content-addressed rules Same exchange always produces the same ID — no duplicates
Gain ratio ranking Every exploit path shows exact multiplier (e.g., 24.0x)
Offline / local-first Single SQLite file, no server required
CI exit code balancelab scan returns non-zero if exploits found
JSON output Machine-readable output for downstream automation
Markdown output Ready-to-paste GitHub PR comment
FastAPI REST server /rule, /rules, /scan, /reports, /health endpoints
MCP server Model Context Protocol integration for Claude and other agents
OpenAI tool spec tools/openai-tools.json for GPT function calling
45 tests Comprehensive test suite covering all layers

Quick Start

pip install balancelab
from balancelab.economy import EconomyRule, EconomyGraph, ExploitFinder
from balancelab.report import print_report

# Define your economy's exchange rules
graph = EconomyGraph()
graph.add_rule(EconomyRule("gold", "silver", 1.0, 3.0, rule_id="mint"))
graph.add_rule(EconomyRule("silver", "gems", 1.0, 2.0, rule_id="jeweler"))
graph.add_rule(EconomyRule("gems", "gold", 1.0, 4.0, rule_id="trader"))

# Find exploits
finder = ExploitFinder()
report = finder.find_exploits(graph)

# Display results
print_report(report)
# Exploit Report (id: a3f8b2c1d4e5f6a7)
#   Items: 3  Rules: 3
#   Exploits found: 1
# ┌──────────────────┬─────────────────────────────────────────┬────────────┐
# │ ID               │ Path                                    │ Gain Ratio │
# ├──────────────────┼─────────────────────────────────────────┼────────────┤
# │ 4d7e9c2a1b8f3e6a │ gold → silver → gems → gold             │ 24.00x     │
# └──────────────────┴─────────────────────────────────────────┴────────────┘

CLI Reference

balancelab [--db PATH] COMMAND [OPTIONS]
Command Description Key options
add SOURCE TARGET SRC_QTY TGT_QTY Add an exchange rule --rule-id LABEL, --db PATH
scan Find exploits in stored rules --format {rich,json}, --db PATH
report REPORT_ID Show a specific exploit report --format {rich,json}, --db PATH
log List all exploit reports --db PATH
status Show rule count and last scan --db PATH
simulate GRAPH_FILE Simulate economy from a JSON graph file --steps N, --strategy {greedy,balanced,exploit}, --format {rich,json}
fixes Show fix recommendations for the latest exploit report --report-id ID, --db PATH

Global options:

Option Default
--db PATH .balancelab/economy.db

Examples:

# Add exchange rules
balancelab add gold silver 1.0 3.0 --rule-id mint
balancelab add silver gems 1.0 2.0 --rule-id jeweler
balancelab add gems gold 1.0 4.0 --rule-id trader

# Scan for exploits
balancelab scan

# Machine-readable output (for CI)
balancelab scan --format json

# Review previous scans
balancelab log

MCP / Claude

balancelab ships a Model Context Protocol server. Add it to Claude Desktop:

{
  "mcpServers": {
    "balancelab": {
      "command": "balancelab-mcp"
    }
  }
}

Available MCP tools: add_rule, scan_economy, list_reports.

Install with MCP support: pip install "balancelab[mcp]"

You can also find balancelab on Smithery for one-click MCP installation.


REST Server

balancelab ships a FastAPI server exposing all core operations over HTTP.

pip install "balancelab[api]"
uvicorn balancelab.api:app --reload

Available endpoints:

Method Path Description
POST /rule Add an exchange rule
GET /rules List all rules
POST /scan Run exploit scan
GET /reports List all reports
GET /health Health check

The full OpenAPI spec is in openapi.yaml.


OpenAI

Use tools/openai-tools.json for OpenAI function calling:

import json, openai
tools = json.load(open("tools/openai-tools.json"))
response = openai.chat.completions.create(
    model="gpt-4o",
    tools=tools,
    messages=[{"role": "user", "content": "Scan my economy for exploits"}],
)

Advanced API

Beyond the core exploit detection primitives, balancelab exposes several higher-level APIs imported directly from the package:

from balancelab import (
    simulate,
    recommend_fixes,
    sensitivity_analysis,
    critical_path,
    BalanceFix,
    SensitivityResult,
    SimulationResult,
)

simulate(graph, initial_levels, n_steps=100, agent_strategy="greedy") -> SimulationResult

Run a forward simulation of the economy. Strategies: "greedy" (apply every rule each step), "balanced" (one rule per source item), "exploit" (agent actively exploits known cycles).

from balancelab import simulate
from balancelab.economy import EconomyGraph, EconomyRule

graph = EconomyGraph()
graph.add_rule(EconomyRule("gold", "silver", 1.0, 3.0))
result = simulate(graph, {"gold": 100.0, "silver": 0.0}, n_steps=50, agent_strategy="exploit")
print(result.inflation_detected)   # True/False
print(result.final_levels)         # {"gold": ..., "silver": ...}

SimulationResult fields: steps, final_levels, violated_rules, inflation_detected, inflation_resource, summary.

recommend_fixes(report) -> list[BalanceFix]

For each exploit in an ExploitReport, suggest the minimum intervention to neutralize it.

from balancelab import recommend_fixes
fixes = recommend_fixes(report)
for fix in fixes:
    print(fix.fix_type, fix.target_edge, fix.suggested_value, fix.description)

BalanceFix fields: exploit_path, fix_type ("rate_cap", "cooldown", "daily_limit", "require_prerequisite"), target_edge, suggested_value, description, estimated_reduction_pct.

sensitivity_analysis(graph, report) -> list[SensitivityResult]

Rank all economy nodes by how much they affect overall balance, descending by impact_score.

from balancelab import sensitivity_analysis
results = sensitivity_analysis(graph, report)
for r in results:
    print(r.node_id, r.impact_score, r.recommendation)

SensitivityResult fields: node_id, node_type ("hub", "source_only", "target_only"), impact_score (0–1), connected_rules, exploit_involvement, recommendation ("monitor", "rate-limit", "gate").

critical_path(graph) -> list[str]

Find the sequence of nodes with the highest economic throughput (most exchange-rate flow). Useful for identifying which items act as economic bottlenecks.

from balancelab import critical_path
path = critical_path(graph)
print(" -> ".join(path))   # e.g. "gems -> gold -> silver"

vs. Alternatives

Approach Scalability Automation Accuracy Cost
balancelab Graph (O·V·E) Full CI Mathematical Free
Manual spreadsheet Poor None Error-prone Low
Playtesting Poor None Incomplete High
Custom scripts Variable Manual Variable Medium
LLM-only analysis N/A Partial Hallucination risk High

Repository Tree

balancelab/
├── src/balancelab/
│   ├── __init__.py          # Public API
│   ├── economy.py           # EconomyRule, EconomyGraph, ExploitFinder
│   ├── store.py             # SQLite persistence
│   ├── report.py            # Rich/JSON/Markdown formatters
│   ├── cli.py               # Click CLI
│   ├── api.py               # FastAPI server
│   └── mcp_server.py        # MCP server
├── tests/
│   ├── test_economy.py      # Data model tests
│   ├── test_exploit.py      # Bellman-Ford exploit detection
│   ├── test_store.py        # SQLite CRUD
│   ├── test_report.py       # Formatters
│   ├── test_cli_runner.py   # CLI integration
│   └── test_api.py          # FastAPI endpoints
├── tools/openai-tools.json  # OpenAI function calling spec
├── openapi.yaml             # Full OpenAPI 3.1 spec
├── examples/demo.py         # Standalone demo
└── smoke_test.py            # End-to-end smoke test

GitHub Topics

Suggested topics for discoverability: #game-economy #arbitrage #balance-testing #agents #mcp #llmops #python #cli #exploit-detection #graph-algorithms


Case Studies

See how teams are using balancelab in production:


Stay Updated

Subscribe to The Silence Layer — weekly dispatches on production AI infrastructure, new releases, and the failure modes that production AI systems don't surface until it's too late.

Star History

Star History Chart

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

balancelab-0.1.0.tar.gz (3.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

balancelab-0.1.0-py3-none-any.whl (23.3 kB view details)

Uploaded Python 3

File details

Details for the file balancelab-0.1.0.tar.gz.

File metadata

  • Download URL: balancelab-0.1.0.tar.gz
  • Upload date:
  • Size: 3.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for balancelab-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0ac3af5e41bb3ebba2edd70a30c55478f6b66d2577a1dab9dcd5e0edd2ce9697
MD5 cb7b00dcfd264fd5aed9dbd8d57d5d45
BLAKE2b-256 095e9ba7c61fec8789a64b1e63cdd84379b5285a0d0381b47bd7f0d9f8b657e5

See more details on using hashes here.

File details

Details for the file balancelab-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: balancelab-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 23.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for balancelab-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d200b346bbb31cd496d54c190bb3bfb881e79fbf99c831632b5501ad682237b3
MD5 c19df6c2feea25c042ae9817399c3600
BLAKE2b-256 2b8d5aa06e513bb2683e26cfbe6b7f3858cd0bda50e9609bc61f256f8e590a3d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page