Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 53 additions & 9 deletions brownie/allocations.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@


def load_from_blockchain():
meta_3pool_dollars = world.ousd_metapool.balances(1) * world.threepool.get_virtual_price() / 1e18
meta_ousd_dollars = world.ousd_metapool.balances(0)
meta_stables_mix = meta_3pool_dollars / (meta_ousd_dollars + meta_3pool_dollars)

base = pd.DataFrame.from_records(
[
["AAVE", "DAI", int(world.aave_strat.checkBalance(world.DAI) / 1e18)],
Expand All @@ -63,7 +67,10 @@ def load_from_blockchain():
["MORPHO_AAVE", "USDT", int(world.morpho_aave_strat.checkBalance(world.USDT) / 1e6)],
["CONVEX", "*", int(world.convex_strat.checkBalance(world.DAI) * 3 / 1e18)],
["LUSD_3POOL", "*", int(world.lusd_3pool_strat.checkBalance(world.DAI) * 3 / 1e18)],
["OUSD_META", "*", int(world.ousd_meta_strat.checkBalance(world.DAI) * 3 / 2 / 1e18)],
["OUSD_META", "*", int(world.ousd_meta_strat.checkBalance(world.DAI) * 3 * meta_stables_mix / 1e18)],
['VAULT','DAI', int(world.dai.balanceOf(world.vault_core)/ 1e18) ],
['VAULT','USDC', int(world.usdc.balanceOf(world.vault_core)/ 1e6)],
['VAULT','USDT', int(world.usdt.balanceOf(world.vault_core)/ 1e6)],
],
columns=["strategy", "token", "current_dollars"],
)
Expand All @@ -86,6 +93,32 @@ def reallocate(from_strat, to_strat, funds):
coins.append(coin)
return world.vault_admin.reallocate(from_strat, to_strat, coins, amounts, {"from": world.STRATEGIST})

def from_strat(from_strat, funds):
"""
Execute and return a transaction reallocating funds from one strat to another
"""
if isinstance(from_strat, str) and from_strat[0:2] != "0x":
from_strat = NAME_TO_STRAT[from_strat]
amounts = []
coins = []
for [dollars, coin] in funds:
amounts.append(int(dollars * 10 ** coin.decimals()))
coins.append(coin)
return world.vault_admin.withdrawFromStrategy(from_strat, coins, amounts, {"from": world.STRATEGIST})

def to_strat(to_strat, funds):
"""
Execute and return a transaction depositing to a strat
"""
if isinstance(to_strat, str) and to_strat[0:2] != "0x":
to_strat = NAME_TO_STRAT[to_strat]
amounts = []
coins = []
for [dollars, coin] in funds:
amounts.append(int(dollars * 10 ** coin.decimals()))
coins.append(coin)
return world.vault_admin.depositToStrategy(to_strat, coins, amounts, {"from": world.STRATEGIST})


