Skip to content

Commit

Permalink
Add deployment script for multichain strategist (#2356)
Browse files Browse the repository at this point in the history
* Add deployment file and update fixtures

* Rename deployment file

* Fund on fork

* clean up tests

* Fix failing tests

* Add proposal ID

* Remove comments
  • Loading branch information
shahthepro authored Jan 20, 2025
1 parent 5ff14c4 commit ebdc81c
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 59 deletions.
77 changes: 77 additions & 0 deletions contracts/deploy/mainnet/118_multichain_strategist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
const { deploymentWithGovernanceProposal } = require("../../utils/deploy");

module.exports = deploymentWithGovernanceProposal(
{
deployName: "118_multichain_strategist",
forceDeploy: false,
//forceSkip: true,
reduceQueueTime: true,
deployerIsProposer: false,
proposalId:
"29029286887383246507190904901480289164471194993284788972189545670391461770154",
},
async () => {
const { multichainStrategistAddr } = await getNamedAccounts();

const cOETHVaultProxy = await ethers.getContract("OETHVaultProxy");
const cOETHVault = await ethers.getContractAt(
"IVault",
cOETHVaultProxy.address
);

const cOUSDVaultProxy = await ethers.getContract("VaultProxy");
const cOUSDVault = await ethers.getContractAt(
"IVault",
cOUSDVaultProxy.address
);

const cOETHBuybackProxy = await ethers.getContract("OETHBuybackProxy");
const cOETHBuyback = await ethers.getContractAt(
"OETHBuyback",
cOETHBuybackProxy.address
);

const cOUSDBuybackProxy = await ethers.getContract("BuybackProxy");
const cOUSDBuyback = await ethers.getContractAt(
"OUSDBuyback",
cOUSDBuybackProxy.address
);

const cOETHHarvesterSimple = await ethers.getContract(
"OETHHarvesterSimple"
);

// Governance Actions
// ----------------
return {
name: "Switch to multichain guardian",
actions: [
{
contract: cOETHVault,
signature: "setStrategistAddr(address)",
args: [multichainStrategistAddr],
},
{
contract: cOUSDVault,
signature: "setStrategistAddr(address)",
args: [multichainStrategistAddr],
},
{
contract: cOETHBuyback,
signature: "setStrategistAddr(address)",
args: [multichainStrategistAddr],
},
{
contract: cOUSDBuyback,
signature: "setStrategistAddr(address)",
args: [multichainStrategistAddr],
},
{
contract: cOETHHarvesterSimple,
signature: "setStrategistAddr(address)",
args: [multichainStrategistAddr],
},
],
};
}
);
10 changes: 8 additions & 2 deletions contracts/deploy/mainnet/999_fork_test_setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ const main = async (hre) => {
await tokenContract.connect(signer).approve(toAddress, allowance);
}

const { deployerAddr, timelockAddr, governorAddr, strategistAddr } =
await getNamedAccounts();
const {
deployerAddr,
timelockAddr,
governorAddr,
strategistAddr,
multichainStrategistAddr,
} = await getNamedAccounts();

hardhatSetBalance(deployerAddr, "1000000");

Expand Down Expand Up @@ -60,6 +65,7 @@ const main = async (hre) => {
await impersonateAndFund(deployerAddr);
await impersonateAndFund(governorAddr);
await impersonateAndFund(strategistAddr);
await impersonateAndFund(multichainStrategistAddr);
await impersonateAndFund(addresses.mainnet.OldTimelock);
log("Unlocked and funded named accounts with ETH");

Expand Down
22 changes: 14 additions & 8 deletions contracts/test/_fixture.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const simpleOETHFixture = deployments.createFixture(async () => {
});
log(`Block after deployments: ${await hre.ethers.provider.getBlockNumber()}`);

const { governorAddr, strategistAddr } = await getNamedAccounts();
const { governorAddr, multichainStrategistAddr } = await getNamedAccounts();
const sGovernor = await ethers.provider.getSigner(governorAddr);

const oethProxy = await ethers.getContract("OETHProxy");
Expand Down Expand Up @@ -144,8 +144,8 @@ const simpleOETHFixture = deployments.createFixture(async () => {
const [matt, josh, anna, domen, daniel, franck] = signers.slice(4);

if (isFork) {
governor = await ethers.provider.getSigner(governorAddr);
strategist = await ethers.provider.getSigner(strategistAddr);
governor = await impersonateAndFund(governorAddr);
strategist = await impersonateAndFund(multichainStrategistAddr);

for (const user of [matt, josh, anna, domen, daniel, franck]) {
// Everyone gets free weth
Expand Down Expand Up @@ -490,7 +490,7 @@ const loadTokenTransferFixture = deployments.createFixture(async () => {

log(`Block after deployments: ${await hre.ethers.provider.getBlockNumber()}`);

const { governorAddr, strategistAddr, timelockAddr } =
const { governorAddr, multichainStrategistAddr, timelockAddr } =
await getNamedAccounts();

const vaultAndTokenConracts = await getVaultAndTokenConracts();
Expand All @@ -510,7 +510,7 @@ const loadTokenTransferFixture = deployments.createFixture(async () => {
...vaultAndTokenConracts,
...accountTypes,
governorAddr,
strategistAddr,
strategistAddr: multichainStrategistAddr,
timelockAddr,
governor,
strategist,
Expand All @@ -534,7 +534,7 @@ const defaultFixture = deployments.createFixture(async () => {

log(`Block after deployments: ${await hre.ethers.provider.getBlockNumber()}`);

const { governorAddr, strategistAddr, timelockAddr } =
const { governorAddr, multichainStrategistAddr, timelockAddr } =
await getNamedAccounts();

const vaultAndTokenConracts = await getVaultAndTokenConracts();
Expand Down Expand Up @@ -1003,10 +1003,16 @@ const defaultFixture = deployments.createFixture(async () => {
const [matt, josh, anna, domen, daniel, franck] = signers.slice(4);

if (isFork) {
governor = await ethers.provider.getSigner(governorAddr);
strategist = await ethers.provider.getSigner(strategistAddr);
governor = await impersonateAndFund(governorAddr);
strategist = await impersonateAndFund(multichainStrategistAddr);
timelock = await impersonateAndFund(timelockAddr);
oldTimelock = await impersonateAndFund(addresses.mainnet.OldTimelock);

// Just a hack to get around using `.getAddress()` on the signer
governor.address = governorAddr;
strategist.address = multichainStrategistAddr;
timelock.address = timelockAddr;
oldTimelock.address = addresses.mainnet.OldTimelock;
} else {
timelock = governor;
}
Expand Down
79 changes: 30 additions & 49 deletions contracts/test/harvest/simple-harvester.mainnet.fork-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const { setERC20TokenBalance } = require("../_fund");

const { loadDefaultFixture } = require("../_fixture");

describe("ForkTest: CurvePoolBooster", function () {
describe("ForkTest: SimpleHarvester", function () {
this.timeout(0);

// Retry up to 3 times on CI
Expand All @@ -19,23 +19,19 @@ describe("ForkTest: CurvePoolBooster", function () {

it("Should have correct parameters", async () => {
const { simpleOETHHarvester } = fixture;
const { strategistAddr } = await getNamedAccounts();
const { multichainStrategistAddr } = await getNamedAccounts();

expect(await simpleOETHHarvester.governor()).to.be.equal(
addresses.mainnet.Timelock
);

expect(await simpleOETHHarvester.strategistAddr()).to.be.equal(
strategistAddr
multichainStrategistAddr
);
});

it("Should support Strategy as governor", async () => {
const { simpleOETHHarvester } = fixture;
const timelock = await ethers.provider.getSigner(
addresses.mainnet.Timelock
);

const { simpleOETHHarvester, timelock } = fixture;
expect(
await simpleOETHHarvester.supportedStrategies(
addresses.mainnet.ConvexOETHAMOStrategy
Expand All @@ -52,23 +48,20 @@ describe("ForkTest: CurvePoolBooster", function () {
});

it("Should support Strategy as strategist", async () => {
const { simpleOETHHarvester } = fixture;
const strategist = await ethers.provider.getSigner(
await simpleOETHHarvester.strategistAddr()
);
const { simpleOETHHarvester, strategist } = fixture;

expect(
await simpleOETHHarvester.supportedStrategies(
addresses.mainnet.ConvexOETHAMOStrategy
)
await simpleOETHHarvester
.connect(strategist)
.supportedStrategies(addresses.mainnet.ConvexOETHAMOStrategy)
).to.be.equal(false);
await simpleOETHHarvester
.connect(strategist)
.setSupportedStrategy(addresses.mainnet.ConvexOETHAMOStrategy, true);
expect(
await simpleOETHHarvester.supportedStrategies(
addresses.mainnet.ConvexOETHAMOStrategy
)
await simpleOETHHarvester
.connect(strategist)
.supportedStrategies(addresses.mainnet.ConvexOETHAMOStrategy)
).to.be.equal(true);
});

Expand All @@ -95,10 +88,7 @@ describe("ForkTest: CurvePoolBooster", function () {
});

it("Should Set strategist", async () => {
const { simpleOETHHarvester, josh } = fixture;
const timelock = await ethers.provider.getSigner(
addresses.mainnet.Timelock
);
const { simpleOETHHarvester, timelock, josh } = fixture;

expect(await simpleOETHHarvester.strategistAddr()).not.to.equal(
josh.address
Expand All @@ -108,46 +98,45 @@ describe("ForkTest: CurvePoolBooster", function () {
});

it("Should Harvest and transfer rewards as strategist", async () => {
const { simpleOETHHarvester, convexEthMetaStrategy, crv } = fixture;
const strategistAddress = await simpleOETHHarvester.strategistAddr();
const strategist = await ethers.provider.getSigner(strategistAddress);
const { simpleOETHHarvester, convexEthMetaStrategy, crv, strategist } =
fixture;

const balanceBeforeCRV = await crv.balanceOf(strategistAddress);
const balanceBeforeCRV = await crv.balanceOf(strategist.address);
await simpleOETHHarvester
.connect(strategist)
.setSupportedStrategy(convexEthMetaStrategy.address, true);
// prettier-ignore
await simpleOETHHarvester
.connect(strategist)["harvestAndTransfer(address)"](convexEthMetaStrategy.address);

const balanceAfterCRV = await crv.balanceOf(strategistAddress);
const balanceAfterCRV = await crv.balanceOf(strategist.address);
expect(balanceAfterCRV).to.be.gt(balanceBeforeCRV);
});

it("Should Harvest and transfer rewards as governor", async () => {
const { simpleOETHHarvester, convexEthMetaStrategy, crv } = fixture;
const timelock = await ethers.provider.getSigner(
addresses.mainnet.Timelock
);
const strategist = await simpleOETHHarvester.strategistAddr();
const {
simpleOETHHarvester,
convexEthMetaStrategy,
strategist,
timelock,
crv,
} = fixture;

const balanceBeforeCRV = await crv.balanceOf(strategist.address);

const balanceBeforeCRV = await crv.balanceOf(strategist);
await simpleOETHHarvester
.connect(timelock)
.setSupportedStrategy(convexEthMetaStrategy.address, true);
// prettier-ignore
await simpleOETHHarvester
.connect(timelock)["harvestAndTransfer(address)"](convexEthMetaStrategy.address);

const balanceAfterCRV = await crv.balanceOf(strategist);
const balanceAfterCRV = await crv.balanceOf(strategist.address);
expect(balanceAfterCRV).to.be.gt(balanceBeforeCRV);
});

it("Should revert if strategy is not authorized", async () => {
const { simpleOETHHarvester, convexEthMetaStrategy } = fixture;
const timelock = await ethers.provider.getSigner(
addresses.mainnet.Timelock
);
const { simpleOETHHarvester, convexEthMetaStrategy, timelock } = fixture;

await expect(
// prettier-ignore
Expand All @@ -157,10 +146,7 @@ describe("ForkTest: CurvePoolBooster", function () {
});

it("Should revert if strategy is address 0", async () => {
const { simpleOETHHarvester } = fixture;
const timelock = await ethers.provider.getSigner(
addresses.mainnet.Timelock
);
const { simpleOETHHarvester, timelock } = fixture;

await expect(
// prettier-ignore
Expand All @@ -170,10 +156,7 @@ describe("ForkTest: CurvePoolBooster", function () {
});

it("Should test to rescue tokens as governor", async () => {
const { simpleOETHHarvester, crv } = fixture;
const timelock = await ethers.provider.getSigner(
addresses.mainnet.Timelock
);
const { simpleOETHHarvester, timelock, crv } = fixture;

await setERC20TokenBalance(simpleOETHHarvester.address, crv, "1000");
const balanceBeforeCRV = await crv.balanceOf(simpleOETHHarvester.address);
Expand All @@ -185,9 +168,7 @@ describe("ForkTest: CurvePoolBooster", function () {
});

it("Should test to rescue tokens as strategist", async () => {
const { simpleOETHHarvester, crv } = fixture;
const strategistAddress = await simpleOETHHarvester.strategistAddr();
const strategist = await ethers.provider.getSigner(strategistAddress);
const { simpleOETHHarvester, strategist, crv } = fixture;

await setERC20TokenBalance(simpleOETHHarvester.address, crv, "1000");
const balanceBeforeCRV = await crv.balanceOf(simpleOETHHarvester.address);
Expand Down

0 comments on commit ebdc81c

Please sign in to comment.