yearn-treasury 0.1.6__cp312-cp312-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 +20 -0
  2. yearn_treasury/_db.cp312-win32.pyd +0 -0
  3. yearn_treasury/_db.py +51 -0
  4. yearn_treasury/_ens.cp312-win32.pyd +0 -0
  5. yearn_treasury/_ens.py +31 -0
  6. yearn_treasury/_logging.cp312-win32.pyd +0 -0
  7. yearn_treasury/_logging.py +43 -0
  8. yearn_treasury/address_labels.yaml +39 -0
  9. yearn_treasury/budget/__init__.cp312-win32.pyd +0 -0
  10. yearn_treasury/budget/__init__.py +6 -0
  11. yearn_treasury/budget/_request.cp312-win32.pyd +0 -0
  12. yearn_treasury/budget/_request.py +44 -0
  13. yearn_treasury/budget/_requests.cp312-win32.pyd +0 -0
  14. yearn_treasury/budget/_requests.py +96 -0
  15. yearn_treasury/constants.py +92 -0
  16. yearn_treasury/main.py +176 -0
  17. yearn_treasury/py.typed +1 -0
  18. yearn_treasury/rules/__init__.py +20 -0
  19. yearn_treasury/rules/constants.cp312-win32.pyd +0 -0
  20. yearn_treasury/rules/constants.py +17 -0
  21. yearn_treasury/rules/cost_of_revenue/__init__.py +1 -0
  22. yearn_treasury/rules/cost_of_revenue/gas.cp312-win32.pyd +0 -0
  23. yearn_treasury/rules/cost_of_revenue/gas.py +66 -0
  24. yearn_treasury/rules/cost_of_revenue/match_on_hash.yaml +12 -0
  25. yearn_treasury/rules/expense/__init__.cp312-win32.pyd +0 -0
  26. yearn_treasury/rules/expense/__init__.py +4 -0
  27. yearn_treasury/rules/expense/general.cp312-win32.pyd +0 -0
  28. yearn_treasury/rules/expense/general.py +13 -0
  29. yearn_treasury/rules/expense/infrastructure.cp312-win32.pyd +0 -0
  30. yearn_treasury/rules/expense/infrastructure.py +47 -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.cp312-win32.pyd +0 -0
  34. yearn_treasury/rules/expense/people.py +84 -0
  35. yearn_treasury/rules/expense/security.cp312-win32.pyd +0 -0
  36. yearn_treasury/rules/expense/security.py +147 -0
  37. yearn_treasury/rules/ignore/__init__.py +8 -0
  38. yearn_treasury/rules/ignore/general.cp312-win32.pyd +0 -0
  39. yearn_treasury/rules/ignore/general.py +11 -0
  40. yearn_treasury/rules/ignore/maker.py +92 -0
  41. yearn_treasury/rules/ignore/passthru.py +310 -0
  42. yearn_treasury/rules/ignore/staking.py +102 -0
  43. yearn_treasury/rules/ignore/swaps/__init__.py +25 -0
  44. yearn_treasury/rules/ignore/swaps/_skip_tokens.py +9 -0
  45. yearn_treasury/rules/ignore/swaps/aave.py +69 -0
  46. yearn_treasury/rules/ignore/swaps/auctions.cp312-win32.pyd +0 -0
  47. yearn_treasury/rules/ignore/swaps/auctions.py +31 -0
  48. yearn_treasury/rules/ignore/swaps/compound.py +58 -0
  49. yearn_treasury/rules/ignore/swaps/conversion_factory.cp312-win32.pyd +0 -0
  50. yearn_treasury/rules/ignore/swaps/conversion_factory.py +21 -0
  51. yearn_treasury/rules/ignore/swaps/cowswap.py +87 -0
  52. yearn_treasury/rules/ignore/swaps/curve.py +176 -0
  53. yearn_treasury/rules/ignore/swaps/gearbox.cp312-win32.pyd +0 -0
  54. yearn_treasury/rules/ignore/swaps/gearbox.py +37 -0
  55. yearn_treasury/rules/ignore/swaps/iearn.cp312-win32.pyd +0 -0
  56. yearn_treasury/rules/ignore/swaps/iearn.py +43 -0
  57. yearn_treasury/rules/ignore/swaps/otc.cp312-win32.pyd +0 -0
  58. yearn_treasury/rules/ignore/swaps/otc.py +58 -0
  59. yearn_treasury/rules/ignore/swaps/pooltogether.cp312-win32.pyd +0 -0
  60. yearn_treasury/rules/ignore/swaps/pooltogether.py +23 -0
  61. yearn_treasury/rules/ignore/swaps/synthetix.cp312-win32.pyd +0 -0
  62. yearn_treasury/rules/ignore/swaps/synthetix.py +10 -0
  63. yearn_treasury/rules/ignore/swaps/uniswap.py +294 -0
  64. yearn_treasury/rules/ignore/swaps/unwrapper.cp312-win32.pyd +0 -0
  65. yearn_treasury/rules/ignore/swaps/unwrapper.py +17 -0
  66. yearn_treasury/rules/ignore/swaps/vaults.cp312-win32.pyd +0 -0
  67. yearn_treasury/rules/ignore/swaps/vaults.py +264 -0
  68. yearn_treasury/rules/ignore/swaps/woofy.cp312-win32.pyd +0 -0
  69. yearn_treasury/rules/ignore/swaps/woofy.py +80 -0
  70. yearn_treasury/rules/ignore/swaps/yfi.cp312-win32.pyd +0 -0
  71. yearn_treasury/rules/ignore/swaps/yfi.py +111 -0
  72. yearn_treasury/rules/ignore/swaps/yla.cp312-win32.pyd +0 -0
  73. yearn_treasury/rules/ignore/swaps/yla.py +28 -0
  74. yearn_treasury/rules/ignore/unit.cp312-win32.pyd +0 -0
  75. yearn_treasury/rules/ignore/unit.py +40 -0
  76. yearn_treasury/rules/ignore/weth.cp312-win32.pyd +0 -0
  77. yearn_treasury/rules/ignore/weth.py +48 -0
  78. yearn_treasury/rules/ignore/ygov.cp312-win32.pyd +0 -0
  79. yearn_treasury/rules/ignore/ygov.py +16 -0
  80. yearn_treasury/rules/other_expense/__init__.cp312-win32.pyd +0 -0
  81. yearn_treasury/rules/other_expense/__init__.py +7 -0
  82. yearn_treasury/rules/other_expense/boost.cp312-win32.pyd +0 -0
  83. yearn_treasury/rules/other_expense/boost.py +49 -0
  84. yearn_treasury/rules/other_expense/bugs.cp312-win32.pyd +0 -0
  85. yearn_treasury/rules/other_expense/bugs.py +81 -0
  86. yearn_treasury/rules/other_expense/donations.cp312-win32.pyd +0 -0
  87. yearn_treasury/rules/other_expense/donations.py +43 -0
  88. yearn_treasury/rules/other_expense/dyfi.cp312-win32.pyd +0 -0
  89. yearn_treasury/rules/other_expense/dyfi.py +29 -0
  90. yearn_treasury/rules/other_expense/events.cp312-win32.pyd +0 -0
  91. yearn_treasury/rules/other_expense/events.py +21 -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.cp312-win32.pyd +0 -0
  95. yearn_treasury/rules/other_expense/misc.py +49 -0
  96. yearn_treasury/rules/other_expense/revshare.cp312-win32.pyd +0 -0
  97. yearn_treasury/rules/other_expense/revshare.py +20 -0
  98. yearn_treasury/rules/other_income/__init__.cp312-win32.pyd +0 -0
  99. yearn_treasury/rules/other_income/__init__.py +2 -0
  100. yearn_treasury/rules/other_income/airdrops.cp312-win32.pyd +0 -0
  101. yearn_treasury/rules/other_income/airdrops.py +30 -0
  102. yearn_treasury/rules/other_income/match_on_hash.yaml +21 -0
  103. yearn_treasury/rules/other_income/misc.cp312-win32.pyd +0 -0
  104. yearn_treasury/rules/other_income/misc.py +80 -0
  105. yearn_treasury/rules/revenue/__init__.py +6 -0
  106. yearn_treasury/rules/revenue/bribes.cp312-win32.pyd +0 -0
  107. yearn_treasury/rules/revenue/bribes.py +26 -0
  108. yearn_treasury/rules/revenue/farming.cp312-win32.pyd +0 -0
  109. yearn_treasury/rules/revenue/farming.py +56 -0
  110. yearn_treasury/rules/revenue/keepcoins.cp312-win32.pyd +0 -0
  111. yearn_treasury/rules/revenue/keepcoins.py +63 -0
  112. yearn_treasury/rules/revenue/match_on_hash.yaml +4 -0
  113. yearn_treasury/rules/revenue/seasolver.cp312-win32.pyd +0 -0
  114. yearn_treasury/rules/revenue/seasolver.py +23 -0
  115. yearn_treasury/rules/revenue/vaults.py +172 -0
  116. yearn_treasury/rules/revenue/yteams.cp312-win32.pyd +0 -0
  117. yearn_treasury/rules/revenue/yteams.py +17 -0
  118. yearn_treasury/shitcoins.py +144 -0
  119. yearn_treasury/vaults.cp312-win32.pyd +0 -0
  120. yearn_treasury/vaults.py +50 -0
  121. yearn_treasury/wallets.yaml +54 -0
  122. yearn_treasury/yteams.py +208 -0
  123. yearn_treasury-0.1.6.dist-info/METADATA +85 -0
  124. yearn_treasury-0.1.6.dist-info/RECORD +128 -0
  125. yearn_treasury-0.1.6.dist-info/WHEEL +5 -0
  126. yearn_treasury-0.1.6.dist-info/entry_points.txt +2 -0
  127. yearn_treasury-0.1.6.dist-info/top_level.txt +2 -0
  128. yearn_treasury__mypyc.cp312-win32.pyd +0 -0
