Skip to content

Commit

Permalink
Merge branch 'master' into shah/oethb-async-withdrawal
Browse files Browse the repository at this point in the history
  • Loading branch information
shahthepro committed Oct 25, 2024
2 parents 6f42f78 + 95ece09 commit 09ece7c
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 14 deletions.
150 changes: 149 additions & 1 deletion brownie/runlogs/2024_10_strategist.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,4 +298,152 @@ def main():
aero.approve(OETHB_HARVESTER, 0, from_strategist)
)

print(to_gnosis_json(txs, OETHB_STRATEGIST, "8453"))
print(to_gnosis_json(txs, OETHB_STRATEGIST, "8453"))

# -------------------------------------------
# Oct 16 2024 - Rebalance and Withdraw from OETH AMO Strategy
# -------------------------------------------

from world import *

def main():
with TemporaryForkForReallocations() as txs:


# Before
txs.append(vault_core.rebase({ 'from': OETHB_STRATEGIST }))
txs.append(oeth_vault_value_checker.takeSnapshot({'from': STRATEGIST}))

# AMO pool before
ethPoolBalance = oeth_metapool.balance()
oethPoolBalance = oeth.balanceOf(OETH_METAPOOL)
totalPool = ethPoolBalance + oethPoolBalance
eth_out_before = oeth_metapool.get_dy(1, 0, 10 * 10**18)

print("Curve OETH/ETH Pool before")
print("Pool ETH ", "{:.6f}".format(ethPoolBalance / 10**18), ethPoolBalance * 100 / totalPool)
print("Pool OETH ", "{:.6f}".format(oethPoolBalance / 10**18), oethPoolBalance * 100 / totalPool)
print("Pool Total ", "{:.6f}".format(totalPool / 10**18), totalPool)

# remove the 10k OETH to increase the price of OETH in the OETH/ETH Curve pool
metapool_virtual_price = 1001921431201396942
lp_amount = 1100 * 10**18 * 10**18 / metapool_virtual_price
txs.append(
oeth_meta_strat.removeAndBurnOTokens(
lp_amount,
std
)
)

# Remove WETH from strategy and burn equivalent OETH
txs.append(
vault_oeth_admin.withdrawFromStrategy(
OETH_CONVEX_OETH_ETH_STRAT,
[weth],
[310 * 10**18],
{'from': STRATEGIST}
)
)

# After
vault_change = vault_oeth_core.totalValue() - oeth_vault_value_checker.snapshots(STRATEGIST)[0]
supply_change = oeth.totalSupply() - oeth_vault_value_checker.snapshots(STRATEGIST)[1]
profit = vault_change - supply_change
txs.append(oeth_vault_value_checker.checkDelta(profit, (0.1 * 10**18), vault_change, (0.1 * 10**18), {'from': STRATEGIST}))
print("-----")
snap_value = oeth_vault_value_checker.snapshots(STRATEGIST)[0]
snap_supply = oeth_vault_value_checker.snapshots(STRATEGIST)[1]
print("Snap value ", "{:.6f}".format(snap_value / 10**18), snap_value)
print("Snap supply", "{:.6f}".format(snap_supply / 10**18), snap_supply)
print("Profit", "{:.6f}".format(profit / 10**18), profit)
print("Vault Change", "{:.6f}".format(vault_change / 10**18), vault_change)
print("-----")


# AMO pool after
ethPoolBalance = oeth_metapool.balance()
oethPoolBalance = oeth.balanceOf(OETH_METAPOOL)
totalPool = ethPoolBalance + oethPoolBalance
eth_out_after = oeth_metapool.get_dy(1, 0, 10 * 10**18)

print("Curve OETH/ETH Pool after")
print("Pool ETH ", "{:.6f}".format(ethPoolBalance / 10**18), ethPoolBalance * 100 / totalPool)
print("Pool OETH ", "{:.6f}".format(oethPoolBalance / 10**18), oethPoolBalance * 100 / totalPool)
print("Pool Total ", "{:.6f}".format(totalPool / 10**18), totalPool)

print("-----")
print("Burn LP amount", "{:.6f}".format(lp_amount / 10**18), lp_amount)
print("Sell 10 OETH Curve prices before and after", "{:.6f}".format(eth_out_before / 10**18), "{:.6f}".format(eth_out_after / 10**18))

# Test the OETH ARM can claim its withdrawals
txs.append(
vault_oeth_core.claimWithdrawals(
[76, 77],
{'from': OETH_ARM}
)
)

# -----------------------------------------------------
# Oct 17th 2024 - OUSD Reallocation 2.483m USDC from Morpho Aave to new MetaMorpho
# -----------------------------------------------------
from world import *

def main():
with TemporaryForkForReallocations() as txs:
# Before
txs.append(vault_core.rebase({'from':STRATEGIST}))
txs.append(vault_value_checker.takeSnapshot({'from':STRATEGIST}))

