Skip to content

Commit 7409abb

Browse files
thevaizmanclaudetomfutagocursoragent
authored
feat(dex): deterministic 0x Settler aggregator volume — supersede #9795 (CUR2-2844) (#9800)
* feat(dex): add 0x Settler RFQ fills to dex.trades (robust echo-ported decoder, 16 chains) Promotes 0x Settler plain-RFQ (action selector 0xd92aadfb) maker fills into dex.trades as a new PMM venue (project '0x API', version 'settler') across 16 chains. They were previously absent from dex.trades (which only carried the legacy ExchangeProxy decodes). Method, ported from Dune's echo indexer (zero_ex_settler.rs): - Token identities (maker, makerAsset, takerToken) come from the signed RFQ action's calldata static head; amounts come from the real ERC20 Transfer logs pivoted on the maker, with an exactly-one-per-leg validity gate (drops ambiguous / native-ETH legs). - Identity-grouped maker pivot so distinct fills sharing a byte offset across multiple settler traces in one tx are not collapsed (the naive (tx_hash,p) grouping silently dropped/aliased such fills via arbitrary()). Files: - new macro zeroex_settler_rfq + per-chain zeroex_settler_<chain>_base_trades (16 chains), registered in dex_<chain>_base_trades; dex_info + ethereum seed test added. - settler-txs staging extended to emit tx_from + rfq_input (RFQ-bearing rows only). Verified on-chain (Ethereum + sampled chains): decoder reproduces real fills exactly; 0 overlap with the legacy native 0x venue (no double counting); AMM-routed settler trades correctly excluded (their underlying pool venues already represent them). mode excluded (no dex pipeline). dex_aggregator path unchanged in this PR. CUR2-2843 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * perf(dex): bound dex_base_trades CI full-refresh to 7d to avoid OOM/timeout CI slim-builds full-refresh dex_<chain>_base_trades (the duplicates_rank window over a chain's entire history), exceeding the per-node memory limit on large chains (bnb: 331GB TopN vs 348GB ceiling) and the CI job timeout. Bound the union to the last 7 days in CI only (target=ci); prod (dunesql) is unchanged and keeps the incremental_predicate. Verified no CI test depends on full-history dex_base_trades: aggregate models carry no history-dependent tests (only dex_story's check_dex_info_relationship, which passes on a subset), seed tests query venue models (not the aggregate), and dex_<chain>_trades is out of CI scope. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(dex): dedup 0x Settler RFQ rows on (tx_hash, evt_index) The 0xd92aadfb selector can recur inside an RFQ action's ABI body, so the all-occurrences scan decodes the SAME action twice (identical maker/asset/token) at two byte offsets, both matching the one maker-leg transfer -> duplicate (tx_hash, evt_index). Keep one row per (tx_hash, maker_evt_index) via row_number; genuine distinct fills always have distinct maker-leg logs, so only the spurious re-decode is dropped (verified: the lone ethereum 14d collision was an identical-tuple recurrence at offsets 1093/1125 of tx 0x49da06f1...). Uses a subquery rather than QUALIFY (no precedent for QUALIFY in this codebase). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(dex): deterministic 0x Settler aggregator volume — supersede PR #9795 (CUR2-2844) Replaces the heuristic maker/taker leg-matching (and the PR #9795 5x-divergence band-aid) for 0x Settler trades in dex_aggregator.trades with a deterministic decode. Per settler call, emits one 0x-API aggregator row = the user's net swap: - token_bought = AllowedSlippage.buyToken (from calldata, deterministic). - amount = the unique Transfer(buyToken, to=receiver) when resolvable, else the minAmountOut floor (verified tight, ~1% under actual). receiver = tx-level sender (execute) / msgSender (executeMetaTxn) — verified to be the true buyToken recipient, NOT the calldata recipient (an intermediate routing hop). Anchoring on a single calldata-named token to the verified user means it cannot mis-bind to internal routing hops the way the heuristic did. - token_sold = best-effort (unique Transfer out of the user, token != buyToken). - volume_usd priced via either leg (add_amount_usd), so an unpriced buyToken still values off the sell leg (cuts the unpriced-NULL bucket ~20% -> ~5%). New macro zeroex_settler_agg; settler-txs staging extended with the AllowedSlippage fields (buy_token, min_amount_out, settler_msgsender); all 17 settler chains' zeroex_v2_<chain>_trades rewired to it. Verified on-chain (example 0xf61374… : current $0.75 -> deterministic ~$490). NOTE: requires a coordinated full-refresh of zeroex_v2_<chain>_trades + dex_aggregator_trades (merge cannot delete the old mis-bound rows). Old-vs-new regression to be validated on CI-built tables before merge. Stacked on CUR2-2843 (Phase 1). CUR2-2844 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: tomfutago <tomfutago@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 26df65a commit 7409abb

