Audits › alsk1992/CloddsBot

Open-source trading bot · audit

alsk1992/CloddsBot

Open Source AI trading agent that operates autonomously across 1000+ markets - Polymarket, Kalshi, Binance, Hyperliquid, Solana DEXs, 5 EVM chains. Scans for edge, executes instantly, manages risk while you sleep. Agent commerce protocol for machine-to-machine payments. Self-hosted. Built on Clau

Repository facts

Repository
alsk1992/CloddsBot
Stars
2,758
Forks
335
Open issues
28
Language
TypeScript
License
MIT
Created
2026-01-26
Last push
2026-09-12
README names exchanges
binance, bybit, robinhood, hyperliquid
README mentions an LLM
yes
Backtesting mentioned
yes
Paper trading / dry run mentioned
yes

Source: GitHub API, 2026-09-17. Exchange and LLM mentions come from a keyword scan of the README, not from running the bot.

Risk-control audit

Audited 2026-09-17 · c930628c47a4

21 of 21 controls checked: 6 present, 10 partial, 2 absent, 0 not applicable, 3 not verified.

Main risk
The unified risk engine (order cap, exposure limits, circuit breakers) is real and well-built, but at the exact commit audited it is confirmed bypassable through several AI-agent-invoked order paths (Drift, Pump.fun, Meteora, a bundled futures skill, MARKET-order price spoofing, and a direct exchange fallback), per two currently open GitHub issues (#126, #127) filed against this same commit.
Summary
CloddsBot is a large (12k+ files across dozens of exchanges/chains), open-source, Claude-powered autonomous trading agent covering prediction markets (Polymarket, Kalshi, etc.), crypto futures (Binance, Bybit, MEXC, Hyperliquid) and Solana DeFi. It has a genuinely well-designed, unified risk engine (order size cap, portfolio exposure limits, daily-loss/drawdown circuit breakers, VaR, audit-logged trades, encrypted credentials, chat-channel allowlisting) that is real and wired into a central orchestrator. The critical finding is that this central gate is provably bypassable today: two issues opened by an independent reviewer at the exact commit audited (c930628, main HEAD) show that AI-agent-invoked order paths (Drift, Pump.fun, Meteora, a bundled futures skill, a direct market-order price trick, and a direct exchange fallback) can submit real orders without ever reaching the order-size cap or the circuit breaker.
ControlVerdictEvidenceNote
Size and exposure
Maximum order sizePartialsrc/trading/risk.ts enforceMaxOrderSize() checks notional (USD) vs maxOrderSize, wired in src/risk/engine.ts validateTrade() step 3; BUT GitHub issue #126 (OPEN, filed at this exact commit c930628) proves MARKET orders defeat the cap because resolveOrderPrice() trusts a caller-supplied `price` (src/execution/futures.ts#L1408) while MARKET submission never forwards it (src/execution/futures.ts#L261; same pattern src/trading/futures/index.ts#L5376). https://github.com/alsk1992/CloddsBot/issues/126The cap exists and is enforced for the guarded limit-order path, but is provably bypassable for MARKET orders at the audited commit.
Execution paths that skip the capPartialsrc/trading/orchestrator.ts explicitly wraps buyLimit/sellLimit/marketBuy/marketSell/makerBuy/makerSell/protectedBuy/protectedSell/placeOrdersBatch with preTradeCheck() (kill switch + safety.validateTrade + breaker). BUT issue #126 (OPEN) lists Drift, Pump.fun and Meteora agent handlers (src/agents/handlers/solana.ts#L1123,#L1188,#L352) and the bundled /bf skill (src/skills/bundled/binance-futures/index.ts#L194) as order paths that reach submission without the breaker or maxOrderSize. Issue #127 (OPEN) confirms a direct Opinion-exchange fallback in src/agents/index.ts (~L13225-13233) that consults only env DRY_RUN, with no breaker/size check. https://github.com/alsk1992/CloddsBot/issues/126 , https://github.com/alsk1992/CloddsBot/issues/127One central, well-documented gate exists (orchestrator.ts), but confirmed sibling entry points bypass it at the audited commit.
Total exposure and leveragePresentsrc/trading/risk.ts enforceExposureLimits() (maxTotalExposure, maxPositionValue per market/outcome) + src/trading/safety.ts (maxConcentrationPct, maxSameDirectionPositions), both invoked from src/risk/engine.ts validateTrade() checks 4 and 5-7.Portfolio-level exposure and concentration limits exist beyond the per-order cap.
Brakes and stops
Global circuit breakerPresentsrc/trading/safety.ts tripBreaker() halts trading on daily loss limit (default $500 or 5%) and max drawdown (default 20%); separate market-condition circuit breaker in src/execution/circuit-breaker.ts and src/risk/circuit-breaker.ts per docs/RISK_MANAGEMENT.md (volatility/liquidity/loss/consecutive-failures/spread trip conditions).Two independent circuit breakers (result-based and market-feature-based) are both wired into the unified risk engine.
Orphaned stop-lossNot verifiedsrc/execution/futures.ts defines FuturesExecutionService.placeStopLoss() / placeTakeProfit(), i.e. exchange-side STOP_LOSS orders are supported (not purely in-memory). Could not confirm within this session's budget whether a stop is placed automatically on every entry, or reconciled/re-verified after a reconnect or process restart.Capability exists at the API level; automatic wiring and restart-survival not verified.
Orderly shutdownPartialsrc/cli/commands/gateway.ts registers process.on('SIGINT'|'SIGTERM', shutdown) which calls gateway.stop() and process.exit(0). ExecutionService exposes cancelOrder/cancelAllOrders, but no call to them was found inside the shutdown handler itself; gateway.stop() internals are in the gitignored gateway module and were not inspectable.Signals are caught and shutdown is orderly at the process level, but explicit cancellation of open orders on shutdown is not confirmed.
Connection and operation
Websocket and data reconnectionNot verifiedExecutionService interface exposes connectFillsWebSocket/disconnectFillsWebSocket/isFillsWebSocketConnected (referenced in src/trading/orchestrator.ts pass-through list), implying a fills websocket exists, but the reconnect/backoff and HTTP 429 handling logic was not located within this session's time and API-search budget.Not found, not ruled out; needs a follow-up pass on src/execution/index.ts or the exchange adapter files.
Duplicate-process lockAbsentGET https://api.github.com/search/code?q=lockfile+repo:alsk1992/CloddsBot returns 1 match, in scripts/lighter-bridge/bridge.py (an unrelated Python bridge script), not the main daemon/gateway process. No PID-file or single-instance guard was found for the main bot process as of 2026-09-17.Two instances of the gateway could plausibly run in parallel and duplicate orders; not disproven by any evidence found.
Heartbeat and alertsPresentdocs/TELEMETRY.md documents telemetry.getHealth() (healthy/status/uptime) and a Prometheus /metrics endpoint via telemetry.startMetricsServer(9090); dedicated src/alerts/index.ts and src/alerts/realtime.ts modules exist for outbound notifications.Both an externally-pollable health signal and an outbound alerting module exist.
Accounting and reconciliation
Position reconciliation with the exchangePartialGET https://api.github.com/search/code?q=reconcile+repo:alsk1992/CloddsBot returns only 1 hit, inside src/feeds/betfair/index.ts. No general position-vs-exchange reconciliation module was found covering Binance/Bybit/MEXC/Hyperliquid/Solana/Polymarket/Kalshi.Reconciliation, if it exists at all, appears limited to one feed integration, not the whole trading surface.
Fees and funding in the accountingPartialsrc/trading/logger.ts defines PLATFORM_FEES and calculateTradeFees(), applying documented maker/taker bps for polymarket/kalshi/betfair/smarkets/manifold and logging fees/isMaker/makerRebate per trade. src/execution/futures.ts declares a FundingRate type for perpetuals, but funding-rate deduction from realized PnL or position sizing was not confirmed within budget.Prediction-market fees are modeled and logged; futures funding-rate accounting is unverified.
Order rejection handlingPartialsrc/trading/orchestrator.ts guardMethod() wraps every guarded order call in try/catch, logs the error via logger.error and returns a structured {success:false, status:'rejected'} result. No bounded-retry-on-partial-fill logic was located within budget.Rejections are caught, logged and reported cleanly; retry behavior on partial fills is unverified.
Auditable logPresentsrc/trading/logger.ts TradeLogger persists every trade (id, platform, marketId, side, price, size, filled, cost, fees, orderId, status, timestamps) to SQLite via the Database module, with real-time events.A persistent, structured trade log exists and is the basis for PnL/fee reporting.
Security
API key permissionsAbsent.env.example documents trading credentials for Polymarket/Kalshi/Manifold/Metaculus (POLY_API_KEY, POLY_PRIVATE_KEY, KALSHI_API_KEY, etc.) with no instruction to disable withdrawals or restrict the key by IP. Futures-exchange keys (Binance/Bybit/MEXC/Hyperliquid) referenced in src/execution/futures.ts are not documented in .env.example at all.No documentation found instructing users to mint a withdrawal-disabled, IP-restricted key for any supported exchange.
Secrets handlingPresentdocs/SECURITY_AUDIT.md section 4: 'No hardcoded secrets - All from environment'; .env.example centralizes every credential as an env var; section 2.12 documents credentials/escrow keypairs encrypted at rest with AES-256-GCM via CLODDS_CREDENTIAL_KEY / CLODDS_ESCROW_KEY (generated with `openssl rand -hex 32`).Secrets management follows standard practice: env-sourced, encrypted at rest, not committed.
Authenticated remote controlPresentsrc/security/index.ts AccessControl class (allowlist/blocklist) plus PairingManager (6-digit DM pairing code, 5-minute expiry, persisted at ~/.clodds/paired-users.json); imported into src/agents/index.ts for channel message authorization (Telegram/Discord/etc.).A concrete allowlist + pairing mechanism restricts who can command the bot over chat channels.
AI and learning
The model cannot override the brakesPartialThe primary order path (src/trading/orchestrator.ts) forces every guarded ExecutionService call through safety.canTrade()/validateTrade() and the circuit breaker before submission. BUT GitHub issues #126 and #127 (both OPEN, filed at the exact audited commit c930628) document confirmed AI-agent-invoked paths (Drift, Pump.fun, Meteora, the bundled /bf skill, and a direct Opinion-exchange fallback in src/agents/index.ts) that submit orders without going through those checks. https://github.com/alsk1992/CloddsBot/issues/126 , https://github.com/alsk1992/CloddsBot/issues/127The design intent is sound (single gatekeeper), but the model-invoked tool handlers have confirmed, currently-open bypasses.
Model output validationPartialClaude's tool-use API constrains agent output to the declared JSON tool schema (inherent format validation from the Anthropic SDK, imported in src/agents/index.ts). Once a call reaches the guarded path, enforceMaxOrderSize/enforceExposureLimits bound price*size. No dedicated check for 'does this symbol exist on the target exchange' prior to submission was found within budget.Format is validated by the SDK; semantic validation of hallucinated symbols/prices is unverified.
Learns from its mistakesPartialdocs/RISK_MANAGEMENT.md documents a DynamicKelly position-sizing module (src/trading/kelly.ts) that adjusts size from historical P&L, explicitly scoped as check #8 of 10 in the risk engine and marked 'No (adjusts size)' i.e. non-blocking — it cannot override the other deterministic limits.Bounded, deterministic learning of position size exists; no evidence found of the agent rewriting its own strategy or prompts from outcomes, with or without a review gate.
Model poisoningPartialsrc/security/index.ts detectInjection() scans inbound text for SQL-injection, shell-command-injection, XSS and path-traversal patterns and is imported in src/agents/index.ts (`import { ..., detectInjection } from '../security/index'`). docs/SECURITY_AUDIT.md section 4 lists this as part of a 'Security Shield' with explicit 'prompt injection detection'.Classic injection payloads in chat input are screened, but no separate mechanism was found that isolates ingested third-party content (news feeds, tweets) as inert data before it reaches the LLM's decision context, so a natural-language instruction embedded in a news item is not clearly covered.
Behavior without model quota or responseNot verifiedCould not verify within this session's time/budget how the agent behaves when the Anthropic API returns a rate-limit or quota error mid-decision, nor whether a daily token-cost cap exists. Not documented in docs/TELEMETRY.md or docs/AUTHENTICATION.md.Needs a follow-up pass on src/agents/index.ts error handling around the Anthropic SDK calls.

CloddsBot Risk Control Audit — Summary

**What it is:** CloddsBot (alsk1992/CloddsBot on GitHub, MIT license, 2758 stars, TypeScript) is a large, open-source, self-hosted AI trading agent built on Claude. It scans and trades autonomously across prediction markets (Polymarket, Kalshi, Manifold, Metaculus, Betfair, Smarkets, Opinion), crypto futures (Binance, Bybit, MEXC, Hyperliquid) and Solana DeFi (Jupiter, Meteora, Raydium, Orca, Pump.fun, Drift), plus 5 EVM chains.

**Exchanges/markets covered:** 7 prediction-market venues, 4 futures exchanges, ~6 Solana DEX/DeFi protocols, 5 EVM chains — a very wide surface area for a single risk system to guard.

**What is genuinely good:** It has a real, unified risk engine (`src/risk/engine.ts`) running 10 ordered checks per trade: kill switch, circuit breaker, max order size, exposure limits, daily-loss/drawdown/concentration, VaR, volatility regime, and Kelly sizing. Trades are logged to SQLite with fees and timestamps. Credentials are environment-sourced and encrypted at rest (AES-256-GCM). Chat-channel access is gated by an allowlist plus a DM pairing code system. A Prometheus-compatible health/metrics endpoint exists.

**What is missing or broken today:** The single biggest gap is that this well-designed central gate is **provably bypassable at the exact commit audited**. Two GitHub issues (#126 and #127), both still open and filed against this same commit (c930628, current `main` HEAD), document concrete, reproducible bypasses:

Beyond that, no lockfile or single-instance guard was found for the main process (two copies could run and duplicate orders), and no general position-reconciliation-with-exchange module was found outside one Betfair-specific feed. Stop-loss orders can be placed on the exchange (not just tracked in memory), but automatic placement on every entry and survival across restarts was not confirmed. Several other points (websocket reconnection, futures funding-rate accounting, LLM-quota-exhaustion behavior) could not be verified within this session's time and API budget and are marked accordingly rather than guessed.

**Main risk:** A well-built risk engine exists, but it is not the only door to the exchanges — and the side doors are documented, open, and dated at this exact commit.

**Commit audited:** `c930628c47a4a745f497e29035a3b64622f97cc7` (branch `main`, HEAD as of 2026-09-17), matching both the tree fetched via the GitHub API and the commit referenced in issues #126/#127.

Badge for the README

risk controls audit: 6/21 present

<a href="https://saasfactoryagents.com/bots/alsk1992-cloddsbot/"><img src="https://saasfactoryagents.com/bots/alsk1992-cloddsbot/badge.svg" alt="risk controls audit: 6/21 present"></a>

Fixed a control? Request a free re-audit at the new commit.

Exchanges

Also named in the README: binance, bybit, hyperliquid.

Running CloddsBot with real money?

The watchdog runs apart from the bot with a read-only key and alerts you when drawdown, position size or heartbeat cross your limits. Founding price 19 USD/month, early access open.