@@ -0,0 +1,111 @@
1
+ import decimal
2
+ from typing import Final
3
+
4
+ from brownie.exceptions import EventLookupError
5
+ from dao_treasury import TreasuryTx
6
+ from y import WRAPPED_GAS_COIN, Network
7
+
8
+ from yearn_treasury.constants import YCHAD_MULTISIG
9
+ from yearn_treasury.rules.ignore.swaps import swaps
10
+
11
+
12
+ buying_yfi: Final = swaps("Buying YFI")
13
+
14
+ VYPER_BUYERS: Final = (
15
+ "0xdf5e4E54d212F7a01cf94B3986f40933fcfF589F", # buys YFI for DAI at the current chainlink price
16
+ "0x6903223578806940bd3ff0C51f87aa43968424c8", # buys YFI for DAI at the current chainlink price. Can be funded via llamapay stream.
17
+ )
18
+ """These contracts, now retired, previously were used to purchase YFI for DAI at the current chainlink market price."""
19
+
20
+
21
+ YFI_BUYBACK_AUCTIONS: Final = "0x4349ed200029e6Cf38F1455B9dA88981F1806df3"
22
+
23
+
24
+ Decimal: Final = decimal.Decimal
25
+
26
+
27
+ @buying_yfi("Top-up Buyer Contract", Network.Mainnet)
28
+ def is_buyer_top_up(tx: TreasuryTx) -> bool:
29
+ """
30
+ The sell side of these transactions is in :func:`is_buying_with_buyer`.
31
+ The buyer is topped up with DAI regularly and buys YFI at the current chainlink market price.
32
+
33
+ # TODO: amortize this into a daily expense
34
+ """
35
+ return tx.symbol == "DAI" and tx.to_address.address in VYPER_BUYERS # type: ignore [union-attr]
36
+
37
+
38
+ @buying_yfi("Buyer Contract", Network.Mainnet)
39
+ def is_buying_with_buyer(tx: TreasuryTx) -> bool:
40
+ """
41
+ The buy side of these transactions is in :func:`is_buyer_top_up`.
42
+ The buyer is topped up with DAI regularly and buys YFI at the current chainlink market price
43
+ """
44
+ if tx.symbol == "YFI" and tx.to_address.address == YCHAD_MULTISIG: # type: ignore [union-attr]
45
+ try:
46
+ events = tx.events
47
+ except KeyError as e:
48
+ if "components" in str(e):
49
+ print(f"cannot parse events of possible YFI buyback {tx}")
50
+ return False
51
+ raise
52
+
53
+ if "Buyback" in events:
54
+ buyback_events = events["Buyback"]
55
+ if len(buyback_events) > 1:
56
+ print(f"Must code handler for multiple Buyback events in one tx: {tx}")
57
+ return False
58
+ buyback_event = buyback_events[0]
59
+ if buyback_event.address in VYPER_BUYERS and all( # type: ignore [attr-defined]
60
+ arg in buyback_event for arg in ("buyer", "yfi", "dai")
61
+ ):
62
+ # TODO get rid of this rounding once we've swapped out sqlite for postgres
63
+ buyback_amount = Decimal(buyback_event["yfi"]) / 10**18 # type: ignore [call-overload]
64
+ if round(tx.amount, 14) == round(buyback_amount, 14):
65
+ return True
66
+ print(
67
+ f"from node: {buyback_amount} "
68
+ f"from db: {tx.amount} "
69
+ f"diff: {buyback_amount - tx.amount}"
70
+ )
71
+ else:
72
+ print("unhandled Buyback event: buyback_event")
73
+ return False
74
+
75
+
76
+ @buying_yfi("Buyback Auction", Network.Mainnet)
77
+ def is_buying_with_auction(tx: TreasuryTx) -> bool:
78
+ try:
79
+ if tx.symbol != "YFI" or tx.to_address != YCHAD_MULTISIG or "AuctionTaken" not in tx.events:
80
+ return False
81
+ except EventLookupError:
82
+ return False
83
+ except KeyError as e:
84
+ # TODO: diagnose and fix this, pretty sure it's in eth-event
85
+ if "components" not in str(e):
86
+ raise
87
+ return False
88
+
89
+ auctions_taken = tx.get_events("AuctionTaken")
90
+ if len(auctions_taken) == 0:
91
+ return False
92
+ if len(auctions_taken) > 1:
93
+ raise NotImplementedError("we need new code to handle this case")
94
+ event = auctions_taken[0]
95
+ if event.address != YFI_BUYBACK_AUCTIONS: # type: ignore [attr-defined]
96
+ raise ValueError(event.address, event) # type: ignore [attr-defined]
97
+ # did the auction contract send weth to tx.sender?
98
+ for transfer in tx.get_events("Transfer"):
99
+ if transfer.address == WRAPPED_GAS_COIN:
100
+ sender, receiver, amount = transfer.values()
101
+ if sender != YFI_BUYBACK_AUCTIONS:
102
+ print(f"Transfer sender is not YFI_BUYBACK_AUCTIONS: sender={sender} YFI_BUYBACK_AUCTIONS={YFI_BUYBACK_AUCTIONS}") # type: ignore [union-attr]
103
+ continue
104
+ if tx.from_address != receiver:
105
+ print(f"Transfer does not match auction taker: taker={tx.from_address.address} transfer={receiver}") # type: ignore [union-attr]
106
+ continue
107
+ # TODO get rid of this rounding once we've swapped out sqlite for postgres
108
+ if round(amount, 14) == round(event["taken"], 14): # type: ignore [call-overload]
109
+ return True
110
+ print(f"AuctionTaken: {event} amount does not match Transfer: {transfer}")
111
+ return False
@@ -0,0 +1,28 @@
1
+ from typing import Final
2
+
3
+ from dao_treasury import TreasuryTx
4
+ from y import Network
5
+
6
+ from yearn_treasury.rules.ignore.swaps import swaps
7
+
8
+
9
+ yla: Final = swaps("Yearn Lazy Ape")
10
+
11
+
12
+ @yla("Deposit", Network.Mainnet)
13
+ def is_yla_deposit(tx: TreasuryTx) -> bool:
14
+ return tx.hash == "0x1d4e974db2d60ebd994410fcd793c5db771af9a14660015faf94cbdaec285009" and (
15
+ tx.symbol == "YLA" or tx.to_address.address == "0x9ba60bA98413A60dB4C651D4afE5C937bbD8044B" # type: ignore [union-attr]
16
+ )
17
+
18
+
19
+ @yla("Withdrawal", Network.Mainnet)
20
+ def is_yla_withdrawal(tx: TreasuryTx) -> bool:
21
+ return (
22
+ "0x85c6D6b0cd1383Cc85e8e36C09D0815dAf36b9E9"
23
+ in (
24
+ tx.from_address.address, # type: ignore [union-attr]
25
+ tx.to_address.address, # type: ignore [union-attr]
26
+ )
27
+ or tx.hash == "0xb1ed399c268dfaf9917e20270cb720ab95986630b6cd4cabd7f02bb55ad5f7c6"
28
+ )
@@ -0,0 +1,40 @@
1
+ """
2
+ Ignore rules for Unit.xyz protocol.
3
+
4
+ This module defines matching logic for Unit.xyz protocol transactions,
5
+ so they can be ignored in analytics and reporting.
6
+ """
7
+
8
+ from typing import Final
9
+
10
+ from dao_treasury import TreasuryTx, ignore
11
+ from y import Network
12
+
13
+ from yearn_treasury.constants import ZERO_ADDRESS
14
+
15
+
16
+ UNIT_XYZ_VAULT: Final = "0xb1cFF81b9305166ff1EFc49A129ad2AfCd7BCf19"
17
+
18
+ unit: Final = ignore("Unit.xyz")
19
+ collateral: Final = unit("Collateral")
20
+ usdp: Final = unit("USDP")
21
+
22
+
23
+ @collateral("YFI Deposit", Network.Mainnet)
24
+ def is_unit_yfi_deposit(tx: TreasuryTx) -> bool:
25
+ return tx.symbol == "YFI" and tx.to_address.address == UNIT_XYZ_VAULT # type: ignore [union-attr]
26
+
27
+
28
+ @collateral("YFI Withdrawal", Network.Mainnet)
29
+ def is_unit_yfi_withdrawal(tx: TreasuryTx) -> bool:
30
+ return tx.symbol == "YFI" and tx.from_address.address == UNIT_XYZ_VAULT # type: ignore [union-attr]
31
+
32
+
33
+ @usdp("Minting", Network.Mainnet)
34
+ def is_minting_usdp(tx: TreasuryTx) -> bool:
35
+ return tx.symbol == "USDP" and tx.from_address.address == ZERO_ADDRESS # type: ignore [union-attr]
36
+
37
+
38
+ @usdp("Burning", Network.Mainnet)
39
+ def is_burning_usdp(tx: TreasuryTx) -> bool:
40
+ return tx.symbol == "USDP" and tx.to_address.address == ZERO_ADDRESS # type: ignore [union-attr]
@@ -0,0 +1,48 @@
1
+ """
2
+ Ignore rules for WETH minting and burning.
3
+
4
+ This module defines matching logic for WETH minting and burning
5
+ transactions, so those transactions can be ignored in analytics
6
+ and reporting.
7
+ """
8
+
9
+ from typing import Final
10
+
11
+ import y
12
+ from dao_treasury import TreasuryTx, TreasuryWallet, ignore
13
+ from eth_typing import ChecksumAddress
14
+
15
+ from yearn_treasury.rules.constants import EEE_ADDRESS, ZERO_ADDRESS
16
+
17
+
18
+ weth: Final[ChecksumAddress] = y.weth.address # type: ignore [assignment]
19
+
20
+
21
+ @ignore("WETH:Minting")
22
+ def is_weth_mint(tx: TreasuryTx) -> bool:
23
+ if (
24
+ tx.from_address == ZERO_ADDRESS
25
+ and TreasuryWallet.check_membership(tx.to_address.address, tx.block) # type: ignore [union-attr, arg-type]
26
+ and tx.token == weth
27
+ ):
28
+ return True
29
+ return bool(
30
+ TreasuryWallet.check_membership(tx.from_address.address, tx.block) # type: ignore [union-attr, arg-type]
31
+ and tx.to_address == weth
32
+ and tx.token == EEE_ADDRESS
33
+ )
34
+
35
+
36
+ @ignore("WETH:Burning")
37
+ def is_weth(tx: TreasuryTx) -> bool:
38
+ if (
39
+ TreasuryWallet.check_membership(tx.from_address.address, tx.block) # type: ignore [union-attr, arg-type]
40
+ and tx.to_address == ZERO_ADDRESS
41
+ and tx.token == weth
42
+ ):
43
+ return True
44
+ return bool(
45
+ tx.from_address == weth
46
+ and TreasuryWallet.check_membership(tx.to_address.address, tx.block) # type: ignore [union-attr, arg-type]
47
+ and tx.token == EEE_ADDRESS
48
+ )
@@ -0,0 +1,16 @@
1
+ from typing import Final
2
+
3
+ from dao_treasury import TreasuryTx, ignore
4
+ from y import Network
5
+
6
+
7
+ YGOV: Final = "0xBa37B002AbaFDd8E89a1995dA52740bbC013D992"
8
+
9
+
10
+ @ignore("Transfer to yGov (Deprecated)", Network.Mainnet)
11
+ def is_sent_to_ygov(tx: TreasuryTx) -> bool:
12
+ return (
13
+ tx.from_nickname == "Yearn Treasury"
14
+ and tx.symbol == "yDAI+yUSDC+yUSDT+yTUSD"
15
+ and tx.to_address == YGOV
16
+ )
@@ -0,0 +1,7 @@
1
+ from yearn_treasury.rules.other_expense.boost import *
2
+ from yearn_treasury.rules.other_expense.bugs import *
3
+ from yearn_treasury.rules.other_expense.donations import *
4
+ from yearn_treasury.rules.other_expense.dyfi import *
5
+ from yearn_treasury.rules.other_expense.events import *
6
+ from yearn_treasury.rules.other_expense.misc import *
7
+ from yearn_treasury.rules.other_expense.revshare import *
@@ -0,0 +1,49 @@
1
+ from dao_treasury import TreasuryTx, other_expense
2
+ from y import Network
3
+
4
+
5
+ @other_expense("Buying CRV For Boosties", Network.Mainnet)
6
+ def is_buying_crv_for_boost(tx: TreasuryTx) -> bool:
7
+ symbol = tx.symbol
8
+ to_nickname = tx.to_nickname
9
+ from_nickname = tx.from_nickname
10
+
11
+ return (
12
+ (
13
+ (symbol == "DAI" and to_nickname == "CRV Buyer Contract (DAI)")
14
+ or (symbol == "CRV" and from_nickname == "CRV Buyer Contract (DAI)")
15
+ )
16
+ or (
17
+ (symbol == "USDT" and to_nickname == "CRV Buyer Contract (USDT)")
18
+ or (symbol == "CRV" and from_nickname == "CRV Buyer Contract (USDT)")
19
+ )
20
+ or "0x3D71d79C224998E608d03C5Ec9B405E7a38505F0"
21
+ in (tx.to_address.address, tx.from_address.address)
22
+ or tx.hash
23
+ in { # type: ignore [union-attr]
24
+ # bought via some multi-token buyer contract that probably doesnt need hueristics
25
+ "0x2391a566b567528ad838169804c77b67ee9724acd174ae6d8a5ebbb715870c35",
26
+ "0xd04e5b2b19b2e88d72426d08cb04a54b64d788309787caacfcdb0a4bd440503f",
27
+ "0x000f6a0140da4a5c70e671523c8b8406ee8353c973b700dcc575ca1f347628af",
28
+ "0x8d7e61b2c6b4e3554258c0f383baee9afc26f60a01d5cdc4a178840f9b506cce",
29
+ "0x2ebb191b54e7b2d9916d36462a211e416781a873bac630c32c5e771192410e14",
30
+ "0x4a8a8ddbca5b4debdc298c3ed39149f8933b79b937aa71b9e8d969c5fd691865",
31
+ # and these from some different one
32
+ "0xb87eb568fb662b28b61bfb4fa477d6db59e8c5c0eb8107cb5f7aa6ad0be4292c",
33
+ "0xe2d6420b3eae91634e6b06f4c1d2d7e25e5277f7f945c98731daccb005513f11",
34
+ "0xd5b506d20d35daf583350d5f7cfbf8f827cbe78326d36dbf02bbbbede7bbb0b2",
35
+ "0x54e88407a9a7161bc259b1d9193a0cec8152c976cf985ccdd9ab1c23e80ce112",
36
+ "0x6fd9d2da32a1b5b4b9e61a1659900ebb54c45b2a6254d79d84cb8cd9fe06c474",
37
+ # and another
38
+ "0x3fa631fe04338ffd71d07c05d5a6d93c4f8c6bbe435a0af17bf819e43d31f8b3",
39
+ "0xf5aa2466338bb9d134c7a7dfe9a42aefa4348684ce2fab3ce655acf5925da8fe",
40
+ "0xc945264eef9e494251bdc3c23147fa7fde7c4115f94c8feae9826bc06dd0338c",
41
+ "0x7c365f0afa683727163ee627e5cdab607be70e1c6beee3e3d0c2e35b0e366bde",
42
+ "0xf0a946524c4b244b626bdddb9ef07051a3252dfa18caac7a8e66ec365655a15f",
43
+ "0xc8ac7d1ec0631723846e170fb22aab5881c15ccf4fdae15dbe283cd38d782ea7",
44
+ # bought via 0x protocol
45
+ "0x2367da0c38d9c5b7fb0e422ce364ae9c8fbb74567a96f94078c58d9f9e0809ac",
46
+ "0x2f5c5e6ba0633d097c99d0bf64e4a96f5f440c6eab2197565e83435f96473ed1",
47
+ "0xcf2f0cfe8c5a1b848b57d5cebd5375335ae889f2075373e23f50a3c65a03b2b2",
48
+ }
49
+ )
@@ -0,0 +1,81 @@
1
+ from dao_treasury import TreasuryTx, other_expense
2
+ from y import Network
3
+
4
+
5
+ bugs = other_expense("Bug Reimbursements")
6
+
7
+
8
+ @bugs("yDAI Fee Calculation Bug", Network.Mainnet)
9
+ def is_double_fee_reimbursement(tx: TreasuryTx) -> bool:
10
+ """
11
+ Due to new single-sided strats that deposit into other vaults,
12
+ some users were accidentally charged 2x the expected withdrawal fee.
13
+ """
14
+ return tx.from_nickname == "Disperse.app" and tx.hash in [
15
+ "0x4ce0c829fb46fc1ea03e434599a68af4c6f65f80aff7e934a008c0fe63e9da3f",
16
+ "0x90b54bf0d35621160b5094c263a2684f8e7b37fc6467c8c1ce6a53e2e7acbfa1",
17
+ "0x2f667223aaefc4b153c28440d151fdb19333aff5d052c0524f2804fbd5a7964c",
18
+ ]
19
+
20
+
21
+ @bugs("yYFI Fee Calculation Bug", Network.Mainnet)
22
+ def is_yyfi_fee_reimbursement(tx: TreasuryTx) -> bool:
23
+ return (
24
+ tx.from_nickname == "Disperse.app"
25
+ and tx.hash == "0x867b547b67910a08c939978d8071acca28ecc444d7155c0626e87730f67c058c"
26
+ )
27
+
28
+
29
+ @bugs("yvCurve-IB Fee Calculation Bug", Network.Mainnet)
30
+ def is_lossy_fee_reimbursement(tx: TreasuryTx) -> bool:
31
+ """old vault code doesn't prevent fees from making harvest lossy. so here we airdrop the fee-take back to vault and do some housekeeper to prevent this from happening on other strats."""
32
+ return (
33
+ tx.hash == "0x61eea3d40b2dc8586a5d20109ed962998c43cc55a37c300f283820150490eaa0"
34
+ and tx.log_index == 179
35
+ )
36
+
37
+
38
+ @bugs("Reimburse st-yCRV User", Network.Mainnet)
39
+ def is_stycrv(tx: TreasuryTx) -> bool:
40
+ """Some user lost some funds in a minor issue, then was reimbursed."""
41
+ return (
42
+ tx.hash == "0x491f07d134f3253ef06a2b46d83b82cdf2927b13cce4d38225d92ce01799da96"
43
+ and tx.log_index == 197
44
+ )
45
+
46
+
47
+ @bugs("Slippage Bug", Network.Mainnet)
48
+ def is_slippage_bug_reimbursement(tx: TreasuryTx) -> bool:
49
+ """a swap tx was messed up so Yearn sent treasury funds to the relevant strategy to compensate"""
50
+ txhash = tx.hash
51
+ if txhash in [
52
+ "0xffe3883e34ae0b6ae3a7f304f00c625a7b315a021cf38f47a932e81d3f1c371c",
53
+ "0x42cfcaa06beebe61547724f22fa790c763b2937ca2af8e3d5dbc680b903aad69",
54
+ ]:
55
+ return True
56
+
57
+ other = {
58
+ # separate slippage event
59
+ "0xc179e27f0e38bca52744d71dc6ff2463ed10fa918908ce28adcf4f4c0d6d6a1e": 103,
60
+ "0x51c611597574aaa3b829004363476b1c2a4dc2941dff695c26c100498b695b4f": 214,
61
+ }
62
+
63
+ return txhash in other and tx.log_index == other[txhash]
64
+
65
+
66
+ @bugs("Reimburse GUSD Vault Bug", Network.Mainnet)
67
+ def is_gusd_vault_bug_reimbursement(tx: TreasuryTx) -> bool:
68
+ return (
69
+ tx.symbol == "GUSD"
70
+ and tx.hash == "0x22f62d0922c430232aa402296055d79a6cf5c36a8b6253a7f1f46f1e1f66e277"
71
+ and tx.log_index != 65
72
+ )
73
+
74
+
75
+ @bugs("Reimburse DAI Vault Bug", Network.Mainnet)
76
+ def is_dai_vault_reimbursement(tx: TreasuryTx) -> bool:
77
+ # this is from very early days, I'm not sure if it's documented anywhere
78
+ return (
79
+ tx.hash == "0x61ad3697ab56316ffdc7b8eaaeee57d0b3f8d4fed3e283eee35c6c38eed594e0"
80
+ and tx.log_index == 202
81
+ )
@@ -0,0 +1,43 @@
1
+ """
2
+ Other expense rules for donations in Yearn Treasury.
3
+
4
+ This module defines matching logic for donation transactions,
5
+ including Gitcoin matching rounds, 4626 Alliance, Vyper Compiler
6
+ Audit Contest, Warroom Games, and more.
7
+ """
8
+
9
+ from typing import Final
10
+
11
+ from dao_treasury import TreasuryTx, other_expense
12
+ from y import Network
13
+
14
+
15
+ donations: Final = other_expense("Donations")
16
+
17
+ gitcoin: Final = "0xde21F729137C5Af1b01d73aF1dC21eFfa2B8a0d6"
18
+
19
+
20
+ @donations("Gitcoin Matching Round", Network.Mainnet)
21
+ def is_gitcoin_matching_donation(tx: TreasuryTx) -> bool:
22
+ return tx.symbol in ["DAI", "USDC"] and tx.to_address == gitcoin
23
+
24
+
25
+ donations("4626 Alliance", Network.Mainnet).match(
26
+ hash="0xca61496c32806ba34f0deb331c32969eda11c947fdd6235173e6fa13d9a1c288",
27
+ log_index=150,
28
+ )
29
+
30
+
31
+ donations("Vyper Compiler Audit Contest", Network.Mainnet).match(
32
+ # Grant for a vyper compiler audit context, vyper-context.eth
33
+ hash="0xb8bb3728fdfb49d7c86c08dba8e3586e3761f13d2c88fa6fab80227b6a3f4519",
34
+ log_index=202,
35
+ )
36
+
37
+
38
+ @donations("Warroom Games 2023 Prizes", Network.Mainnet)
39
+ def is_warroom_games(tx: TreasuryTx) -> bool:
40
+ return (
41
+ tx.hash == "0x8f17ead9cea87166cf99ed2cdbc46dfdf98c04c261de5b5167caddce5f704cb2"
42
+ and tx.log_index in [429, 430, 431]
43
+ )
@@ -0,0 +1,29 @@
1
+ from typing import Final
2
+
3
+ from dao_treasury import TreasuryTx, other_expense
4
+ from pony.orm import commit
5
+ from y import Network
6
+
7
+
8
+ dyfi: Final = other_expense("dYFI")
9
+
10
+
11
+ @dyfi("Launch", Network.Mainnet)
12
+ def is_dyfi_launch(tx: TreasuryTx) -> bool:
13
+ txhash = tx.hash
14
+ if txhash == "0x2ec726e5ee52cdc063e61795d1b96a75d16fd91824136c990b7c3ddd52b28e31":
15
+ # unused returned
16
+ if tx.amount > 0:
17
+ tx.amount *= -1
18
+ commit()
19
+ if tx.value_usd > 0: # type: ignore [operator]
20
+ tx.value_usd *= -1 # type: ignore [operator]
21
+ commit()
22
+ return True
23
+ return txhash == "0x066c32f02fc0908d55b6651afcfb20473ec3d99363de222f2e8f4a7e0c66462e"
24
+
25
+
26
+ @dyfi("Redemptions", Network.Mainnet)
27
+ def is_dyfi_redemptions(tx: TreasuryTx) -> bool:
28
+ """YFI going to the dyfi redemptions contract"""
29
+ return tx.symbol == "YFI" and tx.to_nickname == "dYFI Redemption Contract"
@@ -0,0 +1,21 @@
1
+ from typing import Final
2
+
3
+ from dao_treasury import TreasuryTx, other_expense
4
+ from y import Network
5
+
6
+
7
+ events: Final = other_expense("Events")
8
+
9
+
10
+ events("Devcon").match(
11
+ hash="0x57bc99f6007989606bdd9d1adf91c99d198de51f61d29689ee13ccf440b244df",
12
+ log_index=83,
13
+ )
14
+
15
+
16
+ @events("EthDenver", Network.Mainnet)
17
+ def is_eth_denver(tx: TreasuryTx) -> bool:
18
+ return (
19
+ tx.hash == "0x26956f86b3f4e3ff9de2779fb73533f3e1f8ce058493eec312501d0e8053fe7a"
20
+ and tx.log_index == 179
21
+ )
@@ -0,0 +1,43 @@
1
+ 1:
2
+ Buying CRV For Boosties:
3
+ # bought via some multi-token buyer contract that probably doesnt need hueristics
4
+ - "0x2391a566b567528ad838169804c77b67ee9724acd174ae6d8a5ebbb715870c35"
5
+ - "0xd04e5b2b19b2e88d72426d08cb04a54b64d788309787caacfcdb0a4bd440503f"
6
+ - "0x000f6a0140da4a5c70e671523c8b8406ee8353c973b700dcc575ca1f347628af"
7
+ - "0x8d7e61b2c6b4e3554258c0f383baee9afc26f60a01d5cdc4a178840f9b506cce"
8
+ - "0x2ebb191b54e7b2d9916d36462a211e416781a873bac630c32c5e771192410e14"
9
+ - "0x4a8a8ddbca5b4debdc298c3ed39149f8933b79b937aa71b9e8d969c5fd691865"
10
+ # and these from some different one
11
+ - "0xb87eb568fb662b28b61bfb4fa477d6db59e8c5c0eb8107cb5f7aa6ad0be4292c"
12
+ - "0xe2d6420b3eae91634e6b06f4c1d2d7e25e5277f7f945c98731daccb005513f11"
13
+ - "0xd5b506d20d35daf583350d5f7cfbf8f827cbe78326d36dbf02bbbbede7bbb0b2"
14
+ - "0x54e88407a9a7161bc259b1d9193a0cec8152c976cf985ccdd9ab1c23e80ce112"
15
+ - "0x6fd9d2da32a1b5b4b9e61a1659900ebb54c45b2a6254d79d84cb8cd9fe06c474"
16
+ # and another
17
+ - "0x3fa631fe04338ffd71d07c05d5a6d93c4f8c6bbe435a0af17bf819e43d31f8b3"
18
+ - "0xf5aa2466338bb9d134c7a7dfe9a42aefa4348684ce2fab3ce655acf5925da8fe"
19
+ - "0xc945264eef9e494251bdc3c23147fa7fde7c4115f94c8feae9826bc06dd0338c"
20
+ - "0x7c365f0afa683727163ee627e5cdab607be70e1c6beee3e3d0c2e35b0e366bde"
21
+ - "0xf0a946524c4b244b626bdddb9ef07051a3252dfa18caac7a8e66ec365655a15f"
22
+ - "0xc8ac7d1ec0631723846e170fb22aab5881c15ccf4fdae15dbe283cd38d782ea7"
23
+ # bought via 0x protocol
24
+ - "0x2367da0c38d9c5b7fb0e422ce364ae9c8fbb74567a96f94078c58d9f9e0809ac"
25
+ - "0x2f5c5e6ba0633d097c99d0bf64e4a96f5f440c6eab2197565e83435f96473ed1"
26
+ - "0xcf2f0cfe8c5a1b848b57d5cebd5375335ae889f2075373e23f50a3c65a03b2b2"
27
+ EthGlobal:
28
+ - "0x5b2e904506a54417c054129a01b84c43dd40050d6f8064463e2500195049a070"
29
+ - "0xd667fda716cf9b5e3a8ca6c9729914505ed611eff37b0f5f57d365b302ce6ebc"
30
+ Send 1 YFI Get 2 Back:
31
+ # yearn asked for donations once and instead of using them, repaid them x2
32
+ - "0x8ed7ee716e04096a7274188b5b371bc7c92aff305fa7b47f32ad622374fb23fc"
33
+ EthOnline Prizes:
34
+ - "0x200cbcd15fb934e75e0909e4752cad4e2067b9556a85660bd6980c3473721122"
35
+ YFI.ETH:
36
+ - "0x7c9e50cab268ae67d563ec3e563ebbf6a38a66dfdb02c65d22320d7239480a99"
37
+ Bugs:
38
+ Reimburse Opti Zap Bug:
39
+ - "0xf1bc9683863fd7133377e618e80a7035bc9389e7abf3f650aed4df8b068a2b79"
40
+ Reimburse Discord Link Bug:
41
+ # https://github.com/yearn/chief-multisig-officer/pull/1201
42
+ - "0x2201d33e1050a0c2639a6dc88c2faebc99fe60c2210713cd95ab1424d7e7df1c"
43
+
@@ -0,0 +1,8 @@
1
+ 1:
2
+ YFI Story:
3
+ - "0x93C6c14C134C4fF52cbB6BC2f50F19d84874cDD1"
4
+ Aztek Gas Subsidy:
5
+ - "0xABc30E831B5Cc173A9Ed5941714A7845c909e7fA"
6
+ Donations:
7
+ Vyper:
8
+ - "0x70CCBE10F980d80b7eBaab7D2E3A73e87D67B775"
@@ -0,0 +1,49 @@
1
+ """
2
+ Other expense rules for miscellaneous cases in Yearn Treasury.
3
+
4
+ This module defines matching logic for miscellaneous other expenses.
5
+ If it doesn't really fit anywhere else in :mod:`~other_expenses`,
6
+ it will end up in here.
7
+ """
8
+
9
+ from dao_treasury import TreasuryTx, other_expense
10
+ from y import Network
11
+
12
+
13
+ other_expense("veYFI Launch", Network.Mainnet).match(
14
+ hash="0x51202f9e8a9afa84a9a0c37831ca9a18508810175cb95ab7c52691bbe69a56d5",
15
+ symbol="YFI",
16
+ )
17
+
18
+
19
+ @other_expense("yBudget Reward", Network.Mainnet)
20
+ def is_ybudget_reward(tx: TreasuryTx) -> bool:
21
+ txhash = tx.hash
22
+ return (
23
+ # Epoch 2
24
+ (
25
+ tx.symbol == "YFI"
26
+ and txhash == "0xae7d281b8a093da60d39179452d230de2f1da4355df3aea629d969782708da5d"
27
+ )
28
+ or txhash
29
+ in (
30
+ # Epoch 1
31
+ "0xa1b242b2626def6cdbe49d92a06aad96fa018c27b48719a98530c5e5e0ac61c5",
32
+ # Epoch 3
33
+ "0x6ba3f2bed8b766ed2185df1a492b3ecab0251747c619a5d60e7401908120c9c8",
34
+ )
35
+ )
36
+
37
+
38
+ @other_expense("1 YFI for Signers", Network.Mainnet)
39
+ def is_one_yfi_for_signers(tx: TreasuryTx) -> bool:
40
+ txhash = tx.hash
41
+ return txhash in (
42
+ "0x86700207761cdca82a0ad4e04b49b749913de63c8bd933b4f3f9a145d9b2c1fa",
43
+ # https://snapshot.box/#/s:veyfi.eth/proposal/0xc7ded2863a10154b6b520921af4ada48d64d74e5b7989f98cdf073542b2e4411
44
+ "0x5ed4ce821cb09b4c6929cc9a6b5e0a23515f9bb97d9b5916819a6986f6c89f09",
45
+ "0xe80628d90254f8da0a6016629c8811b5dd54f231e94f71697ab37d8c00482586",
46
+ ) or (
47
+ txhash == "0x831ad751e1be1dbb82cb9e1f5bf0e38e31327b8c58f6ad6b90bcfb396129bb11"
48
+ and tx.log_index == 403
49
+ )
@@ -0,0 +1,20 @@
1
+ """These predate the yteam revshare splitting implementation so were done manually"""
2
+
3
+ from typing import Final
4
+
5
+ from dao_treasury import other_expense
6
+ from y import Network
7
+
8
+
9
+ revshare: Final = other_expense("Revshare")
10
+
11
+
12
+ revshare("yAudit", Network.Mainnet).match(
13
+ hash="0xdf3e6cf2e50052e4eeb57fb2562b5e1b02701014ce65b60e6c8a850c409b341a",
14
+ log_index=127,
15
+ )
16
+
17
+ revshare("yLockers", Network.Mainnet).match(
18
+ hash="0x038aeb3351b762bc92c5e4274c01520ae08dc314e2282ececc2a19a033d994a8",
19
+ log_index=163,
20
+ )
@@ -0,0 +1,2 @@
1
+ from yearn_treasury.rules.other_income.airdrops import *
2
+ from yearn_treasury.rules.other_income.misc import *