feat(decoder): Bancor V3 BancorNetwork trade() decoder + protocol tagging - #157
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Live mainnet smoke (10-min, ran on this branch)
What this validates
What it does NOT validate
RecommendationMerge as-is. Confidence the decoder works comes from the 2 unit tests against real ABI shapes ( |
Adds Bancor V3 to the mempool decoder coverage matrix. Unlike Curve, Bancor swaps go through a single router (`BancorNetwork` at 0xeEF417e1...), so the existing router-filter model fits without modification — Bancor's router address joins the default filter and both trade flavours decode cleanly: * `tradeBySourceAmount(sourceToken, targetToken, sourceAmount, minReturnAmount, deadline, beneficiary)` — most common shape * `tradeByTargetAmount(sourceToken, targetToken, targetAmount, maxSourceAmount, deadline, beneficiary)` — surfaces the target amount as `amount_in` so the predictor has a real magnitude Same scope cut as the Curve PR: decoder + protocol tagging now, post- state scan integration deferred (the existing `BancorPool` predictor needs a `predict_post_state_with_fallback` hook + a Bancor variant on `PredictedPostState` + `unified_to_post_reserves` before cycles can flow through the simulator). * `Protocol::BancorV3` enum variant * `PROTOCOL_BANCOR` writer wire label (paired with the existing `PROTOCOL_CURVE` reserved constant) * Bancor router added to `default_router_addresses` so Alchemy actually delivers these txs * Pipeline arms across `decoder_protocol_to_type`, `decoder_protocol_label`, `protocol_label`, plus early-return at `try_post_state_scan` with `bancor_post_state_pending` skip reason * 2 unit tests covering both trade shapes
cc38bbb to
d449ec1
Compare
Summary
Protocol::BancorV3enum variant + Bancor V3BancorNetworkcalldata decodertradeBySourceAmount(commit source, accept min target) +tradeByTargetAmount(commit target, pay max source)0xeEF417e1D5CC832e619ae18D2F140De2999dD4fB) joinsdefault_router_addresses— Alchemy now actually forwards Bancor traffic to usPROTOCOL_BANCORwriter wire label registered so the schema stays pinnedprotocol="bancor_v3"on every mempool metricWhy
Bancor V3 has been in our
ProtocolTypeenum +BancorPoolpredictor for months, but the decoder rejected every Bancor calldata path withUnknownSelector. This unblocks the observability for Bancor's BNT-intermediary swap volume — small relative to Uni V2/V3 but real and currently invisible.Files Changed
crates/pools/src/router_decoder.rsProtocol::BancorV3variant,IBancorNetworksol! interface,try_bancordispatch, 2 unit testscrates/ingestion/src/mempool.rsdefault_router_addressescrates/grpc-server/src/mempool_writer.rsPROTOCOL_BANCORwire label constant (paired with the existing reservedPROTOCOL_CURVE)crates/grpc-server/src/mempool_pipeline.rsdecoder_protocol_to_type,decoder_protocol_label,protocol_label. Early-return attry_post_state_scantop withbancor_post_state_pendingskip reasonImplementation notes
BancorNetworkrouter — fits the existing decoder model without needing a parallel "pool-direct" code path.token_inandtoken_outcome from calldata directly (sourceToken/targetTokenargs), no registry resolution needed.DecodedSwapbody.tradeByTargetAmountputs the user-committed target amount inDecodedSwap.amount_inand the source ceiling inamount_out_min. Semantics slightly differ from the source-amount path but both numbers are real magnitudes — the upstream predictor gets actionable signal either way.fee_bps = 0for Bancor in the decoded swap. Bancor's fee is applied per-leg through the BNT intermediary and isn't visible in calldata; the predictor reads the on-chain fee from pool state.Scope cut
Same as Curve PR #156. The follow-up PR needs:
predict_post_state_with_fallbackBancor arm (BancorPool currently has no analytical post-state hook through the unified fallback API)PredictedPostState::Bancor { reserve_in, reserve_out }variant inmempool_writerunified_to_post_reservesBancor arm in pipelineSplitting keeps each review surface ~150 LOC instead of ~500.
Acceptance criteria
tradeBySourceAmountdecodes with correct token + amounttradeByTargetAmountdecodes with target asamount_in, max source asamount_out_minaether_pending_dex_tx_total{protocol="bancor_v3"}instead ofdecode_failureaether_mempool_predictionsrows persist withprotocol="bancor"once writer is reached (writer constant pinned, pipeline label wired)aether_pending_arb_candidates_total(follow-up)Test plan
cargo build --releasecleancargo clippy --all-targets -- -D warningscleancargo test --workspace --release -- --test-threads=1all greenrouter_decoder::tests::decode_bancor_*covering both trade shapesgo build ./...+go test ./... -count=1green (no Go changes, regression check)aether_pending_dex_tx_total{protocol="bancor_v3"}should increment within an hour (Bancor volume is lower than Uniswap; expect ≥ 1 per few-min window)