19 files changed

Lines changed: 301 additions & 783 deletions
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
{% macro zeroex_settler_agg(blockchain, start_date='2024-07-15') %}
2+
{%- if target.name == 'ci' -%}
3+
{%- set start_date = (modules.datetime.date.today() - modules.datetime.timedelta(days=14)).strftime('%Y-%m-%d') -%}
4+
{%- endif -%}
5+
{%- set weth = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' -%}
6+
{%- set native_tokens = '(0x0000000000000000000000000000000000000000, 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee)' -%}
7+
{%- set erc20_transfer_topic = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' -%}
8+
{#- 2^128. minAmountOut at/above this is a "no minimum" sentinel (callers scatter across the top of the
9+
uint256 range, incl. UINT256_MAX), not a real token amount — even a $1B trade is well under 2^128.
10+
The floor fallback must ignore these or it emits absurd volume (e.g. ~1e71 USD). -#}
11+
{%- set max_plausible_amount = '340282366920938463463374607431768211456' -%}
12+
13+
-- Deterministic 0x Settler aggregator decode (replaces the heuristic leg-matching + the PR #9795 band-aid).
14+
-- Per settler call, emits ONE 0x-API aggregator row = the user's net swap:
15+
-- token_bought = AllowedSlippage.buyToken (from calldata, deterministic).
16+
-- token_bought amount = the unique Transfer(buyToken, to=receiver) when resolvable, else the minAmountOut
17+
-- floor (verified tight, ~1% under actual). receiver = the tx-level sender (execute) / msgSender
18+
-- (executeMetaTxn) — verified to be the true buyToken recipient, NOT the calldata `recipient` (which is
19+
-- often an intermediate routing hop). Anchoring on a single calldata-named token to the verified user
20+
-- means it cannot mis-bind to internal routing hops the way the heuristic did.
21+
-- token_sold = best-effort: the unique Transfer(from=receiver, token != buyToken).
22+
-- volume_usd = priced via either leg (add_amount_usd), so an unpriced buyToken still values off the sell leg.
23+
-- NOTE: native-ETH buyToken is mapped to mainnet WETH for pricing, so it only resolves a price on ethereum;
24+
-- per-chain wrapped-native pricing for native buys is a tracked follow-up (off-mainnet native buys -> NULL volume).
25+
26+
WITH settler AS (
27+
SELECT
28+
tx_hash, block_time, block_number, method_id, settler_address, zid, tag, rn, cow_rn,
29+
buy_token, min_amount_out, settler_msgsender
30+
FROM {{ ref('zeroex_v2_' ~ blockchain ~ '_settler_txs') }}
31+
-- exclude the sentinel zid (non-trade fills), matching the zeroex_v2 pipeline this replaces
32+
WHERE zid != 0xa00000000000000000000000
33+
{% if is_incremental() %}
34+
AND {{ incremental_predicate('block_time') }}
35+
{% else %}
36+
AND block_time >= DATE '{{ start_date }}'
37+
{% endif %}
38+
),
39+
40+
-- Distinct partition key of the settler txs, so the transactions/logs scans prune by partition
41+
-- (block_time + block_number + tx_hash) rather than a tx_hash-only post-scan filter, per zeroex_v2.sql's norm.
42+
settler_tx_keys AS (
43+
SELECT DISTINCT block_time, block_number, tx_hash FROM settler
44+
),
45+
46+
-- Tx-level sender/recipient (the settler trace's own `from` is an intermediary for nested/Relay-routed calls).
47+
txs AS (
48+
SELECT t.hash AS tx_hash, t."from" AS tx_from, t."to" AS tx_to
49+
FROM {{ source(blockchain, 'transactions') }} t
50+
JOIN settler_tx_keys k
51+
ON k.block_time = t.block_time
52+
AND k.block_number = t.block_number
53+
AND k.tx_hash = t.hash
54+
{% if is_incremental() %}
55+
WHERE {{ incremental_predicate('t.block_time') }}
56+
{% else %}
57+
WHERE t.block_time >= DATE '{{ start_date }}'
58+
{% endif %}
59+
),
60+
61+
calls AS (
62+
SELECT
63+
s.tx_hash, s.block_time, s.block_number, s.settler_address, s.zid, s.tag, s.rn, s.cow_rn,
64+
-- guard the floor against "no minimum" sentinels (minAmountOut >= 2^128): null them so the
65+
-- fallback yields null volume rather than an absurd amount. real amounts are far below 2^128.
66+
CASE WHEN s.min_amount_out < UINT256 '{{ max_plausible_amount }}' THEN s.min_amount_out END AS min_amount_out,
67+
t.tx_from, t.tx_to,
68+
-- receiver (the user): execute -> tx-level sender; executeMetaTxn -> msgSender (relayer pays gas).
69+
CASE WHEN s.method_id = 0xfd3ad6d4 THEN s.settler_msgsender ELSE t.tx_from END AS receiver,
70+
-- native sentinels represented/priced as WETH (see header note)
71+
CASE WHEN s.buy_token IN {{ native_tokens }} THEN {{ weth }} ELSE s.buy_token END AS buy_token
72+
FROM settler s
73+
LEFT JOIN txs t ON t.tx_hash = s.tx_hash
74+
),
75+
76+
transfers AS (
77+
SELECT
78+
logs.block_number,
79+
logs.tx_hash,
80+
logs.contract_address AS token,
81+
varbinary_substring(logs.topic1, 13, 20) AS transfer_from,
82+
varbinary_substring(logs.topic2, 13, 20) AS transfer_to,
83+
-- CASE-guard the conversion (Trino only evaluates the THEN branch when the WHEN holds): a non-standard
84+
-- Transfer-topic log with >32-byte data would otherwise overflow bytearray_to_uint256. The WHERE filter
85+
-- below is not sufficient on its own — Trino may evaluate this projection before applying it.
86+
CASE WHEN varbinary_length(logs.data) = 32 THEN bytearray_to_uint256(logs.data) END AS amount
87+
FROM {{ source(blockchain, 'logs') }} AS logs
88+
JOIN settler_tx_keys k
89+
ON k.block_time = logs.block_time
90+
AND k.block_number = logs.block_number
91+
AND k.tx_hash = logs.tx_hash
92+
WHERE logs.topic0 = {{ erc20_transfer_topic }}
93+
-- standard ERC20 value transfers only (uint256 amount is exactly 32 bytes): drops NFT/ERC721 (0-byte
94+
-- data) and non-standard >32-byte Transfer-topic logs. Row-reducer; the overflow guard is the CASE above.
95+
AND varbinary_length(logs.data) = 32
96+
{% if is_incremental() %}
97+
AND {{ incremental_predicate('logs.block_time') }}
98+
{% else %}
99+
AND logs.block_time >= DATE '{{ start_date }}'
100+
{% endif %}
101+
),
102+
103+
-- Single pass over the transfers: buy leg = unique Transfer(buyToken, to=receiver); sell leg (best-effort) =
104+
-- unique Transfer out of the user of a token other than buyToken.
105+
legs AS (
106+
SELECT c.tx_hash, c.rn,
107+
count(*) FILTER (WHERE t.token = c.buy_token AND t.transfer_to = c.receiver) AS buy_n,
108+
arbitrary(t.amount) FILTER (WHERE t.token = c.buy_token AND t.transfer_to = c.receiver) AS buy_amount,
109+
count(*) FILTER (WHERE t.transfer_from = c.receiver AND t.token <> c.buy_token) AS sell_n,
110+
arbitrary(t.token) FILTER (WHERE t.transfer_from = c.receiver AND t.token <> c.buy_token) AS sell_token,
111+
arbitrary(t.amount) FILTER (WHERE t.transfer_from = c.receiver AND t.token <> c.buy_token) AS sell_amount
112+
FROM calls c
113+
JOIN transfers t
114+
ON t.tx_hash = c.tx_hash
115+
AND t.block_number = c.block_number
116+
AND t.amount > UINT256 '0'
117+
AND (
118+
(t.token = c.buy_token AND t.transfer_to = c.receiver)
119+
OR (t.transfer_from = c.receiver AND t.token <> c.buy_token)
120+
)
121+
GROUP BY c.tx_hash, c.rn
122+
),
123+
124+
token_metadata AS (
125+
SELECT contract_address, symbol, decimals
126+
FROM {{ source('tokens', 'erc20') }}
127+
WHERE blockchain = '{{ blockchain }}'
128+
),
129+
130+
trades AS (
131+
SELECT
132+
c.block_time, c.block_number, c.tx_hash, c.tx_from, c.tx_to, c.zid, c.tag,
133+
c.rn AS evt_index, c.settler_address AS contract_address, c.receiver AS taker,
134+
c.buy_token AS token_bought_address,
135+
-- CoW-batched settler fills (cow_rn set): tx-level receiver is the CoW solver/settlement, not the user,
136+
-- so the receiver-pivot transfer match is unreliable amid the whole batch's transfers. Fall back to the
137+
-- deterministic minAmountOut floor for the bought leg and leave the sell leg null rather than risk
138+
-- mis-assigning another order's transfer. buyToken itself is still the deterministic calldata value.
139+
CASE WHEN c.cow_rn IS NOT NULL THEN c.min_amount_out
140+
WHEN l.buy_n = 1 THEN l.buy_amount
141+
ELSE c.min_amount_out END AS token_bought_amount_raw,
142+
CASE WHEN c.cow_rn IS NULL AND l.sell_n = 1 THEN l.sell_token END AS token_sold_address,
143+
CASE WHEN c.cow_rn IS NULL AND l.sell_n = 1 THEN l.sell_amount END AS token_sold_amount_raw
144+
FROM calls c
145+
LEFT JOIN legs l ON l.tx_hash = c.tx_hash AND l.rn = c.rn
146+
),
147+
148+
results AS (
149+
SELECT
150+
'{{ blockchain }}' AS blockchain,
151+
trades.block_time, trades.block_number, trades.tx_hash, trades.tx_from, trades.tx_to,
152+
trades.zid, trades.tag, trades.evt_index, trades.contract_address, trades.taker,
153+
CAST(NULL AS varbinary) AS maker,
154+
trades.token_bought_address,
155+
bt.symbol AS bought_symbol,
156+
trades.token_bought_amount_raw,
157+
trades.token_bought_amount_raw / POW(10, bt.decimals) AS token_bought_amount,
158+
trades.token_sold_address,
159+
st.symbol AS sold_symbol,
160+
trades.token_sold_amount_raw,
161+
trades.token_sold_amount_raw / POW(10, st.decimals) AS token_sold_amount
162+
FROM trades
163+
LEFT JOIN token_metadata bt ON bt.contract_address = trades.token_bought_address
164+
LEFT JOIN token_metadata st ON st.contract_address = trades.token_sold_address
165+
),
166+
167+
results_usd AS (
168+
{{ add_amount_usd(trades_cte = 'results') }}
169+
)
170+
171+
SELECT
172+
'{{ blockchain }}' AS blockchain,
173+
'0x-API' AS project,
174+
'settler' AS version,
175+
cast(DATE_TRUNC('day', block_time) as date) AS block_date,
176+
cast(DATE_TRUNC('month', block_time) as date) AS block_month,
177+
block_time,
178+
block_number,
179+
sold_symbol AS taker_symbol,
180+
bought_symbol AS maker_symbol,
181+
CASE WHEN LOWER(sold_symbol) > LOWER(bought_symbol) THEN CONCAT(bought_symbol, '-', sold_symbol) ELSE CONCAT(sold_symbol, '-', bought_symbol) END AS token_pair,
182+
token_sold_amount AS taker_token_amount,
183+
token_bought_amount AS maker_token_amount,
184+
token_sold_amount_raw AS taker_token_amount_raw,
185+
token_bought_amount_raw AS maker_token_amount_raw,
186+
amount_usd AS volume_usd,
187+
token_sold_address AS taker_token,
188+
token_bought_address AS maker_token,
189+
taker,
190+
maker,
191+
tag,
192+
zid,
193+
tx_hash,
194+
tx_from,
195+
tx_to,
196+
evt_index,
197+
(ARRAY[-1]) AS trace_address,
198+
'settler' AS type,
199+
TRUE AS swap_flag,
200+
contract_address
201+
FROM results_usd
202+
{% endmacro %}

dbt_subprojects/dex/macros/models/_project/zeroex/zeroex_settler_txs_cte.sql

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ filtered_traces AS (
3232
WHERE
3333
-- Filter for specific method signatures used by 0x Protocol
3434
(varbinary_position(input,0x1fff991f) <> 0 OR varbinary_position(input,0xfd3ad6d4) <> 0)
35+
-- Exclude reverted settler calls (verified: failed ERC-4337 UserOp-wrapped settler calls that execute
36+
-- no swap and emit no transfers — genuine non-trades). Without this, a reverted call carrying a sentinel
37+
-- minAmountOut reaches the aggregator's floor fallback and emits absurd volume; the RFQ path already
38+
-- drops them via its maker-pivot transfer gate, so this only removes non-trades.
39+
AND success
3540
-- Apply time-based filtering for incremental loads
3641
{% if is_incremental() %}
3742
AND {{ incremental_predicate('block_time') }}
@@ -110,7 +115,13 @@ settler_txs AS (
110115
END AS taker,
111116
-- Keep raw calldata only for RFQ-bearing settler calls (plain RFQ action 0xd92aadfb);
112117
-- consumed by the zeroex_settler_rfq macro. NULL otherwise to avoid bloating the staging table.
113-
CASE WHEN varbinary_position(input, 0xd92aadfb) <> 0 THEN input END AS rfq_input
118+
CASE WHEN varbinary_position(input, 0xd92aadfb) <> 0 THEN input END AS rfq_input,
119+
-- AllowedSlippage fields (present in every execute/executeMetaTxn call, fixed offsets) — used by
120+
-- the deterministic aggregator decode (zeroex_settler_agg): buyToken, minAmountOut, and the
121+
-- executeMetaTxn msgSender (the order signer / fund owner; tx-level from is the relayer there).
122+
varbinary_substring(input, 49, 20) AS buy_token,
123+
bytearray_to_uint256(varbinary_substring(input, 69, 32)) AS min_amount_out,
124+
CASE WHEN method_id = 0xfd3ad6d4 THEN varbinary_substring(input, 177, 20) END AS settler_msgsender
114125
FROM
115126
settler_trace_data
116127
WHERE

dbt_subprojects/dex/models/_projects/zeroex/arbitrum/zeroex_v2_arbitrum_trades.sql

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,8 @@
1010
incremental_predicates = [incremental_predicate('DBT_INTERNAL_DEST.block_time')]
1111
)}}
1212

13-
{% set zeroex_settler_start_date = '2024-07-15' %}
14-
{% set blockchain = 'arbitrum' %}
15-
16-
WITH zeroex_tx AS (
17-
-- Read the pre-materialized settler transactions instead of inlining the
18-
-- zeroex_settler_txs_cte macro, which Trino re-expanded into ~14 arbitrum.traces scans.
19-
select
20-
tx_hash,
21-
block_time,
22-
block_number,
23-
method_id,
24-
contract_address,
25-
settler_address,
26-
zid,
27-
tag,
28-
rn,
29-
cow_rn,
30-
taker
31-
from {{ ref('zeroex_v2_arbitrum_settler_txs') }}
32-
{% if is_incremental() %}
33-
where {{ incremental_predicate('block_time') }}
34-
{% endif %}
35-
),
36-
zeroex_v2_trades AS (
37-
{{
38-
zeroex_v2_trades(
39-
blockchain = blockchain,
40-
start_date = zeroex_settler_start_date
41-
42-
)
43-
}}
44-
),
45-
46-
trade_details as (
47-
{{
48-
zeroex_v2_trades_detail(
49-
blockchain = blockchain,
50-
start_date = zeroex_settler_start_date
51-
52-
)
53-
}}
54-
55-
)
56-
select
57-
*
58-
from trade_details
13+
{{
14+
zeroex_settler_agg(
15+
blockchain = 'arbitrum'
16+
)
17+
}}

dbt_subprojects/dex/models/_projects/zeroex/avalanche_c/zeroex_v2_avalanche_c_trades.sql

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,8 @@
1010
incremental_predicates = [incremental_predicate('DBT_INTERNAL_DEST.block_time')]
1111
)}}
1212

