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