From ff05504acceb4a3853f0a961d611072668e8325d Mon Sep 17 00:00:00 2001 From: Felix Henneke Date: Fri, 8 Nov 2024 09:27:28 +0100 Subject: [PATCH 1/5] no service fee on penalties --- src/fetch/payouts.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/fetch/payouts.py b/src/fetch/payouts.py index 1effdfa3..2dcf6916 100644 --- a/src/fetch/payouts.py +++ b/src/fetch/payouts.py @@ -136,11 +136,19 @@ def total_outgoing_eth(self) -> int: def total_cow_reward(self) -> int: """Total outgoing COW token reward""" - return int(self.reward_scaling() * self.primary_reward_cow) + return ( + int(self.reward_scaling() * self.primary_reward_cow) + if self.primary_reward_cow > 0 + else self.primary_reward_cow + ) def total_eth_reward(self) -> int: """Total outgoing ETH reward""" - return int(self.reward_scaling() * self.primary_reward_eth) + return ( + int(self.reward_scaling() * self.primary_reward_eth) + if self.primary_reward_eth > 0 + else self.primary_reward_eth + ) def reward_scaling(self) -> Fraction: """Scaling factor for service fee @@ -149,7 +157,7 @@ def reward_scaling(self) -> Fraction: def total_service_fee(self) -> Fraction: """Total service fee charged from rewards""" - return self.service_fee * (self.primary_reward_cow + self.quote_reward_cow) + return self.service_fee * (max(self.primary_reward_cow, 0) + self.quote_reward_cow) def is_overdraft(self) -> bool: """ From 2f3e371f9c379ea12b5b223e9b36e73085992668 Mon Sep 17 00:00:00 2001 From: Felix Henneke Date: Wed, 15 Jan 2025 14:27:46 +0100 Subject: [PATCH 2/5] black fix --- src/fetch/payouts.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fetch/payouts.py b/src/fetch/payouts.py index 2dcf6916..f538a23d 100644 --- a/src/fetch/payouts.py +++ b/src/fetch/payouts.py @@ -157,7 +157,9 @@ def reward_scaling(self) -> Fraction: def total_service_fee(self) -> Fraction: """Total service fee charged from rewards""" - return self.service_fee * (max(self.primary_reward_cow, 0) + self.quote_reward_cow) + return self.service_fee * ( + max(self.primary_reward_cow, 0) + self.quote_reward_cow + ) def is_overdraft(self) -> bool: """ From 81513b62f33eaf2fa88a0709f4bf7556e384c2f9 Mon Sep 17 00:00:00 2001 From: Felix Henneke Date: Wed, 15 Jan 2025 15:21:06 +0100 Subject: [PATCH 3/5] add test for negative reward --- tests/unit/test_payouts.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/unit/test_payouts.py b/tests/unit/test_payouts.py index 05e2c566..50da7bf3 100644 --- a/tests/unit/test_payouts.py +++ b/tests/unit/test_payouts.py @@ -641,6 +641,38 @@ def test_quote_reward_service_fee(self): ], ) + def test_negative_reward_service_fee(self): + """Sevice fee reduces COW quote reward but not reduce a negative batch reward.""" + primary_reward = -(10**18) # negative reward + slippage = 2 * 10**18 # to avoid overdraft + num_quotes = 100 + service_fee = Fraction(15, 100) + reward_per_quote = 6 * 10**18 + + test_datum = self.sample_record( + primary_reward=primary_reward, + slippage=slippage, + num_quotes=num_quotes, + service_fee=service_fee, + ) + self.assertFalse(test_datum.is_overdraft()) + self.assertEqual( + test_datum.as_payouts(), + [ + Transfer( + token=self.cow_token, + recipient=self.reward_target, + amount_wei=int(reward_per_quote * num_quotes * (1 - service_fee)), + ), + Transfer( + token=None, + recipient=self.buffer_accounting_target, + amount_wei=slippage + + primary_reward, # no multiplication by 1 - service_fee + ), + ], + ) + if __name__ == "__main__": unittest.main() From a413e133f20272242850b941efd1e711487627a2 Mon Sep 17 00:00:00 2001 From: Felix Henneke Date: Wed, 15 Jan 2025 16:43:17 +0100 Subject: [PATCH 4/5] udpade tests to also check - consistency of cow and eth rewards - total service fee since those quantities are modified as well --- tests/unit/test_payouts.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/unit/test_payouts.py b/tests/unit/test_payouts.py index 50da7bf3..26aa15f4 100644 --- a/tests/unit/test_payouts.py +++ b/tests/unit/test_payouts.py @@ -605,6 +605,17 @@ def test_performance_reward_service_fee(self): num_quotes=num_quotes, service_fee=service_fee, ) + + self.assertTrue( + test_datum.total_cow_reward(), + test_datum.total_eth_reward() * self.conversion_rate, + ) # ensure consistency of cow and eth batch rewards + self.assertEqual( + test_datum.total_service_fee(), + int( + primary_reward * self.conversion_rate * service_fee + ), # only quote rewards enter + ) self.assertFalse(test_datum.is_overdraft()) self.assertEqual( test_datum.as_payouts(), @@ -621,12 +632,21 @@ def test_performance_reward_service_fee(self): def test_quote_reward_service_fee(self): """Sevice fee reduces COW reward.""" primary_reward, num_quotes, service_fee = 0, 100, Fraction(15, 100) + reward_per_quote = 6 * 10**18 + test_datum = self.sample_record( primary_reward=primary_reward, slippage=0, num_quotes=num_quotes, service_fee=service_fee, ) + + self.assertEqual( + test_datum.total_service_fee(), + int( + reward_per_quote * num_quotes * service_fee + ), # only quote rewards enter + ) self.assertFalse(test_datum.is_overdraft()) self.assertEqual( test_datum.as_payouts(), @@ -655,6 +675,17 @@ def test_negative_reward_service_fee(self): num_quotes=num_quotes, service_fee=service_fee, ) + + self.assertTrue( + test_datum.total_cow_reward(), + test_datum.total_eth_reward() * self.conversion_rate, + ) # ensure consistency of cow and eth batch rewards + self.assertEqual( + test_datum.total_service_fee(), + int( + reward_per_quote * num_quotes * service_fee + ), # only quote rewards enter + ) self.assertFalse(test_datum.is_overdraft()) self.assertEqual( test_datum.as_payouts(), From 48c2770984dce5f1175e39f8e84fed58f42fe52f Mon Sep 17 00:00:00 2001 From: Felix Henneke Date: Fri, 17 Jan 2025 17:08:01 +0100 Subject: [PATCH 5/5] additional test for positive batch rewards --- tests/unit/test_payouts.py | 40 +++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_payouts.py b/tests/unit/test_payouts.py index 26aa15f4..96ae5804 100644 --- a/tests/unit/test_payouts.py +++ b/tests/unit/test_payouts.py @@ -651,11 +651,49 @@ def test_quote_reward_service_fee(self): self.assertEqual( test_datum.as_payouts(), [ + Transfer( + token=self.cow_token, + recipient=self.reward_target, + amount_wei=int(reward_per_quote * num_quotes * (1 - service_fee)), + ), + ], + ) + + def test_positive_reward_service_fee(self): + """Sevice fee reduces COW reward.""" + primary_reward = 10**18 # positive reward + num_quotes = 100 + service_fee = Fraction(15, 100) + reward_per_quote = 6 * 10**18 + + test_datum = self.sample_record( + primary_reward=primary_reward, + slippage=0, + num_quotes=num_quotes, + service_fee=service_fee, + ) + + self.assertEqual( + test_datum.total_service_fee(), + int( + (primary_reward * self.conversion_rate + reward_per_quote * num_quotes) + * service_fee + ), + ) + self.assertFalse(test_datum.is_overdraft()) + self.assertEqual( + test_datum.as_payouts(), + [ + Transfer( + token=self.cow_token, + recipient=self.reward_target, + amount_wei=int(reward_per_quote * num_quotes * (1 - service_fee)), + ), Transfer( token=self.cow_token, recipient=self.reward_target, amount_wei=int( - 6000000000000000000 * num_quotes * (1 - service_fee) + primary_reward * self.conversion_rate * (1 - service_fee) ), ), ],