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.
- yearn_treasury/__init__.py +19 -0
- yearn_treasury/_db.cp310-win32.pyd +0 -0
- yearn_treasury/_db.py +50 -0
- yearn_treasury/_ens.cp310-win32.pyd +0 -0
- yearn_treasury/_ens.py +30 -0
- yearn_treasury/_logging.cp310-win32.pyd +0 -0
- yearn_treasury/_logging.py +41 -0
- yearn_treasury/address_labels.yaml +39 -0
- yearn_treasury/budget/__init__.cp310-win32.pyd +0 -0
- yearn_treasury/budget/__init__.py +6 -0
- yearn_treasury/budget/_request.cp310-win32.pyd +0 -0
- yearn_treasury/budget/_request.py +43 -0
- yearn_treasury/budget/_requests.cp310-win32.pyd +0 -0
- yearn_treasury/budget/_requests.py +96 -0
- yearn_treasury/constants.py +91 -0
- yearn_treasury/main.py +175 -0
- yearn_treasury/py.typed +1 -0
- yearn_treasury/rules/__init__.py +20 -0
- yearn_treasury/rules/constants.cp310-win32.pyd +0 -0
- yearn_treasury/rules/constants.py +15 -0
- yearn_treasury/rules/cost_of_revenue/__init__.py +1 -0
- yearn_treasury/rules/cost_of_revenue/gas.cp310-win32.pyd +0 -0
- yearn_treasury/rules/cost_of_revenue/gas.py +64 -0
- yearn_treasury/rules/cost_of_revenue/match_on_hash.yaml +12 -0
- yearn_treasury/rules/expense/__init__.cp310-win32.pyd +0 -0
- yearn_treasury/rules/expense/__init__.py +4 -0
- yearn_treasury/rules/expense/general.cp310-win32.pyd +0 -0
- yearn_treasury/rules/expense/general.py +13 -0
- yearn_treasury/rules/expense/infrastructure.cp310-win32.pyd +0 -0
- yearn_treasury/rules/expense/infrastructure.py +46 -0
- yearn_treasury/rules/expense/match_on_hash.yaml +48 -0
- yearn_treasury/rules/expense/match_on_to_address.yaml +7 -0
- yearn_treasury/rules/expense/people.cp310-win32.pyd +0 -0
- yearn_treasury/rules/expense/people.py +83 -0
- yearn_treasury/rules/expense/security.cp310-win32.pyd +0 -0
- yearn_treasury/rules/expense/security.py +146 -0
- yearn_treasury/rules/ignore/__init__.py +8 -0
- yearn_treasury/rules/ignore/general.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/general.py +11 -0
- yearn_treasury/rules/ignore/maker.py +91 -0
- yearn_treasury/rules/ignore/passthru.py +309 -0
- yearn_treasury/rules/ignore/staking.py +101 -0
- yearn_treasury/rules/ignore/swaps/__init__.py +24 -0
- yearn_treasury/rules/ignore/swaps/_skip_tokens.py +8 -0
- yearn_treasury/rules/ignore/swaps/aave.py +68 -0
- yearn_treasury/rules/ignore/swaps/auctions.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/auctions.py +30 -0
- yearn_treasury/rules/ignore/swaps/compound.py +57 -0
- yearn_treasury/rules/ignore/swaps/conversion_factory.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/conversion_factory.py +20 -0
- yearn_treasury/rules/ignore/swaps/cowswap.py +86 -0
- yearn_treasury/rules/ignore/swaps/curve.py +174 -0
- yearn_treasury/rules/ignore/swaps/gearbox.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/gearbox.py +36 -0
- yearn_treasury/rules/ignore/swaps/iearn.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/iearn.py +41 -0
- yearn_treasury/rules/ignore/swaps/otc.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/otc.py +58 -0
- yearn_treasury/rules/ignore/swaps/pooltogether.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/pooltogether.py +23 -0
- yearn_treasury/rules/ignore/swaps/synthetix.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/synthetix.py +10 -0
- yearn_treasury/rules/ignore/swaps/uniswap.py +293 -0
- yearn_treasury/rules/ignore/swaps/unwrapper.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/unwrapper.py +17 -0
- yearn_treasury/rules/ignore/swaps/vaults.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/vaults.py +263 -0
- yearn_treasury/rules/ignore/swaps/woofy.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/woofy.py +79 -0
- yearn_treasury/rules/ignore/swaps/yfi.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/yfi.py +110 -0
- yearn_treasury/rules/ignore/swaps/yla.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/swaps/yla.py +27 -0
- yearn_treasury/rules/ignore/unit.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/unit.py +39 -0
- yearn_treasury/rules/ignore/weth.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/weth.py +47 -0
- yearn_treasury/rules/ignore/ygov.cp310-win32.pyd +0 -0
- yearn_treasury/rules/ignore/ygov.py +15 -0
- yearn_treasury/rules/other_expense/__init__.cp310-win32.pyd +0 -0
- yearn_treasury/rules/other_expense/__init__.py +7 -0
- yearn_treasury/rules/other_expense/boost.cp310-win32.pyd +0 -0
- yearn_treasury/rules/other_expense/boost.py +49 -0
- yearn_treasury/rules/other_expense/bugs.cp310-win32.pyd +0 -0
- yearn_treasury/rules/other_expense/bugs.py +80 -0
- yearn_treasury/rules/other_expense/donations.cp310-win32.pyd +0 -0
- yearn_treasury/rules/other_expense/donations.py +42 -0
- yearn_treasury/rules/other_expense/dyfi.cp310-win32.pyd +0 -0
- yearn_treasury/rules/other_expense/dyfi.py +28 -0
- yearn_treasury/rules/other_expense/events.cp310-win32.pyd +0 -0
- yearn_treasury/rules/other_expense/events.py +20 -0
- yearn_treasury/rules/other_expense/match_on_hash.yaml +43 -0
- yearn_treasury/rules/other_expense/match_on_to_address.yaml +8 -0
- yearn_treasury/rules/other_expense/misc.cp310-win32.pyd +0 -0
- yearn_treasury/rules/other_expense/misc.py +48 -0
- yearn_treasury/rules/other_expense/revshare.cp310-win32.pyd +0 -0
- yearn_treasury/rules/other_expense/revshare.py +19 -0
- yearn_treasury/rules/other_income/__init__.cp310-win32.pyd +0 -0
- yearn_treasury/rules/other_income/__init__.py +2 -0
- yearn_treasury/rules/other_income/airdrops.cp310-win32.pyd +0 -0
- yearn_treasury/rules/other_income/airdrops.py +29 -0
- yearn_treasury/rules/other_income/match_on_hash.yaml +21 -0
- yearn_treasury/rules/other_income/misc.cp310-win32.pyd +0 -0
- yearn_treasury/rules/other_income/misc.py +78 -0
- yearn_treasury/rules/revenue/__init__.py +6 -0
- yearn_treasury/rules/revenue/bribes.cp310-win32.pyd +0 -0
- yearn_treasury/rules/revenue/bribes.py +25 -0
- yearn_treasury/rules/revenue/farming.cp310-win32.pyd +0 -0
- yearn_treasury/rules/revenue/farming.py +55 -0
- yearn_treasury/rules/revenue/keepcoins.cp310-win32.pyd +0 -0
- yearn_treasury/rules/revenue/keepcoins.py +61 -0
- yearn_treasury/rules/revenue/match_on_hash.yaml +4 -0
- yearn_treasury/rules/revenue/seasolver.cp310-win32.pyd +0 -0
- yearn_treasury/rules/revenue/seasolver.py +23 -0
- yearn_treasury/rules/revenue/vaults.py +171 -0
- yearn_treasury/rules/revenue/yteams.cp310-win32.pyd +0 -0
- yearn_treasury/rules/revenue/yteams.py +16 -0
- yearn_treasury/shitcoins.py +143 -0
- yearn_treasury/vaults.cp310-win32.pyd +0 -0
- yearn_treasury/vaults.py +49 -0
- yearn_treasury/wallets.yaml +54 -0
- yearn_treasury/yteams.py +207 -0
- yearn_treasury-0.1.7.dist-info/METADATA +85 -0
- yearn_treasury-0.1.7.dist-info/RECORD +128 -0
- yearn_treasury-0.1.7.dist-info/WHEEL +5 -0
- yearn_treasury-0.1.7.dist-info/entry_points.txt +2 -0
- yearn_treasury-0.1.7.dist-info/top_level.txt +2 -0
- 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"
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
+
)
|
|
Binary file
|
|
@@ -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
|
+
|
|
Binary file
|
|
@@ -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"
|
|
Binary file
|
|
@@ -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 *
|
|
Binary file
|
|
@@ -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
|