From c7d70fe7a30b3fce2d1085feb3dc25b670580445 Mon Sep 17 00:00:00 2001 From: Benjamin Smith Date: Fri, 3 Feb 2023 16:28:49 +0100 Subject: [PATCH] [HotFix] Add missing ETH transfers to slippage (#180) Add missing ETH transfers to slippage --- queries/dune_v2/period_slippage.sql | 91 ++++++++++++++------ src/queries.py | 2 +- tests/queries/test_slippage_investigation.py | 65 ++++++++++++++ 3 files changed, 131 insertions(+), 27 deletions(-) diff --git a/queries/dune_v2/period_slippage.sql b/queries/dune_v2/period_slippage.sql index e304cb4d..b8fc8ea4 100644 --- a/queries/dune_v2/period_slippage.sql +++ b/queries/dune_v2/period_slippage.sql @@ -1,7 +1,8 @@ --- https://github.com/cowprotocol/solver-rewards/pull/169 +-- https://github.com/cowprotocol/solver-rewards/pull/180 with -filtered_trades as ( +batch_meta as ( select t.block_time, + t.block_number, t.tx_hash, case when dex_swaps = 0 @@ -10,7 +11,19 @@ filtered_trades as ( else dex_swaps end as dex_swaps, num_trades, - b.solver_address, + b.solver_address + from cow_protocol_ethereum.trades t + join cow_protocol_ethereum.batches b + on t.block_number = b.block_number + and t.tx_hash = b.tx_hash + where b.block_time between '{{StartTime}}' and '{{EndTime}}' + and t.block_time between '{{StartTime}}' and '{{EndTime}}' + and (b.solver_address = lower('{{SolverAddress}}') or '{{SolverAddress}}' = '0x') + and (t.tx_hash = lower('{{TxHash}}') or '{{TxHash}}' = '0x') +), +filtered_trades as ( + select t.tx_hash, + t.block_number, trader as trader_in, receiver as trader_out, sell_token_address as sell_token, @@ -33,18 +46,14 @@ filtered_trades as ( batchwise_traders as ( select tx_hash, + block_number, collect_set(trader_in) as traders_in, collect_set(trader_out) as traders_out from filtered_trades - group by tx_hash + group by tx_hash, block_number ), - user_in as ( - select block_time, - tx_hash, - dex_swaps, - num_trades, - solver_address, + select tx_hash, trader_in as sender, contract_address as receiver, sell_token as token, @@ -53,11 +62,7 @@ user_in as ( from filtered_trades ), user_out as ( - select block_time, - tx_hash, - dex_swaps, - num_trades, - solver_address, + select tx_hash, contract_address as sender, trader_out as receiver, buy_token as token, @@ -66,16 +71,7 @@ user_out as ( from filtered_trades ), other_transfers as ( - select block_time, - b.tx_hash, - case - when dex_swaps = 0 - -- Estimation made here: https://dune.com/queries/1646084 - then ((gas_used - 73688 - (70528 * num_trades)) / 90000)::int - else dex_swaps - end as dex_swaps, - num_trades, - solver_address, + select b.tx_hash, from as sender, to as receiver, t.contract_address as token, @@ -103,12 +99,55 @@ other_transfers as ( and (t.evt_tx_hash = lower('{{TxHash}}') or '{{TxHash}}' = '0x') and (solver_address = lower('{{SolverAddress}}') or '{{SolverAddress}}' = '0x') ), -batch_transfers as ( +eth_transfers as ( + select + bt.tx_hash, + from as sender, + to as receiver, + '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' as token, + cast(value as decimal(38, 0)) as amount_wei, + case + when '0x9008d19f58aabd9ed0d60971565aa8510560ab41' = to + then 'AMM_IN' + else 'AMM_OUT' + end as transfer_type + from batchwise_traders bt + inner join ethereum.traces et + on bt.block_number = et.block_number + and bt.tx_hash = et.tx_hash + and cast(value as decimal(38, 0)) > 0 + and success = true + and '0x9008d19f58aabd9ed0d60971565aa8510560ab41' in (to, from) + -- WETH unwraps don't have cancelling WETH transfer. + and from != '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' + -- ETH transfers to traders are already part of USER_OUT + and not array_contains(traders_out, to) +), +pre_batch_transfers as ( select * from user_in union all select * from user_out union all select * from other_transfers + union all + select * from eth_transfers +), +batch_transfers as ( + select + block_time, + block_number, + pbt.tx_hash, + dex_swaps, + num_trades, + solver_address, + sender, + receiver, + token, + amount_wei, + transfer_type + from batch_meta bm + join pre_batch_transfers pbt + on bm.tx_hash = pbt.tx_hash ), -- These batches involve a token AXS (Old) -- whose transfer function doesn't align with the emitted transfer event. diff --git a/src/queries.py b/src/queries.py index 38c3f20d..f863ab97 100644 --- a/src/queries.py +++ b/src/queries.py @@ -96,6 +96,6 @@ def with_params( name="Solver Slippage for Period", filepath="period_slippage.sql", v1_id=1728478, - v2_id=1836718, + v2_id=1956003, ), } diff --git a/tests/queries/test_slippage_investigation.py b/tests/queries/test_slippage_investigation.py index dc827c31..89665b9d 100644 --- a/tests/queries/test_slippage_investigation.py +++ b/tests/queries/test_slippage_investigation.py @@ -4,6 +4,7 @@ import pytest from dune_client.client import DuneClient +from dune_client.query import Query from dune_client.types import QueryParameter from src.fetch.dune import DuneFetcher @@ -17,6 +18,16 @@ def setUp(self) -> None: self.dune = DuneClient(os.environ["DUNE_API_KEY"]) self.slippage_query = QUERIES["PERIOD_SLIPPAGE"] + @staticmethod + def slippage_query_for(period: AccountingPeriod, tx_hash: str) -> Query: + return QUERIES["PERIOD_SLIPPAGE"].with_params( + period.as_query_params() + + [ + QueryParameter.text_type("TxHash", tx_hash), + QueryParameter.text_type("CTE_NAME", "results_per_tx"), + ] + ) + @pytest.mark.skip( reason="This takes a while to run and should probably be avoided without local testing." ) @@ -125,6 +136,60 @@ def test_positive_slippage_evaluation(self): # https://dune.com/queries/1836718?CTE_NAME_e15077=final_token_balance_sheet&EndTime_d83555=2023-01-02+00%3A00%3A00&StartTime_d83555=2023-01-01+00%3A00%3A00&TxHash_t6c1ea=0x5c4e410ce5d741f60e06a8621c6f12839ad39273f5abf78d4bbc1cd3b31de46c self.assertEqual(tx_slippage["num_entries"], 4) + def test_slippage_regression(self): + """ + Two known batches with ETH transfers previously not captured. + The following hashes were picked up by this query: https://dune.com/queries/1957339 + which displays batches where these missing ETH transfers occurred. + Bug was picked up by our Dune Alerts on Feb. 2, 2023 + https://cowservices.slack.com/archives/C03PW4CR38A/p1675328564060139 + """ + period = AccountingPeriod("2023-02-01", 1) + # Previously having -210 USD negative slippage. + result_0x3b2e = exec_or_get( + self.dune, + query=self.slippage_query_for( + period, + "0x3b2e9675b6d71a34e9b7f4abb4c9e80922be311076fcbb345d7da9d91a05e048", + ), + result_id="01GRA2NSAVSQZH6B8BPHR0FAN8", + ) + self.assertEqual(result_0x3b2e.query_id, self.slippage_query.v2_query.query_id) + self.assertEqual( + result_0x3b2e.get_rows(), + [ + { + "eth_slippage_wei": -4703807.681117934, + "hour": "2023-02-01T01:00:00Z", + "num_entries": 2, + "solver_address": "0xc9ec550bea1c64d779124b23a26292cc223327b6", + "usd_value": -7.454727687586665e-09, + } + ], + ) + # Previously having -150 USD slippage + result_0x7a00 = exec_or_get( + self.dune, + query=self.slippage_query_for( + period, + "0x7a007eb8ad25f5f1f1f36459998ae758b0e699ca69cc7b4c38354d42092651bf", + ), + result_id="01GRA2Y006E4FGZMWSTACMHZDY", + ) + self.assertEqual(result_0x7a00.query_id, self.slippage_query.v2_query.query_id) + self.assertEqual( + result_0x7a00.get_rows(), + [ + { + "eth_slippage_wei": -815874497.9746609, + "hour": "2023-02-01T01:00:00Z", + "num_entries": 2, + "solver_address": "0xc9ec550bea1c64d779124b23a26292cc223327b6", + "usd_value": -1.2930210208343511e-06, + } + ], + ) + if __name__ == "__main__": unittest.main()