tx-preflight: simulate a Solana transaction and report its observed effect - #137
Open
ace-coderr wants to merge 6 commits into
Open
tx-preflight: simulate a Solana transaction and report its observed effect#137ace-coderr wants to merge 6 commits into
ace-coderr wants to merge 6 commits into
Conversation
ace-coderr
marked this pull request as ready for review
July 25, 2026 02:09
18 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
tx-preflight — simulate a Solana transaction and report its observed effect before a human approves it.
📹 Demo (2 min): https://youtu.be/X8s-na4zFj8
What this is
A T1 tool plugin that answers one question before a human approves a transaction: what will this actually do?
An agent that builds a transaction and asks for approval hands the human a description the language model wrote. Poison the model and the approval card reads "refund the customer 25 USDC" while the bytes underneath move 2,140 and install a delegate.
tx-preflightsimulates against the operator's own RPC and reports the observed effect — net amounts, authority grants, accounts closed — checked against limits declared in config.Holds no key. Signs nothing. Submits nothing.
Verified on the real runtime
Not just unit-tested. Installed and driven by a live agent on ZeroClaw 0.8.3 against devnet:
The full transcript is in the README; the demo video shows both live.
Notes for reviewers
First tool plugin to declare
http_client. Every HTTP plugin in the repo is a channel, andredact-textmakes no network calls, so this linker path had never been exercised. It works —runtime.rs::create_plugincallswith_granted_http()and selectstool_linker_http()— flagging in case that was unintentional rather than deliberate.A
wasi:httpbug found by running it. Anhttps://URL with no explicit port fails from inside a plugin: the scheme's default port doesn't survivewaki→wasi:http→default-send-request, so the request dials 80 and is refused before TLS, surfacing asErrorCode::ConnectionRefused(the catch-all — looks exactly like the endpoint being down). Bisected against the host's ownhttp_requesttool, which works either way, so it's specific to the plugin sandbox. Reported in#solana-bounty;tx-preflightnormalises the URL so operators don't hit it.Two undocumented install prerequisites, also found the hard way and now in the README: the standard host build has no
pluginsubcommand (needs--features plugins-wasm-cranelift), andplugins.enableddefaults to false so an installed plugin's tools never reach the agent.Guardrails live in
__config, deliberately. The protected wallet, the RPC endpoint, and every spending limit are read from the host-injected config, never fromexecuteargs — the runtime strips caller-supplied__configfirst, so a poisoned agent can't name its own wallet and collect a clean PASS on a drain. A mistypedowner_pubkeyfails closed rather than passing everything. Both have tests.solana-sdkdoesn't build forwasm32-wasip2inside a WIT component, so the wire format is decoded by hand incupel-core(MIT/Apache-2.0, published, no path deps): legacy and v0 messages, address lookup tables, SPL Token and Token-2022 layouts. 85 tests, all offline. Reusable by any other Solana plugin in this repo.Fails closed everywhere. Decode failure, unreachable RPC, unresolvable lookup, malformed config, a transaction that wouldn't land, and an owner mismatch all produce the same verdict word. Output is capped at ~160 tokens.
Scope: one component, not three
The brief suggests 1–3 components. This is one, on purpose.
spl-transfer-buildandsolana-pay-requestare both in the brief and both would have been straightforward, but neither strengthens the argument this PR makes. A verifier that a stranger can install, that catches a real attack on a live chain, and that fails closed everywhere is worth more than three plugins that demo once. Depth over breadth was the deliberate call.Checklist
tx-preflight— host tests (16), both clippy gates,wasm32-wasip2release build, all--lockedcupel-corepublished to crates.io (85 tests)Built against
wit/v0ate112ce6. Happy to rebase if the ABI moves.