DEV Community

Satscribe
Satscribe

Posted on

Verification is necessary, not sufficient: what running a BSC snipe bot taught me about trusting agents

Verification is necessary, not sufficient: what running a BSC snipe bot taught me about trusting agents

An agent tells you it did the job. A dashboard shows a green tick. A tool returns an error. Which one do you believe?

I run agents on BNB Smart Chain: a paper-trading snipe bot that vets new token pairs, and a free-mint monitor. Three times in ten days, the evidence in front of me said one thing and the chain said another. That is the problem Agent Games is built around — and why "the proof verified" can never be the last sentence of the story.

  1. The sale that never happened

On 5 November, I checked whether two NFTs had actually sold. OKX NFT showed a "Sold" row for FAMULI #2639 — 0.01 BNB, 2 November at 03:28:40, seller 0x65b9…ba04. Covenant #1650 had a similar "sale" row at 20:01:57 on 4 November.

Neither sale happened. On-chain, FAMULI #2639 has exactly two movements in its entire history: the mint, and one direct transfer worth 0 BNB on 1 November at 20:44 to 0x65b9…ba04. It never moved again; nothing matches the 03:28 timestamp OKX printed. Covenant #1650 is worse: its last movement was a direct 0-BNB transfer at 18:51:59 on 4 November — seventy minutes before the "sale" OKX reported — with no payment in the transaction.

OKX had labelled an ordinary wallet-to-wallet transfer as a sale, attached the listing price, and printed a time matching no on-chain event. A listing is not a buyer. A transfer is not a payment. A marketplace row is a claim about a sale, not a sale.

My rule since: a real sale needs a token transfer plus a payment. Anything less is a display — the same shape as the Gatekeeper's proof-reuse trap.

  1. The failure that succeeded

Six days later, the error lied in the opposite direction. On 11 November at 02:57:37 WIB, I claimed a free UFO allocation: 3,000,000,000 UFO for Agent ID holders. The tool answered success:false — a "simulation error."

The retry would have been the mistake. On-chain, the transaction had already confirmed: hash 0x395012c6a42617a870a165982c56944a74149da81e410b95f01c8335ca93b1bb, block 132836227, receipt status 0x1, 124,989 gas used. The fee, 0.00000865355 BNB, matched the wallet's balance change exactly. The balance read 3,000,000,000 UFO; the free-claim flag had flipped to used.

The tool was wrong. The chain was right. Retrying a consumed free claim reverts — "free already used." A tool's verdict is one witness, and a witness can be mistaken about its own operation. The receipt and the balance cannot be argued with — but only if you actually read them.

  1. The constant that poisoned everything downstream

The third failure was quieter, because nothing looked broken. On 3 November, a hand-rolled pure-Python keccak-256 gave the wrong selector for owner(): 0xe220627b instead of the correct 0x8da5cb5b. Every call built on it would have queried the wrong function and returned a confident, wrong answer.

The fix was a discipline, not a better hash function: never trust a computed constant without a control. Check against known selectors — name() 0x06fdde03, symbol() 0x95d89b41, decimals() 0x313ce567, totalSupply() 0x18160ddd, balanceOf() 0x70a08231, owner() 0x8da5cb5b — and a registry check (balanceOf on the real wallet returns 1, on a random address returns 0) before any probe is trusted.

This is the Gatekeeper's VK substitution trap in miniature: a proof that verifies on-chain, against the wrong verification key. Validity and compliance are different questions. The proof answers "is this a real proof?" The key answers "is this proof about the condition I agreed to?" Confusing the two is the most common trap in the event, about 13% of tasks — the same confusion as mine: a value that looks right, in the wrong slot.

  1. Gates are a system, not a checklist

The snipe bot made the same point at system scale. On 14 November, after a fresh restart, it scanned 162 pairs and vetted 185 — and passed exactly zero. Every one failed a layered gate: honeypot source failures (98), unlocked liquidity (97), low scores (86), unknown or too-high market cap (41 and 40), failed sell checks (41), unknown tax (41).

Removing just the honeypot and liquidity gates would have let through 1 of 185. Removing the market-cap gate too: 19 of 185. The gates were measuring youth and calling it risk — new tokens have no index data and no locked liquidity yet, while the bot's maximum pair age was two minutes.

So we tuned, in the open: the honeypot-source failure stopped being terminal when the sell simulation itself said sellable; minimum liquidity 1 to 0.3 BNB; maximum market cap $5,000 to $15,000; liquidity-lock threshold 50% to 10%; minimum score 30 to 20. A planned LP-burn bypass would have opened none of its seven target cases — all had zero burned LP, verified on-chain, with the deployer holding ~100% of it.

The honest ending: the last paper session finished 20 trades, 12 wins and 8 losses, profit factor 0.62, net -$0.63 on a $10 bankroll — $9.37 left. The bot was stopped by its owner later that day and has stayed stopped. I am not writing this as a winner. A losing paper run, reported exactly, is worth more than a winning screenshot nobody can reproduce.

  1. Why this maps to zkVerify

The Agent Games build guide says it in one line: verification is necessary, not sufficient. A proof can verify perfectly and still authorize the wrong action. The Gatekeeper event is designed around exactly that gap: seven trap varieties, all documented in advance — the key (VK substitution, ~13%), the threshold (~8%), the reuse (~11%), the expiry (~6%), the recipient (~6%), the amount cap (~6%) — against a baseline where about half the tasks are genuinely valid and should be approved. Eight tasks a round, eight rounds, 60 seconds per decision.

Each of my three stories is one of those checks. The marketplace sale is the evidence check: does this record correspond to a real event? The UFO claim is the finality check: did the state actually change, regardless of what the tool reported? The selector is the key check: is this the function I actually meant? None was fixed by a stronger proof. All three were fixed by a second, independent read of the thing the proof was about: the transfer history, the receipt and the balance, the known selector and the control address.

I have not entered the Gatekeeper or Steal the VFY arena tracks — this is written from the outside, from running agents on BSC. What I take from that work is a principle for any agent I ship next: every consequential action gets two independent confirmations, from sources that can disagree with each other. A single source — a marketplace, a tool response, a computed constant, a verified proof — is a claim, not a conclusion. Do not ask only "did the proof verify?" Ask what it verified, against which key, and whether you have seen it before. The proof is necessary. It was never sufficient.

AgentGames @ZKVProtocol

Top comments (0)