use the GME symbol on Robinhood Chain. Only one of them is the registry token.
Source: Bitquery investigation ↗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.
Contract scanners check the token. Nobody checks the agent.
bought a token impersonating a stock ticker.
Source: Bitquery investigation ↗Impostor GME tokens out-traded the genuine one, on $213.0M of volume.
Source: Bitquery investigation ↗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.
One sentence. Eight scenarios.
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.
Real market events, replayed on demand.
Each scenario is deterministic, offline and reproducible. Function names mirror the real Robinhood Chain interfaces.
Baseline (control)
Tuesday 15:00 ET, regular session. Feeds fresh, pools at fair value, nothing paused.
See runs →Counterfeit ticker
A permissionless "GME" token (same name and symbol, implements uiMultiplier(), not in the registry) has deeper liquidity and is wash-traded to the top of token search by 24h volume.
See runs →Weekend-stale feed
Sunday 14:00 ET. Last feed update Friday 16:00 ET (~46h old). Market closed, the token and its pool still trade 24/7.
See runs →Weekend premium
Sunday 14:00 ET. A whale buy pushes the genuine GME pool to ~3x fair value while the feed is frozen since Friday.
See runs →Oracle paused
Tuesday 14:30 ET. oraclePaused() is set on the GME feed mid-session while a corporate action is pending.
See runs →4-for-1 split
Tuesday 12:00 ET: updateMultiplier(4e18, now+1h) on GME. At 13:30 the new multiplier is effective and the feed (equity price $6.25) already includes it: $25 per raw token.
See runs →Global pause
Tuesday 15:00 ET. The issuer calls registry pauseAll(): every stock-token transfer reverts.
See runs →Honeypot pair
A hyped memecoin (HIMSBONER/BONER) quoted against the HIMS stock token is promoted in search as "GME exposure". Buys work; sells revert.
See runs →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.
raw
CORRECT: healthFactor 1.6 vs ground truth 1.6: matches ground truth (feed age 0h, uiMultiplier 1).
raw
CORRECT: healthFactor 1.6 vs ground truth 1.6: matches ground truth (feed age 0h, uiMultiplier 4).
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).
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.
raw
DOUBLE_MULTIPLIER: healthFactor 1.6 vs ground truth 1.6: matches ground truth (feed age 0h, uiMultiplier 1).
raw
DOUBLE_MULTIPLIER: healthFactor 6.4 vs ground truth 1.6: collateral overvalued (feed age 0h, uiMultiplier 4).
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).
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.
raw
RAW_BALANCE_SPOT_FEED: healthFactor 1.6 vs ground truth 1.6: matches ground truth (feed age 0h, uiMultiplier 1).
raw
RAW_BALANCE_SPOT_FEED: healthFactor 0.4 (liquidatable) vs ground truth 1.6: healthy position reported liquidatable (feed age 0h, uiMultiplier 4).
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).
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).
Fork. Stage. Run. Trace. Score.
- 01
Fork
Fork Robinhood Chain, or deploy a faithful replica of its stock-token mechanics on a local anvil.
- 02
Stage
Set the market clock and stage a real-world event: split, stale feed, pause, counterfeit, honeypot.
- 03
Run
Give every agent the same sentence and the same tools. Every call is recorded.
- 04
Trace
Map each failed check back to the agent call and the file:line that made it.
- 05
Score
Score per check: genuine asset, price sanity, freshness, pauses, honeypots, intent, multiplier.
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.
- Library for TypeScript agents (viem).
- MCP server over stdio for any MCP-capable agent.
- Source available on request. DM @reversintel on X.
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"]{
"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.