13-
{% set zeroex_settler_start_date = '2024-07-15' %}
14-
{% set blockchain = 'avalanche_c' %}
15-
16-
WITH zeroex_tx AS (
17-
-- Read the pre-materialized settler transactions instead of inlining the
18-
-- zeroex_settler_txs_cte macro, which Trino re-expanded into ~14 avalanche_c.traces scans.
19-
select
20-
tx_hash,
21-
block_time,
22-
block_number,
23-
method_id,
24-
contract_address,
25-
settler_address,
26-
zid,
27-
tag,
28-
rn,
29-
cow_rn,
30-
taker
31-
from {{ ref('zeroex_v2_avalanche_c_settler_txs') }}
32-
{% if is_incremental() %}
33-
where {{ incremental_predicate('block_time') }}
34-
{% endif %}
35-
),
36-
zeroex_v2_trades AS (
37-
{{
38-
zeroex_v2_trades(
39-
blockchain = blockchain,
40-
start_date = zeroex_settler_start_date
41-
42-
)
43-
}}
44-
),
45-
46-
trade_details as (
47-
{{
48-
zeroex_v2_trades_detail(
49-
blockchain = blockchain,
50-
start_date = zeroex_settler_start_date
51-
52-
)
53-
}}
54-
55-
)
56-
select
57-
*
58-
from trade_details
13+
{{
14+
zeroex_settler_agg(
15+
blockchain = 'avalanche_c'
16+
)
17+
}}

