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.
- 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.
- 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.
- 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.
- 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.
- 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.
Top comments (0)