diff --git a/contracts/deploy/sonic/001_origin_sonic.js b/contracts/deploy/sonic/001_origin_sonic.js index 61fa55e7c8..18e49826a0 100644 --- a/contracts/deploy/sonic/001_origin_sonic.js +++ b/contracts/deploy/sonic/001_origin_sonic.js @@ -159,23 +159,30 @@ module.exports = deployOnSonic( cSonicStakingStrategyProxy .connect(sDeployer)["initialize(address,address,bytes)"]( dSonicStakingStrategy.address, - deployerAddr, + governorAddr, initSonicStakingStrategy ) ); console.log("Initialized SonicStakingStrategy proxy and implementation"); + await withConfirmation( + cOSonicVault + .connect(sGovernor) + .approveStrategy(cSonicStakingStrategy.address) + ); + console.log("Approved Sonic Staking Strategy on Vault"); + // verify validators here: https://explorer.soniclabs.com/staking for (const validatorId of [15, 16, 17, 18]) { await cSonicStakingStrategy - .connect(sDeployer) + .connect(sGovernor) .supportValidator(validatorId); } console.log("Added supported validators"); // Set Defender Relayer for Sonic validator controls await cSonicStakingStrategy - .connect(sDeployer) + .connect(sGovernor) .setRegistrator(addresses.sonic.validatorRegistrator); console.log("Set registrator"); @@ -211,6 +218,11 @@ module.exports = deployOnSonic( await withConfirmation( cOSonicVault.connect(sGovernor).setMaxSupplyDiff(parseEther("1")) // 1 OS ); + await withConfirmation( + cOSonicVault + .connect(sGovernor) + .setStrategistAddr(addresses.sonic.guardian) + ); await withConfirmation( cOSonicVault .connect(sGovernor) @@ -219,6 +231,7 @@ module.exports = deployOnSonic( await withConfirmation( cOSonicVault.connect(sGovernor).setTrusteeFeeBps(2000) // 20% ); + console.log("Configured Vault"); // Deploy the Zapper await deployWithConfirmation("OSonicZapper", [ @@ -235,7 +248,5 @@ module.exports = deployOnSonic( ]); const vaultValueChecker = await ethers.getContract("VaultValueChecker"); console.log("Deployed Vault Value Checker", vaultValueChecker.address); - - // TODO transfer governor to ? } ); diff --git a/contracts/hardhat.config.js b/contracts/hardhat.config.js index 2a3bb95870..37ebc9413a 100644 --- a/contracts/hardhat.config.js +++ b/contracts/hardhat.config.js @@ -56,8 +56,8 @@ const BASE_GOVERNOR = "0x92A19381444A001d62cE67BaFF066fA1111d7202"; const BASE_STRATEGIST = "0x28bce2eE5775B652D92bB7c2891A89F036619703"; const SONIC_DEPLOYER = MAINNET_DEPLOYER; // TODO: update Sonic Governor and strategist -const SONIC_GOVERNOR = MAINNET_DEPLOYER; -const SONIC_STRATEGIST = MAINNET_DEPLOYER; +const SONIC_GOVERNOR = "0x4FF1b9D9ba8558F5EAfCec096318eA0d8b541971"; +const SONIC_STRATEGIST = "0x28bce2eE5775B652D92bB7c2891A89F036619703"; const mnemonic = "replace hover unaware super where filter stone fine garlic address matrix basic"; diff --git a/contracts/test/_fixture-sonic.js b/contracts/test/_fixture-sonic.js index c9e20426ed..d0276f8925 100644 --- a/contracts/test/_fixture-sonic.js +++ b/contracts/test/_fixture-sonic.js @@ -100,35 +100,23 @@ const defaultSonicFixture = deployments.createFixture(async () => { const signers = await hre.ethers.getSigners(); const [minter, burner, rafael, nick, clement] = signers.slice(4); // Skip first 4 addresses to avoid conflict - const { governorAddr, strategistAddr, timelockAddr } = - await getNamedAccounts(); - // TODO: change the deployerAddr to the appropriate governor address - const governor = await ethers.getSigner(isFork ? deployerAddr : governorAddr); - await hhHelpers.setBalance(governorAddr, oethUnits("1")); // Fund governor with some ETH - - const guardian = await ethers.getSigner(governorAddr); - const timelock = await ethers.getContractAt( - "ITimelockController", - timelockAddr - ); - const oSonicVaultSigner = await impersonateAndFund(oSonicVault.address); + const { governorAddr, strategistAddr } = await getNamedAccounts(); + // Impersonate governor + const governor = await impersonateAndFund(governorAddr); + governor.address = governorAddr; // Impersonate strategist const strategist = await impersonateAndFund(strategistAddr); strategist.address = strategistAddr; + const oSonicVaultSigner = await impersonateAndFund(oSonicVault.address); + let validatorRegistrator; if (isFork) { validatorRegistrator = await impersonateAndFund( addresses.sonic.validatorRegistrator ); validatorRegistrator.address = addresses.sonic.validatorRegistrator; - - await impersonateAndFund(governor.address); - await impersonateAndFund(timelock.address); - - // configure Vault to not automatically deposit to strategy - await oSonicVault.connect(governor).setVaultBuffer(oethUnits("1")); } for (const user of [rafael, nick, clement]) { @@ -156,8 +144,6 @@ const defaultSonicFixture = deployments.createFixture(async () => { // Signers governor, - guardian, - timelock, strategist, minter, burner, diff --git a/contracts/test/vault/vault.sonic.fork-test.js b/contracts/test/vault/vault.sonic.fork-test.js new file mode 100644 index 0000000000..6d254b1c66 --- /dev/null +++ b/contracts/test/vault/vault.sonic.fork-test.js @@ -0,0 +1,125 @@ +const { expect } = require("chai"); +const { parseUnits } = require("ethers/lib/utils"); + +const addresses = require("../../utils/addresses"); +const { defaultSonicFixture } = require("./../_fixture-sonic"); +const { isCI } = require("./../helpers"); +const { impersonateAndFund } = require("../../utils/signers"); + +describe("ForkTest: Sonic Vault", function () { + this.timeout(0); + + // Retry up to 3 times on CI + this.retries(isCI ? 3 : 0); + + let fixture; + beforeEach(async () => { + fixture = await defaultSonicFixture(); + }); + + describe("View functions", () => { + // These tests use a transaction to call a view function so the gas usage can be reported. + it("Should get total value", async () => { + const { nick, oSonicVault } = fixture; + + const tx = await oSonicVault + .connect(nick) + .populateTransaction.totalValue(); + await nick.sendTransaction(tx); + }); + it("Should check asset balances", async () => { + const { wS, nick, oSonicVault } = fixture; + + const tx = await oSonicVault + .connect(nick) + .populateTransaction.checkBalance(wS.address); + await nick.sendTransaction(tx); + }); + }); + + describe("Admin", () => { + it("Should have the correct governor address set", async () => { + const { oSonicVault } = fixture; + expect(await oSonicVault.governor()).to.equal(addresses.sonic.admin); + }); + + it("Should have the correct strategist address set", async () => { + const { strategist, oSonicVault } = fixture; + expect(await oSonicVault.strategistAddr()).to.equal( + await strategist.getAddress() + ); + }); + + it("Should have supported assets", async () => { + const { oSonicVault } = fixture; + const assets = await oSonicVault.getAllAssets(); + expect(assets).to.have.length(1); + expect(assets).to.include(addresses.sonic.wS); + + expect(await oSonicVault.isSupportedAsset(addresses.sonic.wS)).to.be.true; + }); + }); + + describe("Rebase", () => { + it(`Shouldn't be paused`, async () => { + const { oSonicVault } = fixture; + expect(await oSonicVault.rebasePaused()).to.be.false; + }); + + it(`Should rebase`, async () => { + const { oSonicVault } = fixture; + await oSonicVault.rebase(); + }); + }); + + describe("Capital", () => { + it(`Shouldn't be paused`, async () => { + const { oSonicVault } = fixture; + expect(await oSonicVault.capitalPaused()).to.be.false; + }); + + it("Should allow to mint w/ Wrapped S (wS)", async () => { + const { oSonic, oSonicVault, nick, wS } = fixture; + const balancePreMint = await oSonic + .connect(nick) + .balanceOf(nick.getAddress()); + await oSonicVault.connect(nick).mint(wS.address, parseUnits("1000"), 0); + + const balancePostMint = await oSonic + .connect(nick) + .balanceOf(nick.getAddress()); + + const balanceDiff = balancePostMint.sub(balancePreMint); + expect(balanceDiff).to.approxEqualTolerance(parseUnits("1000"), 1); + }); + + it("should deposit to and withdraw from staking strategy", async () => { + const { oSonicVault, nick, wS, sonicStakingStrategy } = fixture; + await oSonicVault.connect(nick).mint(wS.address, parseUnits("1000"), 0); + const strategistSigner = await impersonateAndFund( + await oSonicVault.strategistAddr() + ); + + await oSonicVault + .connect(strategistSigner) + .depositToStrategy( + sonicStakingStrategy.address, + [wS.address], + [parseUnits("1000")] + ); + + await oSonicVault + .connect(strategistSigner) + .withdrawFromStrategy( + sonicStakingStrategy.address, + [wS.address], + [parseUnits("1000")] + ); + }); + + it("Should have vault buffer disabled", async () => { + const { oSonicVault } = fixture; + expect(await oSonicVault.vaultBuffer()).to.equal("0"); + }); + }); +}); diff --git a/contracts/utils/deploy-l2.js b/contracts/utils/deploy-l2.js index 4a142aaf3e..a1cfdf4568 100644 --- a/contracts/utils/deploy-l2.js +++ b/contracts/utils/deploy-l2.js @@ -219,8 +219,9 @@ function deployOnSonic(opts, fn) { }; if (isFork) { - const { deployerAddr } = await getNamedAccounts(); + const { deployerAddr, governorAddr } = await getNamedAccounts(); await impersonateAndFund(deployerAddr); + await impersonateAndFund(governorAddr); } await fn(tools);