dbt_subprojects/dex/models/_projects/zeroex/base/zeroex_v2_base_trades.sql

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,8 @@
1010
incremental_predicates = [incremental_predicate('DBT_INTERNAL_DEST.block_time')]
1111
)}}
1212

13-
{% set zeroex_settler_start_date = '2024-07-15' %}
14-
{% set blockchain = 'base' %}
15-
16-
WITH zeroex_tx AS (
17-
-- Read the pre-materialized settler transactions instead of inlining the
18-
-- zeroex_settler_txs_cte macro, which Trino re-expanded into ~14 base.traces scans.
19-
select
20-
tx_hash,
21-
block_time,
22-
block_number,
23-
method_id,
24-
contract_address,
25-
settler_address,
26-
zid,
27-
tag,
28-
rn,
29-
cow_rn,
30-
taker
31-
from {{ ref('zeroex_v2_base_settler_txs') }}
32-
{% if is_incremental() %}
33-
where {{ incremental_predicate('block_time') }}
34-
{% endif %}
35-
),
36-
zeroex_v2_trades AS (
37-
{{
38-
zeroex_v2_trades(
39-
blockchain = blockchain,
40-
start_date = zeroex_settler_start_date
41-
42-
)
43-
}}
44-
),
45-
46-
trade_details as (
47-
{{
48-
zeroex_v2_trades_detail(
49-
blockchain = blockchain,
50-
start_date = zeroex_settler_start_date
51-
52-
)
53-
}}
54-
55-
)
56-
select
57-
*
58-
from trade_details
13+
{{
14+
zeroex_settler_agg(
15+
blockchain = 'base'
16+
)
17+
}}

0 commit comments

Comments
 (0)