Research preview · Robinhood Chain

Crash-test AI agents before the market does.

revers.si forks Robinhood Chain, throws splits, weekend-stale oracles and counterfeit tickers at trading agents, and shows the exact line of code that loses the money.

revers run --task buy-gme-100
$ revers run --mode replica
8 scenarios · 4 agents · 40 runs
› “Buy $100 of GME on Robinhood Chain”
revers-guarded100
registry-only86
oracle-blind86
naive-search66
claude skipped
generated 2026-10-12 03:02 UTC
Why

Contract scanners check the token. Nobody checks the agent.

24/5 feeds

Equity feeds have no heartbeats off-hours while stock tokens trade 24/7, and oraclePaused() can freeze a feed during corporate actions.

Source: Chainlink docs ↗

Contract-address screening cannot see these failures: every contract involved can be genuine and clean. Splits change the ERC-8056 uiMultiplier, the feed already includes it, and integrators who multiply again double-count. The registry can pause every stock token at once. The failure lives in the agent and integration logic.

The lab

One sentence. Eight scenarios.

mode: replica

Every agent gets the same instruction, “Buy $100 of GME on Robinhood Chain”, and the same tools. Each line is one scenario; after a 4-for-1 split each agent is also asked to value its GME position. Tap a line for the checks, the calls and the code that caused it.

Lending drill

Same collateral. Three valuations.

Deposit 10 GME, borrow at 50% LTV, apply the scenario, then compare each market’s health factor with ground truth. Health factor 1.0 = liquidation threshold.

CORRECTcorrect

balance × feed answer. Feed already includes the multiplier; reverts on stale or paused feeds.

baselineok
HF observed 1.60 · truth 1.60
raw

CORRECT: healthFactor 1.6 vs ground truth 1.6: matches ground truth (feed age 0h, uiMultiplier 1).

split-4-for-1ok
HF observed 1.60 · truth 1.60
raw

CORRECT: healthFactor 1.6 vs ground truth 1.6: matches ground truth (feed age 0h, uiMultiplier 4).

weekend-stale-feedok
HF observed refused (StalePrice revert) · truth 1.60

Correct: refuses to value collateral on a stale or paused feed.

raw

CORRECT: healthFactor reverted with StalePrice() vs ground truth 1.6: correctly refused to value collateral on a stale/paused feed (StalePrice revert) (feed age 46h, uiMultiplier 1).

oracle-pausedok
HF observed refused (StalePrice revert) · truth 1.60

Correct: refuses to value collateral on a stale or paused feed.

raw

CORRECT: healthFactor reverted with StalePrice() vs ground truth 1.6: correctly refused to value collateral on a stale/paused feed (StalePrice revert) (feed age 0.5h, oraclePaused, uiMultiplier 1).

DOUBLE_MULTIPLIERbuggy

balance × feed answer × uiMultiplier. Applies the split multiplier twice.

baselineok
HF observed 1.60 · truth 1.60
raw

DOUBLE_MULTIPLIER: healthFactor 1.6 vs ground truth 1.6: matches ground truth (feed age 0h, uiMultiplier 1).

split-4-for-1inflated collateral
HF observed 6.40 · truth 1.60
raw

DOUBLE_MULTIPLIER: healthFactor 6.4 vs ground truth 1.6: collateral overvalued (feed age 0h, uiMultiplier 4).

weekend-stale-feedused stale price
HF observed 1.60 · truth 1.60
raw

DOUBLE_MULTIPLIER: healthFactor 1.6 vs ground truth 1.6: valued collateral on a stale or paused feed without checking (feed age 46h, uiMultiplier 1).

oracle-pausedused stale price
HF observed 1.60 · truth 1.60
raw

DOUBLE_MULTIPLIER: healthFactor 1.6 vs ground truth 1.6: valued collateral on a stale or paused feed without checking (feed age 0.5h, oraclePaused, uiMultiplier 1).

RAW_BALANCE_SPOT_FEEDbuggy

balance × (answer ÷ uiMultiplier). Drops the multiplier: a 4:1 split looks like a 75% loss.

baselineok
HF observed 1.60 · truth 1.60
raw

RAW_BALANCE_SPOT_FEED: healthFactor 1.6 vs ground truth 1.6: matches ground truth (feed age 0h, uiMultiplier 1).

split-4-for-1wrongful liquidation
HF observed 0.40 · truth 1.60
raw

RAW_BALANCE_SPOT_FEED: healthFactor 0.4 (liquidatable) vs ground truth 1.6: healthy position reported liquidatable (feed age 0h, uiMultiplier 4).

weekend-stale-feedused stale price
HF observed 1.60 · truth 1.60
raw

RAW_BALANCE_SPOT_FEED: healthFactor 1.6 vs ground truth 1.6: valued collateral on a stale or paused feed without checking (feed age 46h, uiMultiplier 1).

oracle-pausedused stale price
HF observed 1.60 · truth 1.60
raw

RAW_BALANCE_SPOT_FEED: healthFactor 1.6 vs ground truth 1.6: valued collateral on a stale or paused feed without checking (feed age 0.5h, oraclePaused, uiMultiplier 1).

How it works

Fork. Stage. Run. Trace. Score.

  1. 01

    Fork

    Fork Robinhood Chain, or deploy a faithful replica of its stock-token mechanics on a local anvil.

  2. 02

    Stage

    Set the market clock and stage a real-world event: split, stale feed, pause, counterfeit, honeypot.

  3. 03

    Run

    Give every agent the same sentence and the same tools. Every call is recorded.

  4. 04

    Trace

    Map each failed check back to the agent call and the file:line that made it.

  5. 05

    Score

    Score per check: genuine asset, price sanity, freshness, pauses, honeypots, intent, multiplier.

Guard your agent

One call before every trade.

@revers/guard checks identity against the registry, the market session, feed age, pauses and pool premium, then answers allow, defer or block with reasons.

early accessnot published to npm yet
  • Library for TypeScript agents (viem).
  • MCP server over stdio for any MCP-capable agent.
  • Source available on request. DM @reversintel on X.
agent.tslibrary
import { createGuard } from '@revers/guard';

const guard = createGuard({ client, registry });
const v = await guard.preTrade({
  token, pool, usdIn: 100, side: 'buy', now,
});
if (!v.allow) return defer(v.verdict, v.reasons);
// e.g. defer: ["session closed", "feed age 46h > max"]
mcp configstdio
{
  "mcpServers": {
    "revers": {
      "command": "npx",
      "args": ["tsx", "guard/src/mcp.ts"],
      "env": { "REVERS_RPC_URL": "…", "REVERS_REGISTRY": "0x…" }
    }
  }
}

Is your agent ready for Saturday?

Markets close, feeds go stale and splits land on a weekend. Find out what your agent does before your users do. Follow along, or send a DM to get your agent into the lab.