feat(hindsight): solver-first decoding - #431
Draft
tamaralipows wants to merge 7 commits into
Draft
Conversation
The headline verdict and every dashboard number compare gross amounts since July; the net-of-gas figures were secondary record columns with no consumer. Removed end to end: the trader-paid gas derivation, the solver-frame gas isolation from the trace, the settled_gas trade field, the settled_gas_cost / settled_amount_out_net_gas / net_bps record columns, and the gas-to-token price conversion. The report's per-trade and per-group bps switch to the gross delta (raw_bps), which every recorded dataset already carries. Fynd's own quotes stay gas-aware; this removes only the settled-side bookkeeping. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One debug_traceBlockByNumber call replaces the per-transaction debug_traceTransaction wave. A transaction the tracer cannot process still costs only that trade; a failure of the whole call is the block's error.
SolverKnowledge becomes SolverDecoder — one trait per solver for its calldata reads, veto, and integrator tag. The implementation is joined onto the registry's solver entry when the address book loads; trade-time lookups go through Registry::solver by address. The per-method name-dispatch functions are deleted.
The declared decode — the trade as the settling solver's own calldata states it — runs first for every matched transaction, not only Relay's. RelayCalldata is deleted; its logic and guards live venue-agnostic in decoder/declared.rs, with venue fees recorded from address-book data. Netting decoders are the fallback, and every record now carries a decode column: declared (calldata or logs) or netted. The calldata-vs-netting disagreement warning and its second recovery are deleted — declared columns appear only on declared records.
Venue decoders are deleted. A venue is now only its address-book section: entry points and fee collectors feed the shared netting fallback and the fee bookkeeping; solver aliases feed attribution. One netting module replaces the three (sender, venue, intent arms picked by the entry point). CoW settlements decode from the Trade log as declared data. TraderRole, DecodeContext, TradeDecoder, and the receipt-only matching module are deleted — matching now also accepts any transaction whose trace contains a known solver frame. Fee-wallet venue attribution checks wallets in address order, so a trade cut by two venues' wallets resolves the same way on every run.
The report's main results cover only declared records; --include-netted adds the marked netting-fallback trades. Records from datasets written before the decode column existed carry no marker and are always kept.
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.
Inverts the hindsight decoder: a trade's authoritative terms live in the settling solver's own call, so decoding starts there, and the venue is attributed afterwards as a label. Supersedes #428.
The pipeline now
eth_getBlockReceiptscall plus onedebug_traceBlockByNumbercall. The RPC must supportdebug_traceBlockByNumber.Tradelog) and anchors the settled output at the declared recipient's ledger receipt; it runs for every matched transaction, not only Relay's. Balance netting is the fallback, and its records are marked.What this changes structurally
SolverDecodertrait per solver (declared swap, output recipient, veto, integrator tag), joined onto the registry's solver entry at address-book load. Trade-time lookups are by address; no name is matched on a hot path.decode:"declared"(calldata/logs — trusted) or"netted"(fallback — an unaccounted fee can sit inside the amounts). The report covers declared records by default;--include-nettedadds the marked tier. All other wire fields are unchanged.min_amount_out,declared_quote,quote_timestamp) appear only on declared records.Verification
Decoded mainnet blocks 25741800–25741815 on this branch and on the base branch: all 87 base trades reproduce with identical tokens, amounts, sender, venue, and solver; this branch adds 9 trades the base could not match (known solver frames inside unknown wrappers). Tier split: 35 declared, 61 netted. 253 unit tests, clippy clean.
Design notes:
.claude/plans/solver-first-decoding.md.