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,64 @@
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
+ from typing import Final
10
+
11
+ import pony.orm
12
+ from dao_treasury import TreasuryTx, cost_of_revenue
13
+ from eth_typing import HexStr
14
+ from y import Network
15
+ from y.constants import CHAINID
16
+
17
+ gas: Final = cost_of_revenue("Gas")
18
+
19
+ commit: Final = pony.orm.commit
20
+
21
+
22
+ gas("Multisig Reimbursement").match(
23
+ hash=HexStr("0x19bcb28cd113896fb06f17b2e5efa86bb8bf78c26e75c633d8f1a0e48b238a86"),
24
+ from_nickname="Yearn yChad Multisig",
25
+ )
26
+
27
+
28
+ gas("Other Gas").match(
29
+ hash=HexStr("0x57bc99f6007989606bdd9d1adf91c99d198de51f61d29689ee13ccf440b244df"),
30
+ to_address="0xB1d693B77232D88a3C9467eD5619FfE79E80BCCc", # type: ignore [arg-type]
31
+ )
32
+
33
+
34
+ _STRATEGIST_GAS_HASHES: Final[set[HexStr]] = {}.get(CHAINID, set())
35
+
36
+ _RETURNED_GAS_HASHES: Final[set[HexStr]] = { # type: ignore [assignment]
37
+ Network.Mainnet: {
38
+ "0x86fee63ec8efb0e7320a6d48ac3890b1089b77a3d9ed74cade389f512471c299",
39
+ "0xa77c4f7596968fef96565a0025cc6f9881622f62cc4c823232f9c9000ba5f981",
40
+ "0xac2253f1d8f78680411b353d65135d58bc880cdf9507ea7848daf05925e1443f",
41
+ "0xd27d4a732dd1a9ac93c7db1695a6d2aff40e007627d710da91f328b246be44bc",
42
+ "0x5a828e5bde96cd8745223fe32daefaa9140a09acc69202c33f6f789228c8134b",
43
+ "0x110ef82ec16eb53bf71b073aca4a37d4fbfaa74166c687a726211392a02f0059",
44
+ "0xaad012505975dd13a57599a28d33c979f72084ae56ccba76997f05822a5497f5",
45
+ "0xd10e8eb19b9493b32daf880da40e8e80ae96e9947ebd372562504e376c253731",
46
+ "0xa937f94cd93e07e5a1abf3010267b213caf8fbefb5d56e417ab057de39c697a5",
47
+ },
48
+ }.get(CHAINID, set())
49
+
50
+
51
+ @gas("Strategist Gas")
52
+ def is_strategist_gas(tx: TreasuryTx) -> bool:
53
+ if tx.symbol == "ETH":
54
+ if tx.from_nickname == "Disperse.app":
55
+ return tx.hash in _STRATEGIST_GAS_HASHES
56
+
57
+ # Returned gas
58
+ if tx.hash in _RETURNED_GAS_HASHES:
59
+ tx.amount *= -1
60
+ tx.value_usd *= -1 # type: ignore [operator]
61
+ commit()
62
+ return True
63
+
64
+ 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,46 @@
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
+ infrastructure: Final = expense("Infrastructure")
13
+
14
+
15
+ infrastructure("Tenderly Subscription").match(
16
+ symbol="USDT",
17
+ to_address="0xF6060cE3fC3df2640F72E42441355f50F195D96a",
18
+ )
19
+
20
+
21
+ infrastructure("Wonderland Jobs").match(
22
+ symbol="DAI", to_address="0x8bA72884984f669aBBc9a5a7b441AD8E3D9a4fD3"
23
+ )
24
+
25
+
26
+ @infrastructure("Unspecified Infra")
27
+ def is_generic_infra(tx: TreasuryTx) -> bool:
28
+ txhash = tx.hash
29
+ if tx.symbol == "DAI" and txhash in {
30
+ "0x0c59e87027bcdcaa718e322a28bc436106d73ae8623071930437bdb0706c4d65",
31
+ "0x47035f156d4e6144c144b2ac5e91497e353c9a4e23133587bbf3da2f9d7da596",
32
+ "0x40352e7166bf5196aa1160302cfcc157facf99731af0e11741b8729dd84e131c",
33
+ "0xc269f6fb016a48fe150f689231a73532b631877d1376608df639dad79514904b",
34
+ }:
35
+ return True
36
+
37
+ other = {
38
+ "0x08ef1aacdf7d0f16be5e6fd0a64ebd0ba3b0c3dd0a7884a9a470aa89a7fe1a06": 222,
39
+ "0xeb51cb5a3b4ae618be75bf3e23c2d8e333d93d5e81e869eca7f9612a30079822": 195,
40
+ "0x3e75d22250d87c183824c3b77ddb9cb11935db2061ce7f34df4f024d0646fcfb": 117,
41
+ "0x1621ba5c9b57930c97cc43d5d6d401ee9c69fed435b0b458ee031544a10bfa75": 460,
42
+ "0x5deca5d6c934372c174bbef8be9a1e103e06d8b93fd3bf8d77865dfeb34fe3be": 98,
43
+ "0xfc07ee04d44f8e481f58339b7b8c998d454e4ec427b8021c4e453c8eeee6a9b9": 207,
44
+ }
45
+
46
+ 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,83 @@
1
+ from typing import Final
2
+
3
+ from dao_treasury import TreasuryTx, expense
4
+
5
+ grants: Final = expense("Grants")
6
+ website: Final = grants("Website")
7
+ ux: Final = website("UX")
8
+
9
+
10
+ @expense("Coordinape")
11
+ def is_coordinape(tx: TreasuryTx) -> bool:
12
+ return (
13
+ tx.from_nickname == "Disperse.app"
14
+ and tx.symbol in ("YFI", "yvYFI")
15
+ and tx
16
+ in {
17
+ "0x0b7159645e66c3b460efeb3e1e3c32d5e4eb845a2f2230b28b388ad34a36fcc3",
18
+ "0xb23d189ac94acb68d457e5a21b765fd0affd73ac1cd5afbe9fb57db8c3f95c30",
19
+ "0x5cf6a4c70ec2de7cd25a627213344deae28f11ba9814d5cc1b00946f356ed5bf",
20
+ "0x2a7c60bb7dd6c15a6d0351e6a2b9f01e51fa6e7df9d1e5f02a3759640211ee56",
21
+ "0x371b6a601da36382067a20236d41f540fc77dc793d64d24fc1bdbcd2c666db2b",
22
+ "0x514591e6f8dcac50b6deeabce8a819540cc7caecc182c39dfb93280abb34d3d6",
23
+ "0x8226b3705657f34216483f5091f8bd3eeea385a64b6da458eeaff78521596c28",
24
+ "0x38201edb06e8fd3b9aa9d4142594d28cb73768770fdcb68a4da24d8cb0742cfc",
25
+ "0x4d404a04bf46b80721f03ad6b821c6d82312c53331d8e7425fb68100116d8b98",
26
+ "0xa3627513c8c3e838feaf9ab1076be01df11c5be5a83597626950c3ac38124bba",
27
+ "0x0a9e0f2cadb5dc3209bad74ada2fe71f2cbc0e9e2f16a4de1a29ea663e325798",
28
+ "0xb3aab771a5581df5b1c8e6faefedcc88d91b8820c5ae5eaf9c9283014288dda2",
29
+ "0x1391d6de1f0b5469627da1e23ddd0f892bf7d182780bc2fb807b6bf1e2d0acf1",
30
+ "0x8ed57eff8f4a61cd40d109223c5054f87e35a6f0a5c85b65b1a7afe5b6e308da",
31
+ "0xa121fd9717d0fb4ac72a223db638f4e59094547ddee253e5ba011a5bb0c67126",
32
+ "0xf401d432dcaaea39e1b593379d3d63dcdc82f5f694d83b098bb6110eaa19bbde",
33
+ }
34
+ )
35
+
36
+
37
+ @grants("yGift Team Grant")
38
+ def is_ygift_grant(tx: TreasuryTx) -> bool:
39
+ """Yearn used to use yGift to send team grants but that ended up being too expensive."""
40
+ return tx.to_nickname == "Contract: yGift" and tx.symbol == "yyDAI+yUSDC+yUSDT+yTUSD"
41
+
42
+
43
+ # TODO: refactor all of this, there's gotta be a better way to handle yteams who have received both one-off and streamed pmnts
44
+ @grants("yHAAS Trinity [BR#263]")
45
+ def is_yhaas_trinity_ii(tx: TreasuryTx) -> bool:
46
+ """https://github.com/yearn/budget/issues/263"""
47
+ return (
48
+ tx.hash == "0xd35c30664f3241ea2ec3df1c70261086247025eb72c2bc919108dfef9b08a450"
49
+ and tx.to_address.address
50
+ in (
51
+ # team
52
+ "0x35a83D4C1305451E0448fbCa96cAb29A7cCD0811",
53
+ # stream
54
+ "0xEC83C8c3156e4f6b95B048066F3b308C93cb5848",
55
+ )
56
+ )
57
+
58
+
59
+ @grants("G-Team [BR#267]")
60
+ def is_gteam(tx: TreasuryTx) -> bool:
61
+ """https://github.com/yearn/budget/issues/267"""
62
+ return (
63
+ tx.hash == "0xd35c30664f3241ea2ec3df1c70261086247025eb72c2bc919108dfef9b08a450"
64
+ and tx.to_address == "0x63E02F93622541CfE41aFedCF96a114DB71Ba4EE"
65
+ )
66
+
67
+
68
+ @grants("Rantom [BR#129]")
69
+ def is_rantom(tx: TreasuryTx) -> bool:
70
+ """https://github.com/yearn/budget/issues/129"""
71
+ return tx.to_address == "0x254b42CaCf7290e72e2C84c0337E36E645784Ce1"
72
+
73
+
74
+ @grants("Worms")
75
+ def is_worms(tx: TreasuryTx) -> bool:
76
+ return tx.to_address == "0xB1d693B77232D88a3C9467eD5619FfE79E80BCCc"
77
+
78
+
79
+ # NOTE: this needs to go at the bottom because there are some streams that will already be caught by above matchers
80
+ @grants("Simple Vesting Escrow")
81
+ def is_simple_vesting_escrow(tx: TreasuryTx) -> bool:
82
+ # TODO: amortize the streamed funds as a daily amount and sort more granularly based on BR
83
+ return tx.to_nickname == "Contract: Simple Vesting Escrow"
@@ -0,0 +1,146 @@
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
+ security: Final = expense("Security")
15
+ audits: Final = security("Audits")
16
+ grants: Final = security("Grants")
17
+
18
+
19
+ @audits("yAcademy", Network.Mainnet)
20
+ def is_yacademy_audit(tx: TreasuryTx) -> bool:
21
+ """Expense for an audit performed by yAcademy"""
22
+ # NOTE: the hash we're excluding was a one-time revshare tx before the splitter was set up.
23
+ return (
24
+ tx.to_address == "0x0E0aF03c405E17D0e486354fe709d3294d07EC44"
25
+ and tx.hash != "0xdf3e6cf2e50052e4eeb57fb2562b5e1b02701014ce65b60e6c8a850c409b341a"
26
+ )
27
+
28
+
29
+ @audits("ChainSec", Network.Mainnet)
30
+ def is_chainsec_audit(tx: TreasuryTx) -> bool:
31
+ """Expense for an audit performed by chainsec"""
32
+ if (
33
+ tx.symbol in ["USDC", "USDT"]
34
+ and tx.to_address == "0x8bAf5eaF92E37CD9B1FcCD676918A9B3D4F87Dc7"
35
+ ):
36
+ return True
37
+
38
+ txhash = tx.hash
39
+ return txhash == "0x83ec212072f82f4aba4b512051d52c5f016de79a620a580622a0f051e3473a78" or (
40
+ # https://github.com/yearn/budget/issues/246
41
+ txhash == "0xd0fa31ccf6bf7577a533366955bb528d6d17c928bba1ff13ab273487a27d9602"
42
+ and tx.log_index == 254
43
+ )
44
+
45
+
46
+ @audits("StateMind", Network.Mainnet)
47
+ def is_statemind_audit(tx: TreasuryTx) -> bool:
48
+ """Expense for an audit performed by statemind"""
49
+ txhash = tx.hash
50
+ log_index = tx.log_index
51
+ if log_index is None:
52
+ return False
53
+ if (
54
+ txhash == "0xeb51cb5a3b4ae618be75bf3e23c2d8e333d93d5e81e869eca7f9612a30079822"
55
+ and log_index == 193
56
+ ):
57
+ return True
58
+ elif (
59
+ txhash == "0xcb79cbe5b68d04a1a3feab3360734277020ee0536380843a8c9db3e8356b81d6"
60
+ and log_index == 398
61
+ ):
62
+ return True
63
+ elif (
64
+ txhash == "0x3e75d22250d87c183824c3b77ddb9cb11935db2061ce7f34df4f024d0646fcfb"
65
+ and log_index == 115
66
+ ):
67
+ return True
68
+ return False
69
+
70
+
71
+ @audits("MixBytes", Network.Mainnet)
72
+ def is_mixbytes_audit(tx: TreasuryTx) -> bool:
73
+ """Expense for an audit performed by mixbytes"""
74
+ txhash = tx.hash
75
+ if (
76
+ txhash == "0xcb79cbe5b68d04a1a3feab3360734277020ee0536380843a8c9db3e8356b81d6"
77
+ and tx.log_index == 399
78
+ ):
79
+ return True
80
+ elif (
81
+ txhash == "0xca61496c32806ba34f0deb331c32969eda11c947fdd6235173e6fa13d9a1c288"
82
+ and tx.symbol == "USDC"
83
+ ):
84
+ return True
85
+ return False
86
+
87
+
88
+ @audits("Unspecified Audit", Network.Mainnet)
89
+ def is_other_audit(tx: TreasuryTx) -> bool:
90
+ txhash = tx.hash
91
+ if txhash in {
92
+ "0x7df5566cc9ff8ed0aafe126b74ad0e3957e62d530d007565ee32bd1303bcec32",
93
+ "0x5e95d5b0773eefaef9c7187d5e9187a89717d269f48e5dcf707acfe1a7e55cb9",
94
+ "0x9cfd1098c5459002a90ffa23931f7bbec430b3f2ec0ef2d3a641cef574eb0817",
95
+ "0x70cdcffa444f70754a1df2d80a1adf9c432dfe678381e05ac78ab50b9de9d393",
96
+ }:
97
+ return True
98
+ elif (
99
+ txhash == "0x70ecc34da6c461a0bb9dadfbc4d082a8486e742cbb454f0f67b2df384fb9bffc"
100
+ and tx.log_index == 89
101
+ ):
102
+ return True
103
+ return False
104
+
105
+
106
+ @security("Bug Bounty", Network.Mainnet)
107
+ def is_bug_bounty(tx: TreasuryTx) -> bool:
108
+ txhash = tx.hash
109
+ if txhash == "0x4df2eee567ebf2a41b555fca3fed41300b12ff2dc3c79ffaee8b7bdf262f9303":
110
+ return True
111
+ elif (
112
+ txhash == "0x5deca5d6c934372c174bbef8be9a1e103e06d8b93fd3bf8d77865dfeb34fe3be"
113
+ and tx.log_index in (100, 101)
114
+ ):
115
+ # Immunefi
116
+ return True
117
+ elif (
118
+ txhash == "0x3e045ced19590db8905d8a69c2f0fd0acd4f90301cf6356742e735cd7caa0964"
119
+ and tx.log_index == 327
120
+ ):
121
+ # Sherlock
122
+ return True
123
+ return False
124
+
125
+
126
+ security("Anti-Spam Discord Bot", Network.Mainnet).match(
127
+ hash="0xe397d5682ef780b5371f8c80670e0cd94b4f945c7b432319b24f65c288995a17",
128
+ log_index=357,
129
+ )
130
+
131
+
132
+ @security("War Room Assistance", Network.Mainnet)
133
+ def is_warroom_help(tx: TreasuryTx) -> bool:
134
+ """A past yearner was paid a one-time payment to assist in a war room."""
135
+ return (
136
+ tx.hash == "0xca61496c32806ba34f0deb331c32969eda11c947fdd6235173e6fa13d9a1c288"
137
+ and tx.log_index == 152
138
+ )
139
+
140
+
141
+ @grants("ySecurity", Network.Mainnet)
142
+ def is_ysecurity(tx: TreasuryTx) -> bool:
143
+ """
144
+ https://github.com/yearn/budget/issues/145
145
+ """
146
+ 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,91 @@
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
+ DSPROXY: Final = "0xd42e1Cb8b98382df7Db43e0F09dFE57365659D16"
17
+ DEPOSIT_EVENT_ARGS: Final = "ilk", "usr", "wad"
18
+ WITHDRAWAL_EVENT_ARGS: Final = "cdp", "dst", "wad"
19
+
20
+ maker: Final = ignore("Maker")
21
+ dai: Final = maker("DAI")
22
+ dsr: Final = maker("DSR")
23
+ cdp: Final = maker("CDP")
24
+
25
+
26
+ dai("Minting").match(symbol="DAI", from_address=ZERO_ADDRESS)
27
+ dai("Burning").match(symbol="DAI", to_address=DSPROXY)
28
+
29
+ # sending DAI to or receiving DAI back from Maker's DSR module
30
+ dsr("Deposit").match(to_nickname="Contract: DsrManager")
31
+ dsr("Withdrawal").match(from_nickname="Contract: DsrManager")
32
+
33
+
34
+ @cdp("YFI Deposit")
35
+ def is_yfi_cdp_deposit(tx: TreasuryTx) -> bool:
36
+ if tx.symbol == "YFI" and TreasuryWallet.check_membership(
37
+ tx.from_address.address, tx.block # type: ignore [union-attr, arg-type]
38
+ ):
39
+ for event in tx.get_events("slip"):
40
+ if all(arg in event for arg in DEPOSIT_EVENT_ARGS):
41
+ # TODO: remove this rounding once we move to postgres
42
+ scaled = round(Decimal(event["wad"]) / 10**18, 12)
43
+ rounded = round(tx.amount, 12)
44
+ if scaled == rounded:
45
+ return True
46
+ print(f"yfi cdp deposit amount no match [{scaled}, {rounded}]")
47
+ return False
48
+
49
+
50
+ @cdp("YFI Withdrawal")
51
+ def is_yfi_cdp_withdrawal(tx: TreasuryTx) -> bool:
52
+ if tx.symbol == "YFI" and TreasuryWallet.check_membership(
53
+ tx.to_address.address, tx.block # type: ignore [union-attr, arg-type]
54
+ ):
55
+ for event in tx.get_events("flux"):
56
+ if all(arg in event for arg in WITHDRAWAL_EVENT_ARGS):
57
+ # TODO: remove this rounding once we move to postgres
58
+ scaled = round(Decimal(event["wad"]) / 10**18, 12)
59
+ rounded = round(tx.amount, 12)
60
+ if scaled == rounded:
61
+ return True
62
+ print(f"yfi cdp withdrawal amount no match [{scaled}, {rounded}]")
63
+ return False
64
+
65
+
66
+ @cdp("USDC Deposit")
67
+ def is_usdc_cdp_deposit(tx: TreasuryTx) -> bool:
68
+ if tx.symbol == "USDC" and TreasuryWallet.check_membership(
69
+ tx.from_address.address, tx.block # type: ignore [union-attr, arg-type]
70
+ ):
71
+ for event in tx.get_events("slip"):
72
+ if all(arg in event for arg in DEPOSIT_EVENT_ARGS):
73
+ scaled = Decimal(event["wad"]) / 10**18
74
+ if scaled == tx.amount:
75
+ return True
76
+ print(f"usdc cdp deposit amount no match [{scaled}, {tx.amount}]")
77
+ return False
78
+
79
+
80
+ @cdp("USDC Withdrawal")
81
+ def is_usdc_cdp_withdrawal(tx: TreasuryTx) -> bool:
82
+ if tx.symbol == "USDC" and TreasuryWallet.check_membership(
83
+ tx.to_address.address, tx.block # type: ignore [union-attr, arg-type]
84
+ ):
85
+ for event in tx.get_events("flux"):
86
+ if all(arg in event for arg in WITHDRAWAL_EVENT_ARGS):
87
+ scaled = Decimal(event["wad"]) / 10**18
88
+ if scaled == tx.amount:
89
+ return True
90
+ print(f"usdc cdp withdrawal amount no match [{scaled}, {tx.amount}]")
91
+ return False