From bfaa88926bffb5fc2886ae4d9cbf806b2708b1bd Mon Sep 17 00:00:00 2001 From: 0xRob <83790096+0xRobin@users.noreply.github.com> Date: Wed, 8 Jul 2026 22:11:07 +0200 Subject: [PATCH 1/2] feat(tokens): materialize tokens_gnosis_suicide_events staging table Extracts the SELFDESTRUCT window computation from tokens_gnosis_suicide_transfers into a shared staging model, dropping gnosis.traces scans from 3x to 1x per hourly run (~0.95 CPU-hrs and ~384 GB IO saved daily on baseline). Also fixes a latent nondeterminism: the ROW_NUMBER/LAG window used ORDER BY block_time alone, which had ties on 82 of 143,517 rows over full history. Total order (block_time, block_number, tx_index, trace_address) makes event_sequence stable across runs. Design pass by Andre Monteiro (2026-06-30). --- .../transfers_and_balances/gnosis/_schema.yml | 46 +++++++++++++++++++ .../gnosis/tokens_gnosis_suicide_events.sql | 43 +++++++++++++++++ .../tokens_gnosis_suicide_transfers.sql | 36 ++------------- 3 files changed, 92 insertions(+), 33 deletions(-) create mode 100644 dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_events.sql diff --git a/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/_schema.yml b/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/_schema.yml index e92be5ba4e0..ce27d3d0ba4 100644 --- a/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/_schema.yml +++ b/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/_schema.yml @@ -66,6 +66,52 @@ models: - name: _updated_at description: "Timestamp when this row was last written" + - name: tokens_gnosis_suicide_events + description: "Ordered SELFDESTRUCT (SUICIDE) trace events on the Gnosis blockchain with deterministic per-address event_sequence and previous_block_time. Staging table shared by tokens_gnosis_suicide_transfers to avoid rescanning gnosis.traces on every hourly build." + meta: + blockchain: gnosis + sector: tokens + contributors: ['0xRob', 'hdser'] + config: + tags: ['tokens', 'suicide', 'events', 'gnosis'] + data_tests: + - dbt_utils.unique_combination_of_columns: + arguments: + combination_of_columns: + - address + - event_sequence + columns: + - name: block_month + description: "The month of the block in which the SELFDESTRUCT was executed." + - name: block_date + description: "The date of the block in which the SELFDESTRUCT was executed." + - name: block_time + description: "The exact time when the block was mined." + - name: block_number + description: "The number of the block in the blockchain." + - name: tx_hash + description: "The hash of the transaction containing the SELFDESTRUCT." + - name: tx_index + description: "The transaction index within the block." + - name: trace_address + description: "The trace address of the SELFDESTRUCT trace within the transaction." + - name: tx_from + description: "The transaction sender." + - name: tx_to + description: "The transaction receiver." + - name: address + description: "The self-destructing contract address." + data_tests: + - not_null + - name: refund_address + description: "The refund address that receives the contract's remaining native balance." + - name: event_sequence + description: "1-based ordinal of this SELFDESTRUCT among all SELFDESTRUCTs for this address, using a deterministic total order (block_time, block_number, tx_index, trace_address)." + data_tests: + - not_null + - name: previous_block_time + description: "The block_time of the previous SELFDESTRUCT for this address under the same deterministic order, or NULL for the first." + - name: tokens_gnosis_suicide_transfers description: "Token transfers related to account destruction or contract suicide on the Gnosis blockchain." meta: diff --git a/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_events.sql b/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_events.sql new file mode 100644 index 00000000000..44156e3b958 --- /dev/null +++ b/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_events.sql @@ -0,0 +1,43 @@ +{{ config( + schema = 'tokens_gnosis', + alias = 'suicide_events', + materialized = 'table', + file_format = 'delta', + ) +}} + +-- Ordered SUICIDE (SELFDESTRUCT) trace events on Gnosis. +-- Staging table shared by tokens_gnosis_suicide_transfers so that each hourly +-- build reads this small table (~117K rows total) instead of scanning the full +-- gnosis.traces partition three times. +-- +-- The ORDER BY includes (block_number, tx_index, trace_address) as a tiebreaker +-- after block_time so per-address event_sequence is deterministic even when the +-- same address is self-destructed multiple times inside the same block. + +SELECT + cast(date_trunc('month', block_time) as date) AS block_month + , cast(date_trunc('day', block_time) as date) AS block_date + , block_time + , block_number + , tx_hash + , tx_index + , trace_address + , tx_from + , tx_to + , address + , refund_address + , ROW_NUMBER() OVER ( + PARTITION BY address + ORDER BY block_time, block_number, tx_index, array_join(trace_address, ',') + ) AS event_sequence + , LAG(block_time) OVER ( + PARTITION BY address + ORDER BY block_time, block_number, tx_index, array_join(trace_address, ',') + ) AS previous_block_time +FROM + {{ source('gnosis', 'traces') }} +WHERE + type = 'suicide' + AND + success diff --git a/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_transfers.sql b/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_transfers.sql index 58b2d328419..b3d1d569850 100644 --- a/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_transfers.sql +++ b/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_transfers.sql @@ -13,36 +13,6 @@ WITH -suicide AS ( - SELECT - cast(date_trunc('month', block_time) as date) AS block_month - , cast(date_trunc('day', block_time) as date) AS block_date - , block_time - , block_number - , tx_hash - , tx_index - , trace_address - , tx_from - , tx_to - , address - , refund_address - FROM - {{ source('gnosis', 'traces') }} - WHERE - type = 'suicide' - AND - success -), - -suicide_events AS ( - SELECT - * - ,ROW_NUMBER() OVER (PARTITION BY address ORDER BY block_time) AS event_sequence - ,LAG(block_time) OVER (PARTITION BY address ORDER BY block_time) AS previous_block_time - FROM - suicide -), - tokens_gnosis_base_without_suicide_transfers AS ( SELECT address @@ -56,7 +26,7 @@ tokens_gnosis_base_without_suicide_transfers AS ( FROM {{ ref('tokens_gnosis_base_without_suicide_transfers') }} t1 INNER JOIN - suicide_events t2 + {{ ref('tokens_gnosis_suicide_events') }} t2 ON t2.address = t1."from" WHERE @@ -75,7 +45,7 @@ tokens_gnosis_base_without_suicide_transfers AS ( FROM {{ ref('tokens_gnosis_base_without_suicide_transfers') }} t1 INNER JOIN - suicide_events t2 + {{ ref('tokens_gnosis_suicide_events') }} t2 ON t2.address = t1."to" WHERE @@ -122,7 +92,7 @@ SELECT FROM suicide_balances t1 INNER JOIN - suicide_events t2 + {{ ref('tokens_gnosis_suicide_events') }} t2 ON t2.address = t1.address AND From 10b84976e16af818109248eb27b1be1a48086896 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 15 Jul 2026 10:45:19 +0000 Subject: [PATCH 2/2] Fix trace_address ordering in gnosis suicide events Replace array_join(trace_address, ',') with direct trace_address ordering in window functions to use numeric element-wise array comparison instead of lexicographic string comparison. Applied via @cursor push command --- .../gnosis/tokens_gnosis_suicide_events.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_events.sql b/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_events.sql index 44156e3b958..68cad7ac723 100644 --- a/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_events.sql +++ b/dbt_subprojects/tokens/models/transfers_and_balances/gnosis/tokens_gnosis_suicide_events.sql @@ -29,11 +29,11 @@ SELECT , refund_address , ROW_NUMBER() OVER ( PARTITION BY address - ORDER BY block_time, block_number, tx_index, array_join(trace_address, ',') + ORDER BY block_time, block_number, tx_index, trace_address ) AS event_sequence , LAG(block_time) OVER ( PARTITION BY address - ORDER BY block_time, block_number, tx_index, array_join(trace_address, ',') + ORDER BY block_time, block_number, tx_index, trace_address ) AS previous_block_time FROM {{ source('gnosis', 'traces') }}