Skip to content

Fix Uniswap V4 swap direction logic and Angstrom evt_index mismatch#9680

Open
bh2smith wants to merge 8 commits into
mainfrom
fix/uniswap-v4-buy-sell-direction
Open

Fix Uniswap V4 swap direction logic and Angstrom evt_index mismatch#9680
bh2smith wants to merge 8 commits into
mainfrom
fix/uniswap-v4-buy-sell-direction

Conversation

@bh2smith
Copy link
Copy Markdown
Member

@bh2smith bh2smith commented May 18, 2026

Summary

Two fixes for Uniswap V4 dex.trades accuracy:

1. Defensive fix to V4 swap direction logic (uniswap_compatible_trades.sql)

Use Swap event amounts (e.amount0) instead of call output (c.amount0) for buy/sell direction, and add OR e.amount1 > INT256 '0' condition.

In V4, afterSwap hooks can modify the BalanceDelta after the Swap event is emitted but before the call returns. Using event amounts is more reliable because they reflect the core swap before hook adjustments. The extra OR condition handles edge cases where amount0 == 0 (hooks absorbing the full counterparty amount).

2. Fix Angstrom bundle orders evt_index (angstrom_all_trades.sql)

The angstrom_bundle_orders macro generated synthetic evt_index values via ROW_NUMBER() (1, 2, 3...) instead of the actual Swap event log index. This caused Angstrom swaps in dex.trades to be unmatchable by evt_index with other systems that reference the real event index.

Root cause investigation: A comparison query joining the dex trade stream with dex.trades on (block_number, tx_hash, evt_index) showed all Angstrom V4 swaps as "missing" — the synthetic evt_index never matched the real one.

Verified with transactions:

  • 0xbc49c090...: real evt_index=2, dex.trades had evt_index=1
  • 0x5ab46bde...: real evt_index=3,4, dex.trades had evt_index=1,2

Fix: Join bundle_orders with PoolManager_evt_Swap on (tx_hash, pool_id) to resolve the real evt_index, falling back to the synthetic value for orders without a corresponding Swap event (e.g. off-chain matched user orders).

Affected models

  • uniswap_compatible_v4_trades macro — used by all 15 chain-specific V4 base_trades models
  • angstrom_all_trades macro — used by angstrom_ethereum_base_trades

Test plan

  • Verify Angstrom swaps in dex.trades now have correct evt_index matching Swap event logs
  • Re-run comparison query (dune.com/queries/7527524) — Angstrom rows should no longer appear as "missing"
  • Spot-check non-Angstrom V4 trades for regression
  • CI dbt slim build passes

Closes SIM-5858

Use Swap event amounts instead of call output (output_swapDelta) for
buy/sell direction. In V4, afterSwap hooks can modify the BalanceDelta
after the Swap event is emitted but before the call returns, causing
output_swapDelta to have different signs than the event amounts. This
reverses token_bought/token_sold on pools with active afterSwap hooks.

Also adds an `OR amount1 > 0` condition to handle edge cases where
amount0 is zero (e.g. hooks absorbing the full counterparty amount).
@github-actions github-actions Bot marked this pull request as draft May 18, 2026 07:22
@github-actions github-actions Bot added WIP work in progress dbt: dex covers the DEX dbt subproject labels May 18, 2026
@bh2smith bh2smith requested review from helanto and jeff-dude May 18, 2026 07:22
The angstrom_bundle_orders macro generated synthetic evt_index values
via ROW_NUMBER() instead of using the actual PoolManager Swap event
log index. This caused dex.trades rows for Angstrom swaps to have
evt_index values (1, 2, ...) that didn't match the real event indices,
making it impossible to join with other systems that reference the
actual evt_index.

Fix: join bundle_orders with PoolManager_evt_Swap on tx_hash + pool_id
(maker) to resolve the real evt_index, falling back to the synthetic
value for orders without a corresponding Swap event.
@bh2smith bh2smith changed the title Fix Uniswap V4 buy/sell token reversal on hooked pools Fix Uniswap V4 swap direction logic and Angstrom evt_index mismatch May 18, 2026
bh2smith added 3 commits May 18, 2026 13:30
After resolving real evt_index for bundle_orders, the composable and
bundle paths can produce rows with the same (tx_hash, evt_index) for
swaps that appear in both. Exclude composable rows that have a
matching bundle order, since the bundle path has richer decoded data
(taker, LP fees, protocol fees).

Fixes CI: 362 unique key violations on angstrom_ethereum_base_trades.
The NOT EXISTS anti-join caused Trino to inline bundle_with_real_evt_index
twice, doubling the nested bundle decoding pipeline and pushing the query
to 801 stages (limit 500). Replace with a single-pass UNION ALL + ROW_NUMBER
dedup that references each CTE only once, preferring bundle rows over
composable rows on (tx_hash, evt_index) collision.
@bh2smith bh2smith marked this pull request as ready for review May 18, 2026 13:31
@github-actions github-actions Bot added ready-for-review this PR development is complete, please review and removed WIP work in progress labels May 18, 2026
bh2smith and others added 3 commits May 19, 2026 09:39
Use event amounts for direction (immune to afterSwap hook modifications)
but call output amounts for values (includes hook adjustments, avoids
zero-amount rows). Token addresses still use event-based direction.

This resolves the regression where 5% of Ethereum rows had bought=0 or
sold=0 due to using event amounts that reflect the core swap before hook
adjustments zeroed out one side.
Enables partition pruning on PoolManager_evt_Swap during full builds.
tx_hash functionally determines block, so output is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@jeff-dude jeff-dude self-assigned this May 19, 2026
@jeff-dude jeff-dude added ready-for-merging and removed ready-for-review this PR development is complete, please review labels May 19, 2026
@jeff-dude
Copy link
Copy Markdown
Member

i'll deploy when we have the env ready ✅

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

Labels

dbt: dex covers the DEX dbt subproject ready-for-merging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants