Skip to content

feat(pools): Balancer V2 pool pricing via queryBatchSwap (Phase 1, draft) - #10

Draft
jenish-25 wants to merge 9 commits into
cakevm:mainfrom
jenish-25:feat/balancer-v2-pool
Draft

feat(pools): Balancer V2 pool pricing via queryBatchSwap (Phase 1, draft)#10
jenish-25 wants to merge 9 commits into
cakevm:mainfrom
jenish-25:feat/balancer-v2-pool

Conversation

@jenish-25

Copy link
Copy Markdown

Summary

Adds a BalancerV2Pool that implements the Pool trait and prices swaps by simulating the Balancer Vault's queryBatchSwap inside revm — modeled on the existing CurvePool (EVM-simulation) pattern rather than porting Balancer's weighted/stable math to Rust.

PoolProtocol::BalancerV2 / PoolClass::BalancerV2 already existed and the Vault ABI was already vendored (used for flash loans); this wires them up for pricing.

Scope: Phase 1 (pricing & detection) only. Execution (multicaller opcode encoder + on-chain Vault routing) is intentionally deferred — get_abi_encoder returns None for now.

What's included

  • crates/defi/pools/src/balancerv2pool.rsBalancerV2Pool + Pool impl
    • calculate_out_amount / calculate_in_amount build a single-hop queryBatchSwap (GIVEN_IN / GIVEN_OUT) and run it against the state DB via evm_call, decoding the int256[] deltas
    • get_state_required adds a representative queryBatchSwap per direction so the prestate tracer captures Vault + pool storage (singleton-Vault layout)
  • crates/defi/abi/src/balancer/pool.rs — minimal IBalancerV2Pool interface (getPoolId, getSwapFeePercentage); #[sol(rpc)] added to the Vault interface for fetch_pool_data
  • crates/defi/address-book — Balancer V2 Vault address constant

Status — draft, not yet ready to merge

Opening as a draft for early feedback on the approach. Two things outstanding:

  1. Pricing path not yet verified against a live chain. The fork integration test (test_balancer_v2_pool, #[ignore]) is compile-checked but hasn't been run against an archive node yet. The open question is whether queryBatchSwap returns int256[] cleanly under evm_call or reverts-with-data in query mode — the decode may need adjusting once run.
  2. Pool discovery is not wired into the loader graph — a BalancerV2Pool is constructible and priceable, but I deferred the discovery mechanism (dedicated loader vs. config-based) pending a preference.

Happy to adjust the approach, split it up, or hold it — feedback welcome.

Test Plan

  • cargo build on affected crates
  • Unit tests: queryBatchSwap calldata roundtrip + delta-sign decoding
  • clippy clean on the new file; formatting clean
  • Run test_balancer_v2_pool against a mainnet archive node (MAINNET_WS) to confirm the pricing path end-to-end
  • Wire pool discovery once the mechanism is agreed

@jenish-25

Copy link
Copy Markdown
Author

Design discussion and open questions: #11

@jenish-25

Copy link
Copy Markdown
Author

Heads up on the failing checks — they're pre-existing on main, not introduced by this change:

  • cargo deny check: fails to parse a malformed upstream advisory (RUSTSEC-2026-0124.md, TOML parse error in the RustSec DB) — unrelated to this repo's dependencies. This PR changes zero dependencies.
  • make clippy: nightly clippy::unnecessary_sort_by now errors on pre-existing kabu-strategy-merger code under -D warnings. Fixed separately in fix(merger): use sort_by_key to satisfy clippy::unnecessary_sort_by #12.
  • make test / make swap-test-all: need node access (MAINNET_WS) that isn't available to fork PRs via pull_request_target.

For reference, the README-only PR #88 fails the same four jobs, and main's CI is currently red for the same reasons.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant