yearn-treasury 0.1.7__cp310-cp310-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. yearn_treasury/__init__.py +19 -0
  2. yearn_treasury/_db.cp310-win32.pyd +0 -0
  3. yearn_treasury/_db.py +50 -0
  4. yearn_treasury/_ens.cp310-win32.pyd +0 -0
  5. yearn_treasury/_ens.py +30 -0
  6. yearn_treasury/_logging.cp310-win32.pyd +0 -0
  7. yearn_treasury/_logging.py +41 -0
  8. yearn_treasury/address_labels.yaml +39 -0
  9. yearn_treasury/budget/__init__.cp310-win32.pyd +0 -0
  10. yearn_treasury/budget/__init__.py +6 -0
  11. yearn_treasury/budget/_request.cp310-win32.pyd +0 -0
  12. yearn_treasury/budget/_request.py +43 -0
  13. yearn_treasury/budget/_requests.cp310-win32.pyd +0 -0
  14. yearn_treasury/budget/_requests.py +96 -0
  15. yearn_treasury/constants.py +91 -0
  16. yearn_treasury/main.py +175 -0
  17. yearn_treasury/py.typed +1 -0
  18. yearn_treasury/rules/__init__.py +20 -0
  19. yearn_treasury/rules/constants.cp310-win32.pyd +0 -0
  20. yearn_treasury/rules/constants.py +15 -0
  21. yearn_treasury/rules/cost_of_revenue/__init__.py +1 -0
  22. yearn_treasury/rules/cost_of_revenue/gas.cp310-win32.pyd +0 -0
  23. yearn_treasury/rules/cost_of_revenue/gas.py +64 -0
  24. yearn_treasury/rules/cost_of_revenue/match_on_hash.yaml +12 -0
  25. yearn_treasury/rules/expense/__init__.cp310-win32.pyd +0 -0
  26. yearn_treasury/rules/expense/__init__.py +4 -0
  27. yearn_treasury/rules/expense/general.cp310-win32.pyd +0 -0
  28. yearn_treasury/rules/expense/general.py +13 -0
  29. yearn_treasury/rules/expense/infrastructure.cp310-win32.pyd +0 -0
  30. yearn_treasury/rules/expense/infrastructure.py +46 -0
  31. yearn_treasury/rules/expense/match_on_hash.yaml +48 -0
  32. yearn_treasury/rules/expense/match_on_to_address.yaml +7 -0
  33. yearn_treasury/rules/expense/people.cp310-win32.pyd +0 -0
  34. yearn_treasury/rules/expense/people.py +83 -0
  35. yearn_treasury/rules/expense/security.cp310-win32.pyd +0 -0
  36. yearn_treasury/rules/expense/security.py +146 -0
  37. yearn_treasury/rules/ignore/__init__.py +8 -0
  38. yearn_treasury/rules/ignore/general.cp310-win32.pyd +0 -0
  39. yearn_treasury/rules/ignore/general.py +11 -0
  40. yearn_treasury/rules/ignore/maker.py +91 -0
  41. yearn_treasury/rules/ignore/passthru.py +309 -0
  42. yearn_treasury/rules/ignore/staking.py +101 -0
  43. yearn_treasury/rules/ignore/swaps/__init__.py +24 -0
  44. yearn_treasury/rules/ignore/swaps/_skip_tokens.py +8 -0
  45. yearn_treasury/rules/ignore/swaps/aave.py +68 -0
  46. yearn_treasury/rules/ignore/swaps/auctions.cp310-win32.pyd +0 -0
  47. yearn_treasury/rules/ignore/swaps/auctions.py +30 -0
  48. yearn_treasury/rules/ignore/swaps/compound.py +57 -0
  49. yearn_treasury/rules/ignore/swaps/conversion_factory.cp310-win32.pyd +0 -0
  50. yearn_treasury/rules/ignore/swaps/conversion_factory.py +20 -0
  51. yearn_treasury/rules/ignore/swaps/cowswap.py +86 -0
  52. yearn_treasury/rules/ignore/swaps/curve.py +174 -0
  53. yearn_treasury/rules/ignore/swaps/gearbox.cp310-win32.pyd +0 -0
  54. yearn_treasury/rules/ignore/swaps/gearbox.py +36 -0
  55. yearn_treasury/rules/ignore/swaps/iearn.cp310-win32.pyd +0 -0
  56. yearn_treasury/rules/ignore/swaps/iearn.py +41 -0
  57. yearn_treasury/rules/ignore/swaps/otc.cp310-win32.pyd +0 -0
  58. yearn_treasury/rules/ignore/swaps/otc.py +58 -0
  59. yearn_treasury/rules/ignore/swaps/pooltogether.cp310-win32.pyd +0 -0
  60. yearn_treasury/rules/ignore/swaps/pooltogether.py +23 -0
  61. yearn_treasury/rules/ignore/swaps/synthetix.cp310-win32.pyd +0 -0
  62. yearn_treasury/rules/ignore/swaps/synthetix.py +10 -0
  63. yearn_treasury/rules/ignore/swaps/uniswap.py +293 -0
  64. yearn_treasury/rules/ignore/swaps/unwrapper.cp310-win32.pyd +0 -0
  65. yearn_treasury/rules/ignore/swaps/unwrapper.py +17 -0
  66. yearn_treasury/rules/ignore/swaps/vaults.cp310-win32.pyd +0 -0
  67. yearn_treasury/rules/ignore/swaps/vaults.py +263 -0
  68. yearn_treasury/rules/ignore/swaps/woofy.cp310-win32.pyd +0 -0
  69. yearn_treasury/rules/ignore/swaps/woofy.py +79 -0
  70. yearn_treasury/rules/ignore/swaps/yfi.cp310-win32.pyd +0 -0
  71. yearn_treasury/rules/ignore/swaps/yfi.py +110 -0
  72. yearn_treasury/rules/ignore/swaps/yla.cp310-win32.pyd +0 -0
  73. yearn_treasury/rules/ignore/swaps/yla.py +27 -0
  74. yearn_treasury/rules/ignore/unit.cp310-win32.pyd +0 -0
  75. yearn_treasury/rules/ignore/unit.py +39 -0
  76. yearn_treasury/rules/ignore/weth.cp310-win32.pyd +0 -0
  77. yearn_treasury/rules/ignore/weth.py +47 -0
  78. yearn_treasury/rules/ignore/ygov.cp310-win32.pyd +0 -0
  79. yearn_treasury/rules/ignore/ygov.py +15 -0
  80. yearn_treasury/rules/other_expense/__init__.cp310-win32.pyd +0 -0
  81. yearn_treasury/rules/other_expense/__init__.py +7 -0
  82. yearn_treasury/rules/other_expense/boost.cp310-win32.pyd +0 -0
  83. yearn_treasury/rules/other_expense/boost.py +49 -0
  84. yearn_treasury/rules/other_expense/bugs.cp310-win32.pyd +0 -0
  85. yearn_treasury/rules/other_expense/bugs.py +80 -0
  86. yearn_treasury/rules/other_expense/donations.cp310-win32.pyd +0 -0
  87. yearn_treasury/rules/other_expense/donations.py +42 -0
  88. yearn_treasury/rules/other_expense/dyfi.cp310-win32.pyd +0 -0
  89. yearn_treasury/rules/other_expense/dyfi.py +28 -0
  90. yearn_treasury/rules/other_expense/events.cp310-win32.pyd +0 -0
  91. yearn_treasury/rules/other_expense/events.py +20 -0
  92. yearn_treasury/rules/other_expense/match_on_hash.yaml +43 -0
  93. yearn_treasury/rules/other_expense/match_on_to_address.yaml +8 -0
  94. yearn_treasury/rules/other_expense/misc.cp310-win32.pyd +0 -0
  95. yearn_treasury/rules/other_expense/misc.py +48 -0
  96. yearn_treasury/rules/other_expense/revshare.cp310-win32.pyd +0 -0
  97. yearn_treasury/rules/other_expense/revshare.py +19 -0
  98. yearn_treasury/rules/other_income/__init__.cp310-win32.pyd +0 -0
  99. yearn_treasury/rules/other_income/__init__.py +2 -0
  100. yearn_treasury/rules/other_income/airdrops.cp310-win32.pyd +0 -0
  101. yearn_treasury/rules/other_income/airdrops.py +29 -0
  102. yearn_treasury/rules/other_income/match_on_hash.yaml +21 -0
  103. yearn_treasury/rules/other_income/misc.cp310-win32.pyd +0 -0
  104. yearn_treasury/rules/other_income/misc.py +78 -0
  105. yearn_treasury/rules/revenue/__init__.py +6 -0
  106. yearn_treasury/rules/revenue/bribes.cp310-win32.pyd +0 -0
  107. yearn_treasury/rules/revenue/bribes.py +25 -0
  108. yearn_treasury/rules/revenue/farming.cp310-win32.pyd +0 -0
  109. yearn_treasury/rules/revenue/farming.py +55 -0
  110. yearn_treasury/rules/revenue/keepcoins.cp310-win32.pyd +0 -0
  111. yearn_treasury/rules/revenue/keepcoins.py +61 -0
  112. yearn_treasury/rules/revenue/match_on_hash.yaml +4 -0
  113. yearn_treasury/rules/revenue/seasolver.cp310-win32.pyd +0 -0
  114. yearn_treasury/rules/revenue/seasolver.py +23 -0
  115. yearn_treasury/rules/revenue/vaults.py +171 -0
  116. yearn_treasury/rules/revenue/yteams.cp310-win32.pyd +0 -0
  117. yearn_treasury/rules/revenue/yteams.py +16 -0
  118. yearn_treasury/shitcoins.py +143 -0
  119. yearn_treasury/vaults.cp310-win32.pyd +0 -0
  120. yearn_treasury/vaults.py +49 -0
  121. yearn_treasury/wallets.yaml +54 -0
  122. yearn_treasury/yteams.py +207 -0
  123. yearn_treasury-0.1.7.dist-info/METADATA +85 -0
  124. yearn_treasury-0.1.7.dist-info/RECORD +128 -0
  125. yearn_treasury-0.1.7.dist-info/WHEEL +5 -0
  126. yearn_treasury-0.1.7.dist-info/entry_points.txt +2 -0
  127. yearn_treasury-0.1.7.dist-info/top_level.txt +2 -0
  128. yearn_treasury__mypyc.cp310-win32.pyd +0 -0
@@ -0,0 +1,86 @@
1
+ from typing import Final
2
+
3
+ from dao_treasury import TreasuryTx, TreasuryWallet
4
+ from eth_typing import BlockNumber
5
+ from pony.orm import select
6
+ from y import Network
7
+
8
+ from yearn_treasury.constants import TREASURY_WALLETS
9
+ from yearn_treasury.rules.ignore.swaps import swaps
10
+ from yearn_treasury.rules.ignore.swaps._skip_tokens import SKIP_TOKENS
11
+
12
+ COWSWAP: Final = "0x9008D19f58AAbD9eD0D60971565AA8510560ab41"
13
+
14
+
15
+ @swaps("Cowswap", Network.Mainnet)
16
+ def is_cowswap_swap(tx: TreasuryTx) -> bool:
17
+ # One sided, other side goes elsewhere. typically used for output tokens passed-thru to vaults.
18
+ if tx.from_nickname == "yMechs Multisig" and tx.to_nickname == "Contract: GPv2Settlement":
19
+ return True
20
+
21
+ try:
22
+ if "Trade" not in tx.events:
23
+ return False
24
+ except KeyError as e:
25
+ if "components" in str(e):
26
+ return False
27
+ raise
28
+
29
+ token = tx.token
30
+ block: BlockNumber = tx.block # type: ignore [assignment]
31
+ amount = tx.amount
32
+ token_address = token.address.address
33
+
34
+ for trade in tx.events["Trade"]:
35
+ if (
36
+ trade.address == COWSWAP
37
+ and TreasuryWallet.check_membership(trade["owner"], block)
38
+ and trade["buyToken"] not in SKIP_TOKENS
39
+ ):
40
+ # buy side
41
+ if token_address == trade["buyToken"] and TreasuryWallet.check_membership(
42
+ tx.to_address.address, block # type: ignore [union-attr, arg-type]
43
+ ):
44
+ # TODO get rid of this rounding when we move to postgres
45
+ buy_amount = round(token.scale_value(trade["buyAmount"]), 8)
46
+ if round(amount, 8) == buy_amount:
47
+ return True
48
+ print(f"Cowswap buy amount does not match: {round(amount, 8)} {buy_amount}")
49
+ # sell side
50
+ elif token_address == trade["sellToken"] and tx.from_address == trade["owner"]:
51
+ # TODO get rid of this rounding when we move to postgres
52
+ sell_amount = round(token.scale_value(trade["sellAmount"]), 8)
53
+ if round(amount, 8) != sell_amount:
54
+ print(f"Cowswap sell amount does not match: {round(amount, 8)} {sell_amount}")
55
+ continue
56
+ # Did Yearn actually receive the other side of the trade?
57
+ for address in TREASURY_WALLETS:
58
+ if TreasuryWallet.check_membership(address, block):
59
+ other_side_query = select( # type: ignore [no-untyped-call]
60
+ t
61
+ for t in TreasuryTx # type: ignore [attr-defined]
62
+ if t.hash == tx.hash
63
+ and t.token.address.address == trade["buyToken"]
64
+ and t.from_address.address == COWSWAP
65
+ and t.to_address.address == address
66
+ )
67
+
68
+ if len(other_side_query) > 0:
69
+ return True
70
+
71
+ # made with some help from other contracts
72
+ return tx.hash in {
73
+ "0xd41e40a0e9b49c4f06e1956066006de901a4ed8c856a43c31ac1cbd344ff0ccf",
74
+ "0x94e1a85fa25e433976962449588e522ce0f2a81ae3d4b67ae199e458dfce4e39",
75
+ "0x579056f777c1f05a18e566dd329ea85f5c747fd6e7246411b5e016c8bebe8742",
76
+ "0xd007d04560fc42df93da0fd25ac3942f89f7f5458eb492872b3d87be91d7a571",
77
+ "0x2eb9a897ea48c9802f0129674d0203835a236e2f41c6db8edb017a4c315b84f4",
78
+ "0xce2338b61c8c5875ce4e19f9d5993895a4d5d9eb81b78e1b33279436d2c2c047",
79
+ "0x6dd14144594e7b19fdc4529682eb1cf554132ae318d8ba5b238cdeb3e694d52a",
80
+ "0xb0d430e1ec4d6fa7bd4e56f86e6fefd7f71946549710ca0b9f39de14c04d02ed",
81
+ "0x0b1b00f0a29f787b44421461a3f9444081fe94ca29958c98cd2c23e271f3f69a",
82
+ "0x69eeeb5d7cb0f23ee98ef23f38d02ff0a695d75a1da1fa010abaa7a5aab947ff",
83
+ "0xdfbe76c0af4ec68021c1603d4f9a6b5f20734e70af86d32fbd57fa87461064f2",
84
+ "0x60cfe7c2c19e1fc3010e441ed369fc414bd10dbb7ba88fb4f490d96e15eb2f26",
85
+ "0x1ddddfff1f02c66ef07817144e9e30d6f734432c2736f7859236d3199d4b23fb",
86
+ }
@@ -0,0 +1,174 @@
1
+ from typing import Final
2
+
3
+ from brownie.exceptions import EventLookupError
4
+ from dao_treasury import TreasuryTx, TreasuryWallet
5
+ from eth_typing import ChecksumAddress
6
+ from faster_async_lru import alru_cache
7
+ from y import Contract, Network
8
+
9
+ from yearn_treasury.constants import CHAINID, ZERO_ADDRESS
10
+ from yearn_treasury.rules.ignore.swaps import swaps
11
+
12
+ curve: Final = swaps("Curve")
13
+
14
+
15
+ # curve helpers
16
+ @alru_cache(maxsize=None)
17
+ async def _get_lp_token(pool: Contract) -> ChecksumAddress:
18
+ return ChecksumAddress(await pool.lp_token)
19
+
20
+
21
+ async def _is_old_style(tx: TreasuryTx, pool: Contract) -> bool:
22
+ return hasattr(pool, "lp_token") and tx.token == await _get_lp_token(pool)
23
+
24
+
25
+ def _is_new_style(tx: TreasuryTx, pool: Contract) -> bool:
26
+ return hasattr(pool, "totalSupply") and tx.token == pool.address
27
+
28
+
29
+ def _token_is_curvey(tx: TreasuryTx) -> bool:
30
+ return "crv" in tx.symbol.lower() or "curve" in tx.token.name.lower()
31
+
32
+
33
+ @alru_cache(maxsize=None)
34
+ async def _get_coin_at_index(pool: Contract, index: int) -> ChecksumAddress:
35
+ return ChecksumAddress(await pool.coins.coroutine(index))
36
+
37
+
38
+ @curve("Adding Liquidity")
39
+ async def is_curve_deposit(tx: TreasuryTx) -> bool:
40
+ pool: Contract
41
+ for event in tx.get_events("AddLiquidity"):
42
+ # LP Token Side
43
+ if tx.from_address == ZERO_ADDRESS and _token_is_curvey(tx):
44
+ pool = await Contract.coroutine(event.address) # type: ignore [assignment]
45
+ if await _is_old_style(tx, pool) or _is_new_style(tx, pool):
46
+ return True
47
+
48
+ # Tokens sent
49
+ elif tx.to_address == event.address:
50
+ try:
51
+ tx_amount = round(tx.amount, 8)
52
+ for i, amount in enumerate(event["token_amounts"]):
53
+ # TODO: get rid of this rounding when we migrate to postgres
54
+ event_amount = round(tx.token.scale_value(amount), 8)
55
+ if tx_amount == event_amount:
56
+ pool = await Contract.coroutine(event.address) # type: ignore [assignment]
57
+ if tx.token == await _get_coin_at_index(pool, i):
58
+ return True
59
+ return True
60
+ else:
61
+ print(
62
+ f"Curve AddLiquidity sent amount does not match: {tx_amount} {event_amount}"
63
+ )
64
+ except EventLookupError:
65
+ pass
66
+
67
+ # What if a 3crv deposit was needed before the real deposit?
68
+ elif (
69
+ TreasuryWallet.check_membership(tx.from_address.address, tx.block) # type: ignore [union-attr, arg-type]
70
+ and tx.to_address == "0xA79828DF1850E8a3A3064576f380D90aECDD3359"
71
+ and event.address == "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7"
72
+ ):
73
+ print(f"AddLiquidity-3crv: {event}")
74
+ token = tx.token
75
+ for i, amount in enumerate(event["token_amounts"]):
76
+ event_amount = token.scale_value(amount)
77
+ # TODO: get rid of this rounding when we migrate to postgres
78
+ if round(tx.amount, 14) == round(event_amount, 14):
79
+ pool = await Contract.coroutine(event.address) # type: ignore [assignment]
80
+ if token == await _get_coin_at_index(pool, i):
81
+ return True
82
+ else:
83
+ print(
84
+ f"AddLiquidity-3crv amount does not match: {round(tx.amount, 14)} {round(event_amount)}"
85
+ )
86
+
87
+ # TODO: see if we can remove these with latest hueristics
88
+ return CHAINID == Network.Mainnet and tx.hash in (
89
+ "0x567d2ebc1a336185950432b8f8b010e1116936f9e6c061634f5aba65bdb1e188",
90
+ "0x17e2d7a40697204b3e726d40725082fec5f152f65f400df850f13ef4a4f6c827",
91
+ )
92
+
93
+
94
+ @curve("Removing Liquidity")
95
+ async def is_curve_withdrawal(tx: TreasuryTx) -> bool:
96
+ return (
97
+ _is_curve_withdrawal_one(tx)
98
+ or await _is_curve_withdrawal_multi(tx)
99
+ or (
100
+ CHAINID == Network.Mainnet
101
+ and tx.hash
102
+ in (
103
+ # This was a one-off withdrawal from a special pool 0x5756bbdDC03DaB01a3900F01Fb15641C3bfcc457
104
+ "0xe4f7c8566944202faed1d1e190e400e7bdf8592e65803b09510584ca5284d174",
105
+ )
106
+ )
107
+ )
108
+
109
+
110
+ def _is_curve_withdrawal_one(tx: TreasuryTx) -> bool:
111
+ for event in tx.get_events("RemoveLiquidityOne"):
112
+ # LP Token Side
113
+ if tx.to_address == ZERO_ADDRESS and _token_is_curvey(tx):
114
+ # TODO: get rid of this rounding when we migrate to postgres
115
+ event_amount = round(tx.token.scale_value(event["token_amount"]), 9)
116
+ if round(tx.amount, 9) == event_amount:
117
+ return True
118
+ print(
119
+ f"Curve withdrawal one curvey amount does not match: {round(tx.amount, 9)} {event_amount}"
120
+ )
121
+ # Tokens rec'd
122
+ if tx.from_address != event.address:
123
+ continue
124
+ # TODO: get rid of this rounding when we migrate to postgres
125
+ event_amount = tx.token.scale_value(event["coin_amount"])
126
+ if round(tx.amount, 9) == round(event_amount, 9):
127
+ return True
128
+ print(
129
+ f"Curve withdrawal one amount does not match: {round(tx.amount, 9)} {round(event_amount, 9)}"
130
+ )
131
+ return False
132
+
133
+
134
+ async def _is_curve_withdrawal_multi(tx: TreasuryTx) -> bool:
135
+ pool: Contract
136
+
137
+ for i, event in enumerate(tx.get_events("RemoveLiquidity")):
138
+ print(f"checking {tx.hash} RemoveLiquidity event {i+1}: {event}")
139
+ # LP Token side
140
+ if tx.to_address == ZERO_ADDRESS and _token_is_curvey(tx):
141
+ pool = await Contract.coroutine(event.address) # type: ignore [assignment]
142
+ if await _is_old_style(tx, pool) or _is_new_style(tx, pool):
143
+ return True
144
+ print(
145
+ f"curve pool no match: {tx}\n"
146
+ f"symbol={tx.symbol}\n"
147
+ f"name={tx.token.name}\n"
148
+ f"token_address={tx.token_address}\n"
149
+ f"event_address={pool.address}"
150
+ )
151
+ # Tokens rec'd
152
+ elif tx.from_address == event.address and TreasuryWallet.check_membership(
153
+ tx.to_address.address, tx.block # type: ignore [union-attr, arg-type]
154
+ ):
155
+ tx_amount = round(tx.amount, 7)
156
+ try:
157
+ for i, amount in enumerate(event["token_amounts"]):
158
+ # TODO: get rid of this rounding when we migrate to postgres
159
+ event_amount = round(tx.token.scale_value(amount), 7)
160
+ if tx_amount == event_amount:
161
+ pool = await Contract.coroutine(event.address) # type: ignore [assignment]
162
+ if hasattr(pool, "underlying_coins"):
163
+ coin: ChecksumAddress = await pool.underlying_coins.coroutine(i)
164
+ return tx.token == coin
165
+ else:
166
+ return tx.token == await _get_coin_at_index(pool, i)
167
+ else:
168
+ print(
169
+ f"Curve withdrawal multi amount does not match: {tx_amount} {event_amount}"
170
+ )
171
+ except EventLookupError:
172
+ # some other event has different keys, maybe we need to implement logic to capture these. time will tell.
173
+ pass
174
+ return False
@@ -0,0 +1,36 @@
1
+ """
2
+ Ignore rules for Gearbox protocol transactions.
3
+
4
+ This module defines matching logic for Gearbox protocol deposit and
5
+ withdrawal swaps, so these transactions can be filtered from analytics
6
+ and reporting.
7
+ """
8
+
9
+ from dao_treasury import TreasuryTx
10
+ from y import Network
11
+
12
+ from yearn_treasury.rules.ignore.swaps import swaps
13
+
14
+ gearbox = swaps("Gearbox")
15
+
16
+
17
+ @gearbox("Deposit", Network.Mainnet)
18
+ def is_gearbox_deposit(tx: TreasuryTx) -> bool:
19
+ txhash = tx.hash
20
+ log_index = tx.log_index
21
+ return (
22
+ txhash == "0x5666b03add778468482fb376e65761128f9f5051b487f3efc996a55c3620d6d4"
23
+ and log_index in (366, 367)
24
+ ) or (
25
+ txhash == "0x9e113dda11fcd758df2fe94a641aa7afe6329afec4097a8cb5d6fb68489cf7d8"
26
+ and log_index in (74, 75)
27
+ )
28
+
29
+
30
+ @gearbox("Withdrawal", Network.Mainnet)
31
+ def is_gearbox_withdrawal(tx: TreasuryTx) -> bool:
32
+ txhash = tx.hash
33
+ return txhash == "0xb98d8f4dd3d9de50e6fec700fb8e5a732e5a564b7edfe365f97e601694536bb5" or (
34
+ txhash == "0x1d9e7930d0bf6725a4ffff43e284dfa9d10e34e16460e75d01a7f05a98e252a6"
35
+ and tx.log_index in (212, 213)
36
+ )
@@ -0,0 +1,41 @@
1
+ from typing import Final, cast
2
+
3
+ from dao_treasury import TreasuryTx
4
+ from eth_typing import ChecksumAddress
5
+ from y import Contract, Network
6
+
7
+ from yearn_treasury.constants import ZERO_ADDRESS
8
+ from yearn_treasury.rules.ignore.swaps import swaps
9
+
10
+ IEARN: Final[dict[str, ChecksumAddress]] = {
11
+ # v1 - deprecated
12
+ # v2
13
+ "yDAIv2": "0x16de59092dAE5CcF4A1E6439D611fd0653f0Bd01",
14
+ "yUSDCv2": "0xd6aD7a6750A7593E092a9B218d66C0A814a3436e",
15
+ "yUSDTv2": "0x83f798e925BcD4017Eb265844FDDAbb448f1707D",
16
+ "ysUSDv2": "0xF61718057901F84C4eEC4339EF8f0D86D2B45600",
17
+ "yTUSDv2": "0x73a052500105205d34daf004eab301916da8190f",
18
+ "yWBTCv2": "0x04Aa51bbcB46541455cCF1B8bef2ebc5d3787EC9",
19
+ # v3
20
+ "yDAIv3": "0xC2cB1040220768554cf699b0d863A3cd4324ce32",
21
+ "yUSDCv3": "0x26EA744E5B887E5205727f55dFBE8685e3b21951",
22
+ "yUSDTv3": "0xE6354ed5bC4b393a5Aad09f21c46E101e692d447",
23
+ "yBUSDv3": "0x04bC0Ab673d88aE9dbC9DA2380cB6B79C4BCa9aE",
24
+ }
25
+
26
+ POOLS: Final = set(IEARN.values())
27
+
28
+ POOL_TO_UNDERLYING: Final[dict[ChecksumAddress, ChecksumAddress]] = {
29
+ pool: ChecksumAddress(Contract(pool).token()) for pool in POOLS
30
+ }
31
+
32
+
33
+ @swaps("iEarn:Withdrawal", Network.Mainnet)
34
+ def is_iearn_withdrawal(tx: TreasuryTx) -> bool:
35
+ # Vault side
36
+ if tx.to_address == ZERO_ADDRESS:
37
+ return tx.token_address in POOLS
38
+ # Token side
39
+ from_address = cast(ChecksumAddress, tx.from_address.address)
40
+ token_address = tx.token_address
41
+ return POOL_TO_UNDERLYING.get(from_address) == token_address
@@ -0,0 +1,58 @@
1
+ from typing import Final
2
+
3
+ from dao_treasury import TreasuryTx
4
+ from y import Network
5
+
6
+ from yearn_treasury.constants import CHAINID
7
+ from yearn_treasury.rules.ignore.swaps import swaps
8
+
9
+
10
+ @swaps("OTC")
11
+ def is_otc_swap(tx: TreasuryTx) -> bool:
12
+ txhash = tx.hash
13
+ log_index = tx.log_index
14
+ for otc_swap in _OTC_SWAPS:
15
+ if isinstance(otc_swap, tuple):
16
+ if txhash == otc_swap[0] and log_index in otc_swap[1]:
17
+ return True
18
+ else:
19
+ if txhash == otc_swap:
20
+ return True
21
+ return False
22
+
23
+
24
+ _OTC_SWAPS: Final = {
25
+ Network.Mainnet: (
26
+ "0xd59dfba383c0a7d5f0e30124888fa6d9c2c964755fb9bed8f22483feb292c1e9",
27
+ "0xa00430b408c75dc432fcc0bbcabc5c3c63196addab532eecd233f6e80b295990",
28
+ "0x3419d8378321b5cb59c69584693ef59a65aeee4591e7e96c31f31906bc9a627a",
29
+ "0x30afed767aafd21696242c6a54576afc6598e976b969ffe50591360c729ef35a",
30
+ # Emergency dump of yvUSDN
31
+ "0xb22e345f58d7fe40257e41bac5d59ca74af8f6cc1e220aedf6f97113e4ace53a",
32
+ "0xd6bcaf0f144201d5c6affd73746ae57a262dbf00b957534a7b22bc0473bd589b",
33
+ # deprecated vault tokens
34
+ "0xf60060f25ae9f7d377741cde14d374a665dc8f1bff44f6fb231a1d89ac403711",
35
+ # ~8900 USDC sent back
36
+ "0xce4a854560f5b8f5d1790b7828ce90147eafee2f75cfc4009581977eebff8d51",
37
+ # "I moved them I moved them from yTrades to my EOA to dump since the liquidity was insanely small for OGV (mega price impact on cowswap) and there wasn't enough of VEC to justify cowswap"
38
+ # "I sold them to eth over time in my deployer EOA and am just gonna use it for gas"
39
+ "0x4713d14c624e0d4489980c91d3dc19fe468a9f0ad9c9b90fe4b7e55d9e67034e",
40
+ # vault tokens sent to swapper msig
41
+ (
42
+ "0xae7d281b8a093da60d39179452d230de2f1da4355df3aea629d969782708da5d",
43
+ (258, 262, 267, 272, 276),
44
+ ),
45
+ # ~9136 crvUSD returned to treasury
46
+ "0xac1f2a5e2960577e54c4a9cd096763cb6df614aa28eff221aeb4159097d9fa0f",
47
+ # ~8112 USDC returned to treasury
48
+ "0x015cdac2a021a44404c56600a96acfe2cb768e8789031b150be51db18874ec77",
49
+ # one-off dumping 1INCH (on 1INCH not otc but this works)
50
+ "0x037477c516652437004050e955edb6bc0de82a6b0f03e7665009e802c196516f",
51
+ # not otc swap, but swapped by 0x444 so close enough
52
+ ("0xd7e7abe600aad4a3181a3a410bef2539389579d2ed28f3e75dbbf3a7d8613688", (558, 559)),
53
+ "0x5a65d5299864ae6db364ee6a459a4f50d19e6fa8892f4f4c0221372b6c9b3ca2",
54
+ "0x71bd987e89940185b1131a6b73b981f5716c767ac12d106bf226a1aa8880f7c8",
55
+ ),
56
+ }.get(
57
+ CHAINID, ()
58
+ ) # type: ignore [call-overload]
@@ -0,0 +1,23 @@
1
+ """
2
+ Ignore rules for PoolTogether protocol transactions.
3
+
4
+ This module defines matching logic for PoolTogether deposits swaps,
5
+ as they can be safely ignored in analytics and reporting.
6
+ """
7
+
8
+ from dao_treasury import TreasuryTx
9
+ from y import Network
10
+
11
+ from yearn_treasury.constants import ZERO_ADDRESS
12
+ from yearn_treasury.rules.ignore.swaps import swaps
13
+
14
+
15
+ @swaps("PoolTogether:Deposit", Network.Mainnet)
16
+ def is_pooltogether_deposit(tx: TreasuryTx) -> bool:
17
+ # TODO: figure out what was done with the withdrawals and put a note here
18
+ symbol = tx.symbol
19
+ return (
20
+ symbol == "POOL" and tx.to_address.address == "0x396b4489da692788e327E2e4b2B0459A5Ef26791"
21
+ ) or ( # type: ignore [union-attr]
22
+ symbol == "PPOOL" and tx.from_address.address == ZERO_ADDRESS
23
+ ) # type: ignore [union-attr]
@@ -0,0 +1,10 @@
1
+ from dao_treasury import TreasuryTx
2
+ from y import Network
3
+
4
+ from yearn_treasury.rules.ignore.swaps import swaps
5
+
6
+
7
+ @swaps("Synthetix", Network.Mainnet)
8
+ def is_synthetix_swap(tx: TreasuryTx) -> bool:
9
+ # TODO Figure out hueristics for sorting these if they become more frequent
10
+ return tx.hash == "0x5a55121911d9a3992fc1ea9504da9b86331da2148822d88c16f805b2c6b2c753"