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,66 @@
1
+ """
2
+ Gas cost rules for Yearn Treasury.
3
+
4
+ This module defines rules and matching logic for classifying gas-related
5
+ transactions as cost of revenue. It includes logic for multisig
6
+ reimbursements, strategist gas, returned gas, and more.
7
+ """
8
+
9
+ # mypy: disable-error-code="call-overload"
10
+ from typing import Final, Set
11
+
12
+ import pony.orm
13
+ from dao_treasury import TreasuryTx, cost_of_revenue
14
+ from eth_typing import HexStr
15
+ from y import Network
16
+ from y.constants import CHAINID
17
+
18
+
19
+ gas: Final = cost_of_revenue("Gas")
20
+
21
+ commit: Final = pony.orm.commit
22
+
23
+
24
+ gas("Multisig Reimbursement").match(
25
+ hash=HexStr("0x19bcb28cd113896fb06f17b2e5efa86bb8bf78c26e75c633d8f1a0e48b238a86"),
26
+ from_nickname="Yearn yChad Multisig",
27
+ )
28
+
29
+
30
+ gas("Other Gas").match(
31
+ hash=HexStr("0x57bc99f6007989606bdd9d1adf91c99d198de51f61d29689ee13ccf440b244df"),
32
+ to_address="0xB1d693B77232D88a3C9467eD5619FfE79E80BCCc", # type: ignore [arg-type]
33
+ )
34
+
35
+
36
+ _STRATEGIST_GAS_HASHES: Final[Set[HexStr]] = {}.get(CHAINID, set())
37
+
38
+ _RETURNED_GAS_HASHES: Final[Set[HexStr]] = { # type: ignore [assignment]
39
+ Network.Mainnet: {
40
+ "0x86fee63ec8efb0e7320a6d48ac3890b1089b77a3d9ed74cade389f512471c299",
41
+ "0xa77c4f7596968fef96565a0025cc6f9881622f62cc4c823232f9c9000ba5f981",
42
+ "0xac2253f1d8f78680411b353d65135d58bc880cdf9507ea7848daf05925e1443f",
43
+ "0xd27d4a732dd1a9ac93c7db1695a6d2aff40e007627d710da91f328b246be44bc",
44
+ "0x5a828e5bde96cd8745223fe32daefaa9140a09acc69202c33f6f789228c8134b",
45
+ "0x110ef82ec16eb53bf71b073aca4a37d4fbfaa74166c687a726211392a02f0059",
46
+ "0xaad012505975dd13a57599a28d33c979f72084ae56ccba76997f05822a5497f5",
47
+ "0xd10e8eb19b9493b32daf880da40e8e80ae96e9947ebd372562504e376c253731",
48
+ "0xa937f94cd93e07e5a1abf3010267b213caf8fbefb5d56e417ab057de39c697a5",
49
+ },
50
+ }.get(CHAINID, set())
51
+
52
+
53
+ @gas("Strategist Gas")
54
+ def is_strategist_gas(tx: TreasuryTx) -> bool:
55
+ if tx.symbol == "ETH":
56
+ if tx.from_nickname == "Disperse.app":
57
+ return tx.hash in _STRATEGIST_GAS_HASHES
58
+
59
+ # Returned gas
60
+ if tx.hash in _RETURNED_GAS_HASHES:
61
+ tx.amount *= -1
62
+ tx.value_usd *= -1 # type: ignore [operator]
63
+ commit()
64
+ return True
65
+
66
+ return False
@@ -0,0 +1,12 @@
1
+ 1:
2
+ Gas:
3
+ Strategists:
4
+ - "0x420cfbc7856f64e8949d4dd6d4ce9570f8270def1380ebf381376fbcd0b0d5bf"
5
+ - "0xc7bca93dc6bfa37e45bebb030a2ce1198fc402176ba0b3a5553a0580299df5e7"
6
+ YearnHarvest:
7
+ # dont really remember what this is, might just shove everything into generalized "gas" category
8
+ - "0xb05494705ce91cc5e5db259ded8acaf80b645c655556ee40a85097fd9054d9b6"
9
+ TheGraph:
10
+ - "0x33a50699c95fa37e2cc4032719ed6064bbd892b0992dde01d4ef9b3470b9da0b"
11
+ yKeeper:
12
+ - "0x140246e693445b448f8e9baaad1872fe44f3982cba44e7d652bf1c2235c7ac4a"
@@ -0,0 +1,4 @@
1
+ from yearn_treasury.rules.expense.general import *
2
+ from yearn_treasury.rules.expense.infrastructure import *
3
+ from yearn_treasury.rules.expense.people import *
4
+ from yearn_treasury.rules.expense.security import *
@@ -0,0 +1,13 @@
1
+ from decimal import Decimal
2
+
3
+ from dao_treasury import TreasuryTx, expense
4
+ from y import Network
5
+
6
+
7
+ @expense("SMS Discretionary Budget", networks=Network.Mainnet)
8
+ def is_sms_discretionary_budget(tx: TreasuryTx) -> bool:
9
+ return (
10
+ tx.to_nickname == "Yearn Strategist Multisig"
11
+ and tx.symbol == "DAI"
12
+ and tx.amount == Decimal(200_000)
13
+ )
@@ -0,0 +1,47 @@
1
+ """
2
+ Expense rules for infrastructure payments.
3
+
4
+ This module defines matching logic for infrastructure-related expenses,
5
+ including Tenderly, Wonderland Jobs, and generic infra payments.
6
+ """
7
+
8
+ from typing import Final
9
+
10
+ from dao_treasury import TreasuryTx, expense
11
+
12
+
13
+ infrastructure: Final = expense("Infrastructure")
14
+
15
+
16
+ infrastructure("Tenderly Subscription").match(
17
+ symbol="USDT",
18
+ to_address="0xF6060cE3fC3df2640F72E42441355f50F195D96a",
19
+ )
20
+
21
+
22
+ infrastructure("Wonderland Jobs").match(
23
+ symbol="DAI", to_address="0x8bA72884984f669aBBc9a5a7b441AD8E3D9a4fD3"
24
+ )
25
+
26
+
27
+ @infrastructure("Unspecified Infra")
28
+ def is_generic_infra(tx: TreasuryTx) -> bool:
29
+ txhash = tx.hash
30
+ if tx.symbol == "DAI" and txhash in {
31
+ "0x0c59e87027bcdcaa718e322a28bc436106d73ae8623071930437bdb0706c4d65",
32
+ "0x47035f156d4e6144c144b2ac5e91497e353c9a4e23133587bbf3da2f9d7da596",
33
+ "0x40352e7166bf5196aa1160302cfcc157facf99731af0e11741b8729dd84e131c",
34
+ "0xc269f6fb016a48fe150f689231a73532b631877d1376608df639dad79514904b",
35
+ }:
36
+ return True
37
+
38
+ other = {
39
+ "0x08ef1aacdf7d0f16be5e6fd0a64ebd0ba3b0c3dd0a7884a9a470aa89a7fe1a06": 222,
40
+ "0xeb51cb5a3b4ae618be75bf3e23c2d8e333d93d5e81e869eca7f9612a30079822": 195,
41
+ "0x3e75d22250d87c183824c3b77ddb9cb11935db2061ce7f34df4f024d0646fcfb": 117,
42
+ "0x1621ba5c9b57930c97cc43d5d6d401ee9c69fed435b0b458ee031544a10bfa75": 460,
43
+ "0x5deca5d6c934372c174bbef8be9a1e103e06d8b93fd3bf8d77865dfeb34fe3be": 98,
44
+ "0xfc07ee04d44f8e481f58339b7b8c998d454e4ec427b8021c4e453c8eeee6a9b9": 207,
45
+ }
46
+
47
+ return txhash in other and tx.log_index == other[txhash]
@@ -0,0 +1,48 @@
1
+ 1:
2
+ Team Payments:
3
+ - "0x0704961379ad0ee362c9a2dfd22fdfa7d9a2ed5a94a99dbae1f83853a2d597bc"
4
+ - "0x78f39093239242c68f77dee8912546189adf2447264e8340d3a4982b9474a159"
5
+ - "0x53fbd564acf39e0694773b5228d31d32623aa249b73a9989a2a43d8b7b8484af"
6
+ Coordinape:
7
+ - "0xfd83d667c278a74f0ad9507b8d159e43f893c5067dbd47c05c80e229ec6c3cd4"
8
+ Grants:
9
+ Brand Identity:
10
+ - "0xd7188e4e6e0191e599bcb479991c8a8df228b725795e437e4c23728819bde82e"
11
+ Design:
12
+ - "0x31ea090cc6b7acc25be6881a9daa82bd7b120a219c9f53f340a1ab166c1f4f9f"
13
+ Vault Management Dashboard:
14
+ # These is also a stream for these guys TODO figure out how to account for streams as they stream
15
+ - "0xc59b692bff01c3a364d9a1fc629dfd743c1e421f7eaee7efdca86f23d0a8a7ad"
16
+ Docs Grant:
17
+ # https://github.com/yearn/budget/issues/105
18
+ - "0x99f8e351a15e7ce7f0acbae2dea52c56cd93ef97b0a5981f79a68180ff777f00"
19
+ yCRV Dev Grant:
20
+ - "0x116a44242ffafd12a8e40a7a2dbc9f6a98580ca4d72e626ddb60d09417cab15d"
21
+ Travel Reimbursements:
22
+ - "0xb11d1f505bcdba152c25c80d2c8268a437b50c86fe0cde2f26d3e952aca4e2b3"
23
+ - "0x628b9973ed22a5ea300dc79abcaf0d390e2941f28bc804886801ae9f82544f49"
24
+ - "0x20520b219ba999df961139d88e992459d345010ca6cbae57726911921824e653"
25
+ - "0xf3ccaabce022b773d93a5d497d228c8cb75d7cd5bf181802276ab26afb8459c7"
26
+ - "0x9aa72f4a6179d69b05dd53bd92b0667bd9a89930455040d837e82d652963c454"
27
+ # This tx is for a budget request TODO curate the budget requests somewhere in this repo.
28
+ - "0xe5ff2368fae88c103f80cbbc10a2f32b91f562d83bcd34e94aba6e249a0f317a"
29
+ # This was for travel planning but this is the most fitting category at this time.
30
+ - "0x7222e1ae42ed80dc0b0cbc90db23b1b5ccae356d045ddb039ce635fd5871643b"
31
+ Infrastructure:
32
+ Unspecified Infra:
33
+ - "0xeac1e31beb90945f41c39a08763a0e3fbd4b18345ea71be8c8ff9a4b4fa358e6"
34
+ - "0x8fe97937c6a127086abc376a7d38aa97dad6b0fc16c324ebdd1cd2192f2191e6"
35
+ - "0x5cd6b1e13b021bd8fba4a1823c6ef8647d190f85083c15a1e6e3e5fd8a9df6ee"
36
+ - "0x020ee660197f91647d47fab8e279d0396c8d4781f5562c6d243e976d8102d2e4"
37
+ - "0xeb8d642da7b4f0981aca22b747489c67b09d86e75381da5d68d6c00448e440c8"
38
+ - "0x3160b025085b17ee4bc3810c753c2d1fe9c556d2fb4cdf2ec7669cc878a94c68"
39
+ - "0x17a72a66512aa302a4f89b7d894519abf335156deac2a4801c884283181daa83"
40
+ - "0xb9b5eef15987d97448d6cae146231c47910ba937db7dc30cfb253d64cbc5515d"
41
+ - "0xf9ddee2db73fdf322caa10da88a178aca8308d79c2ad83324716c22878600e1c"
42
+ - "0xaf303a94ca3949c44855dfe90848bef142f8afdaa7a524f51593c827c2d2d733"
43
+ Audit:
44
+ Debaub:
45
+ - "0xb2595246e8387b80e35784aaade3a92bd3111bf9059c3b563516886d1aefcf3f"
46
+ Decurity:
47
+ - "0x3d1a0b2bb71f3b7118b1a4d5f9e78962809044616ae04659ef383141df678b4f"
48
+
@@ -0,0 +1,7 @@
1
+ 1:
2
+ Rantom [BR#xxx]:
3
+ - "0x254b42CaCf7290e72e2C84c0337E36E645784Ce1"
4
+ ySecurity 2 [BR#xxx]:
5
+ - "0x4851C7C7163bdF04A22C9e12Ab77e184a5dB8F0E"
6
+ Worms:
7
+ - "0xB1d693B77232D88a3C9467eD5619FfE79E80BCCc"
@@ -0,0 +1,84 @@
1
+ from typing import Final
2
+
3
+ from dao_treasury import TreasuryTx, expense
4
+
5
+
6
+ grants: Final = expense("Grants")
7
+ website: Final = grants("Website")
8
+ ux: Final = website("UX")
9
+
10
+
11
+ @expense("Coordinape")
12
+ def is_coordinape(tx: TreasuryTx) -> bool:
13
+ return (
14
+ tx.from_nickname == "Disperse.app"
15
+ and tx.symbol in ("YFI", "yvYFI")
16
+ and tx
17
+ in {
18
+ "0x0b7159645e66c3b460efeb3e1e3c32d5e4eb845a2f2230b28b388ad34a36fcc3",
19
+ "0xb23d189ac94acb68d457e5a21b765fd0affd73ac1cd5afbe9fb57db8c3f95c30",
20
+ "0x5cf6a4c70ec2de7cd25a627213344deae28f11ba9814d5cc1b00946f356ed5bf",
21
+ "0x2a7c60bb7dd6c15a6d0351e6a2b9f01e51fa6e7df9d1e5f02a3759640211ee56",
22
+ "0x371b6a601da36382067a20236d41f540fc77dc793d64d24fc1bdbcd2c666db2b",
23
+ "0x514591e6f8dcac50b6deeabce8a819540cc7caecc182c39dfb93280abb34d3d6",
24
+ "0x8226b3705657f34216483f5091f8bd3eeea385a64b6da458eeaff78521596c28",
25
+ "0x38201edb06e8fd3b9aa9d4142594d28cb73768770fdcb68a4da24d8cb0742cfc",
26
+ "0x4d404a04bf46b80721f03ad6b821c6d82312c53331d8e7425fb68100116d8b98",
27
+ "0xa3627513c8c3e838feaf9ab1076be01df11c5be5a83597626950c3ac38124bba",
28
+ "0x0a9e0f2cadb5dc3209bad74ada2fe71f2cbc0e9e2f16a4de1a29ea663e325798",
29
+ "0xb3aab771a5581df5b1c8e6faefedcc88d91b8820c5ae5eaf9c9283014288dda2",
30
+ "0x1391d6de1f0b5469627da1e23ddd0f892bf7d182780bc2fb807b6bf1e2d0acf1",
31
+ "0x8ed57eff8f4a61cd40d109223c5054f87e35a6f0a5c85b65b1a7afe5b6e308da",
32
+ "0xa121fd9717d0fb4ac72a223db638f4e59094547ddee253e5ba011a5bb0c67126",
33
+ "0xf401d432dcaaea39e1b593379d3d63dcdc82f5f694d83b098bb6110eaa19bbde",
34
+ }
35
+ )
36
+
37
+
38
+ @grants("yGift Team Grant")
39
+ def is_ygift_grant(tx: TreasuryTx) -> bool:
40
+ """Yearn used to use yGift to send team grants but that ended up being too expensive."""
41
+ return tx.to_nickname == "Contract: yGift" and tx.symbol == "yyDAI+yUSDC+yUSDT+yTUSD"
42
+
43
+
44
+ # TODO: refactor all of this, there's gotta be a better way to handle yteams who have received both one-off and streamed pmnts
45
+ @grants("yHAAS Trinity [BR#263]")
46
+ def is_yhaas_trinity_ii(tx: TreasuryTx) -> bool:
47
+ """https://github.com/yearn/budget/issues/263"""
48
+ return (
49
+ tx.hash == "0xd35c30664f3241ea2ec3df1c70261086247025eb72c2bc919108dfef9b08a450"
50
+ and tx.to_address.address
51
+ in (
52
+ # team
53
+ "0x35a83D4C1305451E0448fbCa96cAb29A7cCD0811",
54
+ # stream
55
+ "0xEC83C8c3156e4f6b95B048066F3b308C93cb5848",
56
+ )
57
+ )
58
+
59
+
60
+ @grants("G-Team [BR#267]")
61
+ def is_gteam(tx: TreasuryTx) -> bool:
62
+ """https://github.com/yearn/budget/issues/267"""
63
+ return (
64
+ tx.hash == "0xd35c30664f3241ea2ec3df1c70261086247025eb72c2bc919108dfef9b08a450"
65
+ and tx.to_address == "0x63E02F93622541CfE41aFedCF96a114DB71Ba4EE"
66
+ )
67
+
68
+
69
+ @grants("Rantom [BR#129]")
70
+ def is_rantom(tx: TreasuryTx) -> bool:
71
+ """https://github.com/yearn/budget/issues/129"""
72
+ return tx.to_address == "0x254b42CaCf7290e72e2C84c0337E36E645784Ce1"
73
+
74
+
75
+ @grants("Worms")
76
+ def is_worms(tx: TreasuryTx) -> bool:
77
+ return tx.to_address == "0xB1d693B77232D88a3C9467eD5619FfE79E80BCCc"
78
+
79
+
80
+ # NOTE: this needs to go at the bottom because there are some streams that will already be caught by above matchers
81
+ @grants("Simple Vesting Escrow")
82
+ def is_simple_vesting_escrow(tx: TreasuryTx) -> bool:
83
+ # TODO: amortize the streamed funds as a daily amount and sort more granularly based on BR
84
+ return tx.to_nickname == "Contract: Simple Vesting Escrow"
@@ -0,0 +1,147 @@
1
+ """
2
+ Expense rules for security, audits, and bug bounties.
3
+
4
+ This module defines matching logic for security-related expenses,
5
+ including audits (yAcademy, ChainSec, StateMind, MixBytes, unspecified),
6
+ bug bounties, and other security-related deliverables.
7
+ """
8
+
9
+ from typing import Final
10
+
11
+ from dao_treasury import TreasuryTx, expense
12
+ from y import Network
13
+
14
+
15
+ security: Final = expense("Security")
16
+ audits: Final = security("Audits")
17
+ grants: Final = security("Grants")
18
+
19
+
20
+ @audits("yAcademy", Network.Mainnet)
21
+ def is_yacademy_audit(tx: TreasuryTx) -> bool:
22
+ """Expense for an audit performed by yAcademy"""
23
+ # NOTE: the hash we're excluding was a one-time revshare tx before the splitter was set up.
24
+ return (
25
+ tx.to_address == "0x0E0aF03c405E17D0e486354fe709d3294d07EC44"
26
+ and tx.hash != "0xdf3e6cf2e50052e4eeb57fb2562b5e1b02701014ce65b60e6c8a850c409b341a"
27
+ )
28
+
29
+
30
+ @audits("ChainSec", Network.Mainnet)
31
+ def is_chainsec_audit(tx: TreasuryTx) -> bool:
32
+ """Expense for an audit performed by chainsec"""
33
+ if (
34
+ tx.symbol in ["USDC", "USDT"]
35
+ and tx.to_address == "0x8bAf5eaF92E37CD9B1FcCD676918A9B3D4F87Dc7"
36
+ ):
37
+ return True
38
+
39
+ txhash = tx.hash
40
+ return txhash == "0x83ec212072f82f4aba4b512051d52c5f016de79a620a580622a0f051e3473a78" or (
41
+ # https://github.com/yearn/budget/issues/246
42
+ txhash == "0xd0fa31ccf6bf7577a533366955bb528d6d17c928bba1ff13ab273487a27d9602"
43
+ and tx.log_index == 254
44
+ )
45
+
46
+
47
+ @audits("StateMind", Network.Mainnet)
48
+ def is_statemind_audit(tx: TreasuryTx) -> bool:
49
+ """Expense for an audit performed by statemind"""
50
+ txhash = tx.hash
51
+ log_index = tx.log_index
52
+ if log_index is None:
53
+ return False
54
+ if (
55
+ txhash == "0xeb51cb5a3b4ae618be75bf3e23c2d8e333d93d5e81e869eca7f9612a30079822"
56
+ and log_index == 193
57
+ ):
58
+ return True
59
+ elif (
60
+ txhash == "0xcb79cbe5b68d04a1a3feab3360734277020ee0536380843a8c9db3e8356b81d6"
61
+ and log_index == 398
62
+ ):
63
+ return True
64
+ elif (
65
+ txhash == "0x3e75d22250d87c183824c3b77ddb9cb11935db2061ce7f34df4f024d0646fcfb"
66
+ and log_index == 115
67
+ ):
68
+ return True
69
+ return False
70
+
71
+
72
+ @audits("MixBytes", Network.Mainnet)
73
+ def is_mixbytes_audit(tx: TreasuryTx) -> bool:
74
+ """Expense for an audit performed by mixbytes"""
75
+ txhash = tx.hash
76
+ if (
77
+ txhash == "0xcb79cbe5b68d04a1a3feab3360734277020ee0536380843a8c9db3e8356b81d6"
78
+ and tx.log_index == 399
79
+ ):
80
+ return True
81
+ elif (
82
+ txhash == "0xca61496c32806ba34f0deb331c32969eda11c947fdd6235173e6fa13d9a1c288"
83
+ and tx.symbol == "USDC"
84
+ ):
85
+ return True
86
+ return False
87
+
88
+
89
+ @audits("Unspecified Audit", Network.Mainnet)
90
+ def is_other_audit(tx: TreasuryTx) -> bool:
91
+ txhash = tx.hash
92
+ if txhash in {
93
+ "0x7df5566cc9ff8ed0aafe126b74ad0e3957e62d530d007565ee32bd1303bcec32",
94
+ "0x5e95d5b0773eefaef9c7187d5e9187a89717d269f48e5dcf707acfe1a7e55cb9",
95
+ "0x9cfd1098c5459002a90ffa23931f7bbec430b3f2ec0ef2d3a641cef574eb0817",
96
+ "0x70cdcffa444f70754a1df2d80a1adf9c432dfe678381e05ac78ab50b9de9d393",
97
+ }:
98
+ return True
99
+ elif (
100
+ txhash == "0x70ecc34da6c461a0bb9dadfbc4d082a8486e742cbb454f0f67b2df384fb9bffc"
101
+ and tx.log_index == 89
102
+ ):
103
+ return True
104
+ return False
105
+
106
+
107
+ @security("Bug Bounty", Network.Mainnet)
108
+ def is_bug_bounty(tx: TreasuryTx) -> bool:
109
+ txhash = tx.hash
110
+ if txhash == "0x4df2eee567ebf2a41b555fca3fed41300b12ff2dc3c79ffaee8b7bdf262f9303":
111
+ return True
112
+ elif (
113
+ txhash == "0x5deca5d6c934372c174bbef8be9a1e103e06d8b93fd3bf8d77865dfeb34fe3be"
114
+ and tx.log_index in (100, 101)
115
+ ):
116
+ # Immunefi
117
+ return True
118
+ elif (
119
+ txhash == "0x3e045ced19590db8905d8a69c2f0fd0acd4f90301cf6356742e735cd7caa0964"
120
+ and tx.log_index == 327
121
+ ):
122
+ # Sherlock
123
+ return True
124
+ return False
125
+
126
+
127
+ security("Anti-Spam Discord Bot", Network.Mainnet).match(
128
+ hash="0xe397d5682ef780b5371f8c80670e0cd94b4f945c7b432319b24f65c288995a17",
129
+ log_index=357,
130
+ )
131
+
132
+
133
+ @security("War Room Assistance", Network.Mainnet)
134
+ def is_warroom_help(tx: TreasuryTx) -> bool:
135
+ """A past yearner was paid a one-time payment to assist in a war room."""
136
+ return (
137
+ tx.hash == "0xca61496c32806ba34f0deb331c32969eda11c947fdd6235173e6fa13d9a1c288"
138
+ and tx.log_index == 152
139
+ )
140
+
141
+
142
+ @grants("ySecurity", Network.Mainnet)
143
+ def is_ysecurity(tx: TreasuryTx) -> bool:
144
+ """
145
+ https://github.com/yearn/budget/issues/145
146
+ """
147
+ return tx.to_address == "0x4851C7C7163bdF04A22C9e12Ab77e184a5dB8F0E"
@@ -0,0 +1,8 @@
1
+ from yearn_treasury.rules.ignore.general import *
2
+ from yearn_treasury.rules.ignore.maker import *
3
+ from yearn_treasury.rules.ignore.passthru import *
4
+ from yearn_treasury.rules.ignore.staking import *
5
+ from yearn_treasury.rules.ignore.swaps import *
6
+ from yearn_treasury.rules.ignore.unit import *
7
+ from yearn_treasury.rules.ignore.weth import *
8
+ from yearn_treasury.rules.ignore.ygov import *
@@ -0,0 +1,11 @@
1
+ from dao_treasury import TreasuryTx, ignore
2
+
3
+
4
+ @ignore("Returned Funds")
5
+ def is_returned_fundus(tx: TreasuryTx) -> bool:
6
+ """A user accientally refunded their yield to yChad, yChad sent it back."""
7
+ txhash = tx.hash
8
+ return txhash == "0x2c2fb9d88a7a25b100ae3ba08bdb1cafbbd6a63386a08fdcfe32d077836defa3" or (
9
+ txhash == "0xd7e7abe600aad4a3181a3a410bef2539389579d2ed28f3e75dbbf3a7d8613688"
10
+ and tx.log_index == 556
11
+ )
@@ -0,0 +1,92 @@
1
+ """
2
+ Ignore rules for Maker protocol.
3
+
4
+ This module defines matching logic for Maker protocol transactions,
5
+ including DAI minting/burning, DSR deposit/withdrawal, and CDP
6
+ deposit/withdrawal for YFI and USDC.
7
+ """
8
+
9
+ from decimal import Decimal
10
+ from typing import Final
11
+
12
+ from dao_treasury import TreasuryTx, TreasuryWallet, ignore
13
+
14
+ from yearn_treasury.rules.constants import ZERO_ADDRESS
15
+
16
+
17
+ DSPROXY: Final = "0xd42e1Cb8b98382df7Db43e0F09dFE57365659D16"
18
+ DEPOSIT_EVENT_ARGS: Final = "ilk", "usr", "wad"
19
+ WITHDRAWAL_EVENT_ARGS: Final = "cdp", "dst", "wad"
20
+
21
+ maker: Final = ignore("Maker")
22
+ dai: Final = maker("DAI")
23
+ dsr: Final = maker("DSR")
24
+ cdp: Final = maker("CDP")
25
+
26
+
27
+ dai("Minting").match(symbol="DAI", from_address=ZERO_ADDRESS)
28
+ dai("Burning").match(symbol="DAI", to_address=DSPROXY)
29
+
30
+ # sending DAI to or receiving DAI back from Maker's DSR module
31
+ dsr("Deposit").match(to_nickname="Contract: DsrManager")
32
+ dsr("Withdrawal").match(from_nickname="Contract: DsrManager")
33
+
34
+
35
+ @cdp("YFI Deposit")
36
+ def is_yfi_cdp_deposit(tx: TreasuryTx) -> bool:
37
+ if tx.symbol == "YFI" and TreasuryWallet.check_membership(
38
+ tx.from_address.address, tx.block # type: ignore [union-attr, arg-type]
39
+ ):
40
+ for event in tx.get_events("slip"):
41
+ if all(arg in event for arg in DEPOSIT_EVENT_ARGS):
42
+ # TODO: remove this rounding once we move to postgres
43
+ scaled = round(Decimal(event["wad"]) / 10**18, 12)
44
+ rounded = round(tx.amount, 12)
45
+ if scaled == rounded:
46
+ return True
47
+ print(f"yfi cdp deposit amount no match [{scaled}, {rounded}]")
48
+ return False
49
+
50
+
51
+ @cdp("YFI Withdrawal")
52
+ def is_yfi_cdp_withdrawal(tx: TreasuryTx) -> bool:
53
+ if tx.symbol == "YFI" and TreasuryWallet.check_membership(
54
+ tx.to_address.address, tx.block # type: ignore [union-attr, arg-type]
55
+ ):
56
+ for event in tx.get_events("flux"):
57
+ if all(arg in event for arg in WITHDRAWAL_EVENT_ARGS):
58
+ # TODO: remove this rounding once we move to postgres
59
+ scaled = round(Decimal(event["wad"]) / 10**18, 12)
60
+ rounded = round(tx.amount, 12)
61
+ if scaled == rounded:
62
+ return True
63
+ print(f"yfi cdp withdrawal amount no match [{scaled}, {rounded}]")
64
+ return False
65
+
66
+
67
+ @cdp("USDC Deposit")
68
+ def is_usdc_cdp_deposit(tx: TreasuryTx) -> bool:
69
+ if tx.symbol == "USDC" and TreasuryWallet.check_membership(
70
+ tx.from_address.address, tx.block # type: ignore [union-attr, arg-type]
71
+ ):
72
+ for event in tx.get_events("slip"):
73
+ if all(arg in event for arg in DEPOSIT_EVENT_ARGS):
74
+ scaled = Decimal(event["wad"]) / 10**18
75
+ if scaled == tx.amount:
76
+ return True
77
+ print(f"usdc cdp deposit amount no match [{scaled}, {tx.amount}]")
78
+ return False
79
+
80
+
81
+ @cdp("USDC Withdrawal")
82
+ def is_usdc_cdp_withdrawal(tx: TreasuryTx) -> bool:
83
+ if tx.symbol == "USDC" and TreasuryWallet.check_membership(
84
+ tx.to_address.address, tx.block # type: ignore [union-attr, arg-type]
85
+ ):
86
+ for event in tx.get_events("flux"):
87
+ if all(arg in event for arg in WITHDRAWAL_EVENT_ARGS):
88
+ scaled = Decimal(event["wad"]) / 10**18
89
+ if scaled == tx.amount:
90
+ return True
91
+ print(f"usdc cdp withdrawal amount no match [{scaled}, {tx.amount}]")
92
+ return False