# Withdraw 2.483m from Morpho Aave
txs.append(
vault_admin.withdrawFromStrategy(
MORPHO_AAVE_STRAT,
[usdc],
[2_483_000 * 10**6],
{'from': STRATEGIST}
)
)

# Put everything in new MetaMorpho
txs.append(
vault_admin.depositToStrategy(
MORPHO_META_USDC_STRAT,
[usdc],
[2_483_000*10**6],
{'from': STRATEGIST}
)
)

# After
vault_change = vault_core.totalValue() - vault_value_checker.snapshots(STRATEGIST)[0]
supply_change = ousd.totalSupply() - vault_value_checker.snapshots(STRATEGIST)[1]
profit = vault_change - supply_change

txs.append(vault_value_checker.checkDelta(profit, (500 * 10**18), vault_change, (500 * 10**18), {'from': STRATEGIST}))
print("-----")
print("Profit", "{:.6f}".format(profit / 10**18), profit)
print("Vault Change", "{:.6f}".format(vault_change / 10**18), vault_change)

# -----------------------------------------------------
# Oct 22, 2024 - Change the USDC default strategy from Morpho Aave V2 to the new Meta Morpho strategy
# -----------------------------------------------------

from world import *

def main():
with TemporaryForkForReallocations() as txs:
# Before
txs.append(vault_core.rebase({'from':STRATEGIST}))
txs.append(vault_value_checker.takeSnapshot({'from':STRATEGIST}))

txs.append(vault_admin.setAssetDefaultStrategy(USDC, MORPHO_META_USDC_STRAT, {'from':STRATEGIST}))

# After
vault_change = vault_core.totalValue() - vault_value_checker.snapshots(STRATEGIST)[0]
supply_change = ousd.totalSupply() - vault_value_checker.snapshots(STRATEGIST)[1]
profit = vault_change - supply_change

txs.append(vault_value_checker.checkDelta(profit, (500 * 10**18), vault_change, (500 * 10**18), {'from': STRATEGIST}))
print("-----")
print("Profit", "{:.6f}".format(profit / 10**18), profit)
print("Vault Change", "{:.6f}".format(vault_change / 10**18), vault_change)
2 changes: 1 addition & 1 deletion contracts/contracts/vault/VaultCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ contract VaultCore is VaultInitializer {
emit YieldDistribution(_trusteeAddress, yield, fee);
}

