Every number below came from a run against a live surfpool mainnet fork — no signature,
no broadcast, $0. A fork is not mainnet, and compute units vary per run. The commands to
reproduce each one are in proofs.
Pump.fun — the account that exists only in prose
Before. An agent reads the IDL, assembles the sixteen accounts it names, and submits a buy. The transaction reverts:AccountNotInitialized (3012). The buyer has never held
this token, so their token account doesn’t exist yet — and nothing in the schema says it
must. The agent had no way to know, and only one way to find out.
A sell is worse. It reverts with InvalidBondingCurveV2 (6074) after transferring the
tokens. The account it’s missing, bonding_curve_v2, is required — but it appears nowhere
in the IDL’s account list. It’s mentioned once, in a sentence, in a doc comment.
After. Gecko recovers that account’s derivation and reads the buyer’s state to decide
whether the token account needs creating. It also reads a boolean at byte 82 of the bonding
curve to know whether this is a cashback coin — which changes the account count from 16 to
17. The plan is handed to the builder, simulated, and comes back:
Meteora DLMM — the pool that couldn’t be found
Before. The agent asks the builder to derivelb_pair, the pool account every swap
starts from. The answer: “no PDA seeds.” Not a wrong address — no address at all. The
seed recipe uses a helper function, and Anchor’s IDL format has no slot for that
(issue #4057, confirmed by a
maintainer). Nothing downstream can be derived, so nothing can be built.
There was a second, quieter problem. The pool derivation gained a fourth seed in 2024.
A tool using the old three-seed recipe doesn’t error — it derives a different pool, silently.
After. Gecko recovers the seed recipe from the SDK source, including the fourth seed,
and derives the pool that actually holds the liquidity. Then it reads the pool’s liquidity
bitmap to select which bin arrays the swap will cross — the obvious guess (the active bin
and its neighbours) points at accounts that don’t exist. Wrap, swap, unwrap:
ORE — when the published spec disagrees with the program
Before. ORE is built with Steel, not Anchor, so there is no generated IDL. The project publishes one by hand, and the builder serves it. An agent following it produces a transaction that transfers the tokens and then dies:writable privilege escalated.
The published spec marks the board account read-only. The deployed program writes to it.
We checked the last 193 mainnet instructions of one kind: 193 of 193 carried two
accounts the spec doesn’t list. An argument is missing entirely. A struct is 208 bytes off.
This is the sharpest version of the problem, because nothing here is fixable by reading
more carefully. A valid document can disagree with reality, and only reality settles it.
After. Gecko takes the account roles from the deployed program’s source, corrects the
metadata the spec got wrong, and refuses to plan a claim for an authority the program will
reject rather than hand back something that looks fine and isn’t:
MetaDAO — nothing to derive at all
Before. The builder’s PDA finder returns zero accounts for this program. Not partial — none. The published IDL carries no seed recipes, so an agent cannot construct the call in the first place. There’s no revert to debug, because there’s no transaction to submit. After. Gecko recovers all three account derivations from the deployed program’s source and assembles the full account set. Then something honest happened: the naive path also lands here. Once the accounts are filled in, the raw instruction succeeds — this funder already held the token account, and the program creates its own funding record. MetaDAO’s gap isn’t a missing prelude. It’s that you cannot derive the accounts at all.What actually changed
Not the model. Not the agent. Not anyone’s API. The information the call was built from — and the chance to try it before it counted.
Every account in those plans carries where it came from —
extracted from the published
surface, recovered from program source, or flagged when we genuinely don’t know. A
flagged account is never guessed.
Gecko comprehends the call. Orquestra builds
the transaction. A vault signs it. We never hold a key, never sign, and never broadcast —
the simulation runs on an unsigned transaction, which is the whole point.