def allocation_exposure(allocation):
"""
Expand Down Expand Up @@ -147,9 +180,17 @@ def __exit__(self, *args, **kwargs):
else:
vault_change = world.vault_core.totalValue() - self.before_vault_value
supply_change = world.ousd.totalSupply() - self.before_total_supply
after_allocaiton = with_target_allocations(load_from_blockchain(), self.before_votes)
print(pretty_allocations(after_allocaiton))
allocation_exposure(after_allocaiton)
after_allocation = with_target_allocations(load_from_blockchain(), self.before_votes)
print(pretty_allocations(after_allocation))
print("Coin deltas to target")
print(after_allocation.groupby('token')['delta_dollars'].sum().apply("{:,}".format))
allocation_exposure(after_allocation)

print('Vault Direct Holdings:')
print(" DAI", world.c18(world.dai.balanceOf(world.vault_core)))
print(" USDC", world.c6(world.usdc.balanceOf(world.vault_core)))
print(" USDT", world.c6(world.usdt.balanceOf(world.vault_core)))

show_default_strategies()
print("Vault change", world.c18(vault_change))
print("Supply change", world.c18(supply_change))
Expand Down Expand Up @@ -190,14 +231,17 @@ def with_target_allocations(allocation, votes):
print(df["target_allocation"].sum())
raise Exception("Target allocations total too low")

df["target_dollars"] = (
df["current_dollars"].sum() * df["target_allocation"] / df["target_allocation"].sum()
).astype(int)
if isinstance(votes, pd.DataFrame):
df["target_dollars"] = votes["target_dollars"]
else:
df["target_dollars"] = (
df["current_dollars"].sum() * df["target_allocation"] / df["target_allocation"].sum()
).astype(int)
df["delta_dollars"] = df["target_dollars"] - df["current_dollars"]
return df


def pretty_allocations(allocation, close_enough=50_000):
def pretty_allocations(allocation, close_enough=255_000):
df = allocation.copy()
df["s"] = ""
df.loc[df["delta_dollars"].abs() < close_enough, "s"] = "✔︎"
Expand All @@ -206,7 +250,7 @@ def pretty_allocations(allocation, close_enough=50_000):
df["current_dollars"] = df["current_dollars"].apply("{:,}".format)
df["target_dollars"] = df["target_dollars"].apply("{:,}".format)
df["delta_dollars"] = df["delta_dollars"].apply("{:,}".format)
return df.sort_values("token")
return df.sort_values("strategy")


def net_delta(allocation):
Expand Down
239 changes: 238 additions & 1 deletion brownie/runlogs/2023_01_strategist.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,4 +397,241 @@
safe = ApeSafe('0xF14BBdf064E3F67f51cd9BD646aE3716aD938FDC')
safe_tx = safe.multisend_from_receipts(txs)
safe.sign_with_frame(safe_tx)
r = safe.post_transaction(safe_tx)
r = safe.post_transaction(safe_tx)


# --------------------------------
# Jan 26, 2023 - Weekly allocation
# (new style protoype, not run)
#

from addresses import *
from world import *
from allocations import *
from ape_safe import ApeSafe

# Temp for local fork testing
whale = accounts.at(BIGWALLET, force=True)
unlock(whale.address)
whale.transfer(STRATEGIST, 1e18)

votes = """
Convex OUSD+3Crv 35.3%
Morpho Compound USDC 32.09%
Morpho Compound USDT 12.15%
Morpho Aave USDT 11.96%
Morpho Aave USDC 4.04%
Aave DAI 0.24%
Aave USDC 0.24%
Aave USDT 0.24%
Compound DAI 0.19%
Compound USDC 0.19%
Compound USDT 0.19%
Convex LUSD+3Crv 0.19%
Existing Allocation 0%
Convex DAI+USDC+USDT 0%
Morpho Aave DAI 3%
Morpho Compound DAI 0%
"""

with TemporaryForkWithVaultStats(votes):
before_votes = with_target_allocations(load_from_blockchain(), votes)
txs = []
txs.extend(auto_take_snapshot())

# From
from_strat(MORPHO_AAVE_STRAT,[[380_000, dai], [8_124_000, usdt]])
from_strat(MORPHO_COMP_STRAT,[[864_000, dai]])
from_strat(OUSD_META_STRAT,[[3_000_000, usdc]])

# Convert
to_strat(CONVEX_STRAT,[[1_244_000, dai], [4_905_000, usdt]])
from_strat(CONVEX_STRAT,[[7_149_000, usdc]])

# To
to_strat(MORPHO_COMP_STRAT,[[10_149_000, usdc], [3_271_000, usdt]])
txs.append(vault_admin.setAssetDefaultStrategy(usdc, MORPHO_COMP_STRAT, {'from':STRATEGIST}))
txs.append(vault_admin.setAssetDefaultStrategy(usdt, MORPHO_COMP_STRAT, {'from':STRATEGIST}))

txs.extend(auto_check_snapshot())
print("Est Gas Max: {:,}".format(1.10*sum([x.gas_used for x in txs])))


safe = ApeSafe('0xF14BBdf064E3F67f51cd9BD646aE3716aD938FDC')
safe_tx = safe.multisend_from_receipts(txs)
safe.sign_with_frame(safe_tx)
r = safe.post_transaction(safe_tx)


# --------------------------------
# Jan 30, 2023 - Weekly allocation
#

from addresses import *
from world import *
from allocations import *
from ape_safe import ApeSafe

votes = """
Convex OUSD+3Crv 35.3%
Morpho Compound USDC 32.09%
Morpho Compound USDT 12.15%
Morpho Aave USDT 11.96%
Morpho Aave USDC 4.04%
Aave DAI 0.24%
Aave USDC 0.24%
Aave USDT 0.24%
Compound DAI 0.19%
Compound USDC 0.19%
Compound USDT 0.19%
Convex LUSD+3Crv 0.19%
Existing Allocation 0%
Convex DAI+USDC+USDT 0%
Morpho Aave DAI 3%
Morpho Compound DAI 0%
"""

with TemporaryForkWithVaultStats(votes):
before_votes = with_target_allocations(load_from_blockchain(), votes)
txs = []
txs.extend(auto_take_snapshot())

txs.append(reallocate(MORPHO_AAVE_STRAT, MORPHO_COMP_STRAT, [[3_271_000, usdt]]))
txs.append(reallocate(MORPHO_COMP_STRAT, MORPHO_AAVE_STRAT, [[864_000, dai]]))

# Swap
txs.append(reallocate(MORPHO_AAVE_STRAT, CONVEX_STRAT, [[1_244_000, dai], [4_852_000, usdt]]))
txs.append(reallocate(CONVEX_STRAT, MORPHO_COMP_STRAT, [[7_165_000, usdc]]))

# From meta
txs.append(reallocate(OUSD_META_STRAT, MORPHO_COMP_STRAT, [[3_330_000, usdc]]))

txs.extend(auto_check_snapshot())
print("Est Gas Max: {:,}".format(1.10*sum([x.gas_used for x in txs])))


safe = ApeSafe('0xF14BBdf064E3F67f51cd9BD646aE3716aD938FDC')
safe_tx = safe.multisend_from_receipts(txs)
safe.sign_with_frame(safe_tx)
r = safe.post_transaction(safe_tx)


# --------------------------------
# Jan 31, 2023 - Transfer OUSD
#

from world import *

def make_governable(pair):
return Contract.from_abi(pair[1], pair[0], buyback.abi)

def parse_contracts(s):
out = []
for line in s.split("\n"):
tokens = line.split(" ")
if len(tokens) == 2:
g = make_governable(tokens)
out.append(g)
return out


transfer_contracts = parse_contracts("""
0x6C5cdfB47150EFc52072cB93Eea1e0F123529748 Buyback
0x7294CD3C3eb4097b03E1A61EB2AD280D3dD265e6 Buyback
0x77314EB392b2be47C014cde0706908b3307Ad6a9 Buyback
0x2A8e1E676Ec238d8A992307B495b45B3fEAa5e86 OUSDProxy
0xE75D77B1865Ae93c7eaa3040B038D7aA7BC02F70 VaultProxy
0x9c459eeb3FA179a40329b81C1635525e9A0Ef094 InitializeGovernedUpgradeabilityProxy
0x21Fb5812D70B3396880D30e90D9e5C1202266c89 HarvesterProxy
0x80C898ae5e56f888365E235CeB8CEa3EB726CB58 HarvesterProxy
0x5e3646A1Db86993f73E6b74A57D8640B69F7e259 InitializeGovernedUpgradeabilityProxy
0xEA2Ef2e2E5A749D4A66b41Db9aD85a38Aa264cb3 ConvexStrategyProxy
0x89Eb88fEdc50FC77ae8a18aAD1cA0ac27f777a90 ConvexUSDDMetaStrategyProxy
0x5A4eEe58744D1430876d5cA93cAB5CcB763C037D MorphoCompoundStrategyProxy
0x7A192DD9Cc4Ea9bdEdeC9992df74F1DA55e60a19 ConvexLUSDMetaStrategyProxy
0x79F2188EF9350A1dC11A062cca0abE90684b0197 MorphoAaveStrategyProxy
0xD2af830E8CBdFed6CC11Bab697bB25496ed6FA62 wOUSDProxy
0x501804B374EF06fa9C427476147ac09F1551B9A0 InitializeGovernedUpgradeabilityProxy
""")

accept_only_contracts = parse_contracts("""
0x997c35A0bf8E21404aE4379841E0603C957138c3 VaultCore
""")

# Another day: 0x52BEBd3d7f37EC4284853Fd5861Ae71253A7F428 OldTimelock

all_contracts = [*transfer_contracts, *accept_only_contracts]

# Pre-transfer old vault core
g = make_governable(['0x997c35A0bf8E21404aE4379841E0603C957138c3', 'VaultCore'])
g.transferGovernance(TIMELOCK, {'from': g.governor()})


for c in all_contracts:
print(c.governor(), c._name)


# --- Old governor

with TemporaryFork():
gov_txs = []
for c in transfer_contracts:
gov_txs.append(c.transferGovernance(TIMELOCK, {'from':GOVERNOR}))

governor.propose(
[x.receiver for x in gov_txs],
['transferGovernance(address)' for x in gov_txs],
[x.input[10:] for x in gov_txs],
"Transfer governance of OUSD to veOGV governance system",
{'from': GOV_MULTISIG }
)

print(history[-1].receiver)
print(history[-1].input)
print(history[-1].events)
proposal_id = history[-1].events['ProposalCreated'][0]['id']
print(proposal_id)

sim_governor_execute(proposal_id)


# --- New governor

accept_txs = []
with TemporaryFork():
for c in all_contracts:
accept_txs.append(c.claimGovernance({'from': TIMELOCK}))

governor_five.propose(
[x.receiver for x in accept_txs],
[0 for x in accept_txs],
['claimGovernance()' for x in accept_txs],
['' for x in accept_txs],
"Claim governance of OUSD contracts\n\nAll OUSD governance contracts will be owned by the veOGV governance system.",
{'from': GOV_MULTISIG }
)

print("Raw proposal:")
print(history[-1].receiver)
print(history[-1].input)
print(history[-1].events)
proposal_id = history[-1].events['ProposalCreated'][0]['proposalId']
print(proposal_id)

print("...Simulating vote")
chain.mine()
governor_five.castVote(proposal_id, 1, {'from': GOV_MULTISIG})

print("...Simulating voting time, going to take time")
chain.mine(governor_five.votingPeriod() + 1)

print("...Simulating queue")
governor_five.queue(proposal_id, {'from': GOV_MULTISIG})
chain.mine(timedelta=2*24*60*60+2)

print("...Simulating execution")
governor_five.execute(proposal_id, {'from': GOV_MULTISIG})


for c in all_contracts:
print(c.governor(), c._name)
Loading