// Only rachet OToken supply upwards
// Only ratchet OToken supply upwards
ousdSupply = oUSD.totalSupply(); // Final check should use latest value
if (vaultValue > ousdSupply) {
oUSD.changeSupply(vaultValue);
Expand Down
27 changes: 27 additions & 0 deletions contracts/deploy/base/018_strategist_as_executor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { deployOnBaseWithGuardian } = require("../../utils/deploy-l2");
const addresses = require("../../utils/addresses");

const EXECUTOR_ROLE =
"0xd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63";

module.exports = deployOnBaseWithGuardian(
{
deployName: "018_strategist_as_executor",
},
async ({ ethers }) => {
const cTimelock = await ethers.getContractAt(
"ITimelockController",
addresses.base.timelock
);

return {
actions: [
{
contract: cTimelock,
signature: "grantRole(bytes32,address)",
args: [EXECUTOR_ROLE, addresses.base.strategist],
},
],
};
}
);
3 changes: 2 additions & 1 deletion contracts/deployments/base/.migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@
"014_fixed_rate_dripper": 1727409372,
"015_harvester": 1727718319,
"016_timelock_2d_delay": 1727845272,
"017_upgrade_amo": 1728599745
"017_upgrade_amo": 1728599745,
"018_strategist_as_executor": 1729078818
}
21 changes: 17 additions & 4 deletions contracts/scripts/defender-actions/harvest.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,33 @@ const harvest = async (
signer,
stratDesc
) => {
const nativeStakingStrategy1 = new ethers.Contract(
const nativeStakingStrategy = new ethers.Contract(
nativeStakingProxyAddress,
nativeStakingStrategyAbi,
signer
);
const consensusRewards = await nativeStakingStrategy1.consensusRewards();
const consensusRewards = await nativeStakingStrategy.consensusRewards();
log(`Consensus rewards for ${stratDesc}: ${formatUnits(consensusRewards)}`);
if (consensusRewards.gt(parseEther("1"))) {

const feeAccumulatorAddress =
await nativeStakingStrategy.FEE_ACCUMULATOR_ADDRESS();
const executionRewards = await signer.provider.getBalance(
feeAccumulatorAddress
);
log(`Execution rewards for ${stratDesc}: ${formatUnits(executionRewards)}`);

if (
consensusRewards.gt(parseEther("1")) ||
executionRewards.gt(parseEther("0.5"))
) {
const tx1 = await harvester
.connect(signer)
.harvestAndSwap(nativeStakingProxyAddress);
await logTxDetails(tx1, `${stratDesc} harvestAndSwap`);
} else {
log(`Skipping ${stratDesc} harvestAndSwap due to low consensus rewards`);
log(
`Skipping ${stratDesc} harvestAndSwap due to low consensus and execution rewards`
);
}
};

Expand Down
10 changes: 5 additions & 5 deletions contracts/test/strategies/morpho-aave.mainnet.fork-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,28 +47,28 @@ describe("ForkTest: Morpho Aave Strategy", function () {

const supplyBeforeMint = await ousd.totalSupply();

const amount = "10010";
const redeemAmount = ousdUnits("30000");

// Mint with all three assets
for (const asset of [usdt, usdc, dai]) {
await vault
.connect(anna)
.mint(asset.address, await units(amount, asset), 0);
.mint(asset.address, await units("15000", asset), 0);
}

const currentSupply = await ousd.totalSupply();
const supplyAdded = currentSupply.sub(supplyBeforeMint);
expect(supplyAdded).to.approxEqualTolerance(ousdUnits("30000"), 1);
expect(supplyAdded).to.gt(redeemAmount);

const currentBalance = await ousd.connect(anna).balanceOf(anna.address);

// Now try to redeem 30k
await vault.connect(anna).redeem(ousdUnits("30000"), 0);
await vault.connect(anna).redeem(redeemAmount, 0);

// User balance should be down by 30k
const newBalance = await ousd.connect(anna).balanceOf(anna.address);
expect(newBalance).to.approxEqualTolerance(
currentBalance.sub(ousdUnits("30000")),
currentBalance.sub(redeemAmount),
1
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ describe("ForkTest: OETH AMO Curve Metapool Strategy", function () {
const loadFixture = createFixtureLoader(convexOETHMetaVaultFixture, {
wethMintAmount: 20000,
depositToStrategy: false,
poolAddOethAmount: 7000,
poolAddOethAmount: 5000,
balancePool: true,
});
beforeEach(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ describe("ForkTest: MetaMorpho USDC Strategy", function () {
vaultSigner,
} = fixture;

const checkBalanceBefore = await OUSDMetaMorphoStrategy.checkBalance(
usdc.address
);

const usdcDepositAmount = await units("1000", usdc);

// Vault transfers USDC to strategy
Expand Down Expand Up @@ -141,7 +145,10 @@ describe("ForkTest: MetaMorpho USDC Strategy", function () {
);
expect(
await OUSDMetaMorphoStrategy.checkBalance(usdc.address)
).to.approxEqualTolerance(usdcDepositAmount, 0.01); // 0.01% or 1 basis point
).to.approxEqualTolerance(
checkBalanceBefore.add(usdcDepositAmount),
0.01
); // 0.01% or 1 basis point
});
it("Only vault can deposit some USDC to the strategy", async function () {
const {
Expand Down
2 changes: 2 additions & 0 deletions contracts/test/vault/vault.mainnet.fork-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ describe("ForkTest: Vault", function () {
"0x89Eb88fEdc50FC77ae8a18aAD1cA0ac27f777a90", // OUSD MetaStrategy
"0x79F2188EF9350A1dC11A062cca0abE90684b0197", // MorphoAaveStrategy
"0x6b69B755C629590eD59618A2712d8a2957CA98FC", // Maker DSR Strategy
"0x603CDEAEC82A60E3C4A10dA6ab546459E5f64Fa0", // Meta Morpho USDC
];

for (const s of strategies) {
Expand Down Expand Up @@ -384,6 +385,7 @@ describe("ForkTest: Vault", function () {
"0x5e3646A1Db86993f73E6b74A57D8640B69F7e259",
"0x9c459eeb3FA179a40329b81C1635525e9A0Ef094",
"0x79F2188EF9350A1dC11A062cca0abE90684b0197", // MorphoAave
"0x603CDEAEC82A60E3C4A10dA6ab546459E5f64Fa0", // Meta Morpho USDC
]).to.include(await vault.assetDefaultStrategies(usdc.address));
});

Expand Down
2 changes: 2 additions & 0 deletions contracts/utils/addresses.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ addresses.mainnet.beaconChainDepositContract =
// Native Staking Strategy
addresses.mainnet.NativeStakingSSVStrategyProxy =
"0x34eDb2ee25751eE67F68A45813B22811687C0238";
addresses.mainnet.NativeStakingSSVStrategy2Proxy =
"0x4685dB8bF2Df743c861d71E6cFb5347222992076";

// Defender relayer
addresses.mainnet.validatorRegistrator =
Expand Down

0 comments on commit 09ece7c

Please sign in to comment.