From 938727242e1a8775182b6dacf8e65d727a5d5123 Mon Sep 17 00:00:00 2001 From: Carl Farterson Date: Wed, 1 Dec 2021 16:43:04 -0800 Subject: [PATCH 01/15] feat(hub): requirement if no update args passed --- contracts/Hub.sol | 10 +++++++++- test/contracts/Hub.ts | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/contracts/Hub.sol b/contracts/Hub.sol index f0a4f538..9fe9a5c9 100644 --- a/contracts/Hub.sol +++ b/contracts/Hub.sol @@ -102,6 +102,14 @@ contract Hub is IHub, Ownable, Initializable { } require(!hub_.updating, "already updating"); require(block.timestamp >= hub_.endCooldown, "Still cooling down"); + // Make sure at least one of the values is different + require( + (_targetRefundRatio != 0 || + _targetRefundRatio != hub_.refundRatio) || + (_targetCurve != address(0) || _targetCurve != hub_.curve) || + (_encodedCurveDetails.length > 0), + "Nothing to update" + ); if (_targetRefundRatio != 0) { require( _targetRefundRatio < MAX_REFUND_RATIO, @@ -115,8 +123,8 @@ contract Hub is IHub, Ownable, Initializable { bool reconfigure; if (_encodedCurveDetails.length > 0) { if (_targetCurve == address(0)) { - reconfigure = true; ICurve(hub_.curve).initReconfigure(_id, _encodedCurveDetails); + reconfigure = true; } else { require( curveRegistry.isApproved(_targetCurve), diff --git a/test/contracts/Hub.ts b/test/contracts/Hub.ts index ff9a5e3b..64e2cdbb 100644 --- a/test/contracts/Hub.ts +++ b/test/contracts/Hub.ts @@ -37,7 +37,7 @@ describe("Hub.sol", () => { }); it("Cannot be called during warmup, duration, and cooldown", async () => { - // TODO: fast fwd to warmup, duration, cooldown and try expect + // TODO: fast fwd to warmup, duration, cooldown and use expect() for each // calling initUpdate() to revert }); From 49645cbc7053f821acec6e3a1c887ab1ea1a3c16 Mon Sep 17 00:00:00 2001 From: Carl Farterson Date: Wed, 1 Dec 2021 16:44:05 -0800 Subject: [PATCH 02/15] test(hub): cancelUpdate(), transferOwnership(), additional initUpdate() test shells --- test/contracts/Hub.ts | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/test/contracts/Hub.ts b/test/contracts/Hub.ts index 64e2cdbb..492bad9a 100644 --- a/test/contracts/Hub.ts +++ b/test/contracts/Hub.ts @@ -31,8 +31,15 @@ describe("Hub.sol", () => { }); describe("initUpdate()", () => { - it("Cannot be called if all values are the same", async () => {}); - it("Can be called a first time", async () => { + it("Fails when nothing to update", async () => { + // TODO: Hub to check + }); + + it("fails on ICurve.initReconfigure() from invalid encodedCurveDetails", async () => {}); + + it("fails on ICurve.register() from invalid encodedCurveDetails", async () => {}); + + it("", async () => { // TODO: call initUpdate() }); @@ -48,6 +55,18 @@ describe("Hub.sol", () => { }); }); + describe("cancelUpdate()", () => { + it("Cannot be called by non-owner", async () => { + // TODO + }); + it("Can only be called when updating and during the warmup period", async () => { + // TODO + }); + it("Correctly cancels a hub update and resets hub struct update values", async () => { + // TODO + }); + }); + describe("finishUpdate()", () => { it("Should revert if all arguments are the same", async () => { // TODO @@ -82,4 +101,16 @@ describe("Hub.sol", () => { // TODO }); }); + + describe("transferHubOwnership()", () => { + it("Cannot be called by non-owner", async () => { + // TODO + }); + it("Cannot be set to the current owner", async () => { + // TODO + }); + it("Successfully transfers hub ownership", async () => { + // TODO + }); + }); }); From 2befe2a45fce4f8cef6ed5ba3eb31780a28f80cd Mon Sep 17 00:00:00 2001 From: Carl Farterson Date: Thu, 2 Dec 2021 10:42:18 -0800 Subject: [PATCH 03/15] fix(hub): update requirements/non-zero refundRatio --- contracts/Hub.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/Hub.sol b/contracts/Hub.sol index 9fe9a5c9..96fd6ac2 100644 --- a/contracts/Hub.sol +++ b/contracts/Hub.sol @@ -54,6 +54,7 @@ contract Hub is IHub, Ownable, Initializable { require(curveRegistry.isApproved(address(_curve)), "_curve !approved"); require(vaultRegistry.isApproved(address(_vault)), "_vault !approved"); require(_refundRatio < MAX_REFUND_RATIO, "_refundRatio > MAX"); + require(_refundRatio > 0, "_refundRatio == 0"); // Ensure asset is valid based on encoded args and vault validation logic require(_vault.isValid(_asset, _encodedVaultArgs), "asset !valid"); @@ -104,12 +105,12 @@ contract Hub is IHub, Ownable, Initializable { require(block.timestamp >= hub_.endCooldown, "Still cooling down"); // Make sure at least one of the values is different require( - (_targetRefundRatio != 0 || - _targetRefundRatio != hub_.refundRatio) || - (_targetCurve != address(0) || _targetCurve != hub_.curve) || + (_targetRefundRatio != 0) || + (_targetCurve != hub_.curve) || (_encodedCurveDetails.length > 0), "Nothing to update" ); + if (_targetRefundRatio != 0) { require( _targetRefundRatio < MAX_REFUND_RATIO, From 6d9c4603bfe6374538adc2a3b1c5e16681d462ed Mon Sep 17 00:00:00 2001 From: Parv Date: Tue, 7 Dec 2021 20:01:52 +0530 Subject: [PATCH 04/15] feat(hub): add incremental hub testcases --- test/contracts/Hub.ts | 430 ++++++++++++++++++++++++++++++++++++++--- test/utils/hubSetup.ts | 85 +++++++- 2 files changed, 477 insertions(+), 38 deletions(-) diff --git a/test/contracts/Hub.ts b/test/contracts/Hub.ts index 492bad9a..caff784c 100644 --- a/test/contracts/Hub.ts +++ b/test/contracts/Hub.ts @@ -1,8 +1,19 @@ -import { ethers } from "hardhat"; +import { ethers, getNamedAccounts } from "hardhat"; import { Hub } from "../../artifacts/types/Hub"; import { Foundry } from "../../artifacts/types/Foundry"; import { CurveRegistry } from "../../artifacts/types/CurveRegistry"; import { VaultRegistry } from "../../artifacts/types/VaultRegistry"; +import { Signer, BigNumber } from "ethers"; +import { ERC20 } from "../../artifacts/types/ERC20"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { BancorZeroCurve } from "../../artifacts/types/BancorZeroCurve"; +import { MeTokenRegistry } from "../../artifacts/types/MeTokenRegistry"; +import { MeToken } from "../../artifacts/types/MeToken"; +import { SingleAssetVault } from "../../artifacts/types/SingleAssetVault"; +import { MigrationRegistry } from "../../artifacts/types/MigrationRegistry"; +import { deploy } from "../utils/helpers"; +import { hubSetup, hubSetupWithoutRegister } from "../utils/hubSetup"; +import { expect } from "chai"; /* const paginationFactory = await ethers.getContractFactory("Pagination", {}); @@ -16,100 +27,461 @@ const policyFactory = await ethers.getContractFactory("PolicyLib", { */ describe("Hub.sol", () => { - before(async () => {}); + let DAI: string; + let DAIWhale: string; + let WETH: string; + let WETHWhale: string; + let daiHolder: Signer; + let dai: ERC20; + let account0: SignerWithAddress; + let account1: SignerWithAddress; + let account2: SignerWithAddress; + let curve: BancorZeroCurve; + let meTokenRegistry: MeTokenRegistry; + let foundry: Foundry; + let token: ERC20; + let meToken: MeToken; + let tokenHolder: Signer; + let hub: Hub; + let singleAssetVault: SingleAssetVault; + let migrationRegistry: MigrationRegistry; + let curveRegistry: CurveRegistry; + let vaultRegistry: VaultRegistry; + let encodedVaultDAIArgs: string; + let encodedVaultWETHArgs: string; + let encodedCurveDetails: string; + + const hubId = 1; + const name = "Carl meToken"; + const symbol = "CARL"; + const refundRatio1 = 250000; + const refundRatio2 = 240000; + const initRefundRatio = 50000; + const PRECISION = ethers.utils.parseEther("1"); + const amount = ethers.utils.parseEther("10"); + const amount1 = ethers.utils.parseEther("100"); + const amount2 = ethers.utils.parseEther("6.9"); + const duration = 60 * 60; + + // TODO: pass in curve arguments to function + // TODO: then loop over array of set of curve arguments + const MAX_WEIGHT = 1000000; + const reserveWeight = MAX_WEIGHT / 2; + const baseY = PRECISION.div(1000); + + before(async () => { + ({ DAI, DAIWhale, WETH, WETHWhale } = await getNamedAccounts()); + encodedVaultDAIArgs = ethers.utils.defaultAbiCoder.encode( + ["address"], + [DAI] + ); + encodedVaultWETHArgs = ethers.utils.defaultAbiCoder.encode( + ["address"], + [WETH] + ); + // TODO: pass in name of curve to deploy, encodedCurveDetails to general func + encodedCurveDetails = ethers.utils.defaultAbiCoder.encode( + ["uint256", "uint32"], + [baseY, reserveWeight] + ); + curve = await deploy("BancorZeroCurve"); + ({ + token, + tokenHolder, + hub, + foundry, + account0, + account1, + account2, + meTokenRegistry, + vaultRegistry, + curveRegistry, + migrationRegistry, + singleAssetVault, + } = await hubSetupWithoutRegister(curve)); + }); + + describe("Initial state", () => { + it("Check initial values", async () => { + expect(await hub.MAX_REFUND_RATIO()).to.be.equal(10 ** 6); + expect(await hub.foundry()).to.be.equal(foundry.address); + expect(await hub.vaultRegistry()).to.be.equal(vaultRegistry.address); + expect(await hub.curveRegistry()).to.be.equal(curveRegistry.address); + expect(await hub.owner()).to.be.equal(account0.address); + expect(await hub.count()).to.be.equal(0); + expect(await hub.getWarmup()).to.be.equal(0); + expect(await hub.getDuration()).to.be.equal(0); + expect(await hub.getCooldown()).to.be.equal(0); + const details = await hub.getDetails(0); + expect(details.active).to.be.equal(false); + expect(details.owner).to.be.equal(ethers.constants.AddressZero); + expect(details.vault).to.be.equal(ethers.constants.AddressZero); + expect(details.asset).to.be.equal(ethers.constants.AddressZero); + expect(details.curve).to.be.equal(ethers.constants.AddressZero); + expect(details.refundRatio).to.be.equal(0); + expect(details.updating).to.be.equal(false); + expect(details.startTime).to.be.equal(0); + expect(details.endTime).to.be.equal(0); + expect(details.endCooldown).to.be.equal(0); + expect(details.reconfigure).to.be.equal(false); + expect(details.targetCurve).to.be.equal(ethers.constants.AddressZero); + expect(details.targetRefundRatio).to.be.equal(0); + }); + }); describe("register()", () => { it("Should revert from invalid address arguments", async () => { - // TODO + // Un-approved curve + let tx = hub.register( + account0.address, + DAI, + singleAssetVault.address, + account0.address, // random unapproved address + refundRatio1, + encodedCurveDetails, + encodedVaultDAIArgs + ); + await expect(tx).to.be.revertedWith("_curve !approved"); + + // Un-approved vault + tx = hub.register( + account0.address, + DAI, + account0.address, // random unapproved address + curve.address, + refundRatio1, + encodedCurveDetails, + encodedVaultDAIArgs + ); + await expect(tx).to.be.revertedWith("_vault !approved"); }); it("Should revert from invalid encodedCurveDetails", async () => { - // TODO + // Invalid _encodedCurveDetails for particular curve + let tx = hub.register( + account0.address, + DAI, + singleAssetVault.address, + curve.address, + refundRatio1, + "0x", // invalid _encodedCurveDetails + encodedVaultDAIArgs + ); + await expect(tx).to.be.revertedWith("!_encodedDetails"); + + // TODO as this revert is caused by external contracts, do they need to be covered here? }); it("Should revert from invalid encodedVaultArgs", async () => { - // TODO + // Invalid _encodedVaultArgs + const tx = hub.register( + account0.address, + ethers.constants.AddressZero, + singleAssetVault.address, + curve.address, + refundRatio1, + encodedCurveDetails, + encodedVaultDAIArgs // invalid _encodedVaultArgs + ); + await expect(tx).to.be.revertedWith("asset !valid"); + }); + it("Should revert from invalid _refundRatio", async () => { + // _refundRatio > MAX_REFUND_RATIO + let tx = hub.register( + account0.address, + DAI, + singleAssetVault.address, + curve.address, + 10 ** 7, + encodedCurveDetails, + encodedVaultDAIArgs + ); + await expect(tx).to.be.revertedWith("_refundRatio > MAX"); + + // _refundRatio = 0 + tx = hub.register( + account0.address, + DAI, + singleAssetVault.address, + curve.address, + 0, + encodedCurveDetails, + encodedVaultDAIArgs + ); + await expect(tx).to.be.revertedWith("_refundRatio == 0"); + }); + it("Should be able to register", async () => { + const tx = await hub.register( + account0.address, + DAI, + singleAssetVault.address, + curve.address, + refundRatio1, + encodedCurveDetails, + encodedVaultDAIArgs + ); + await tx.wait(); + + expect(tx) + .to.emit(hub, "Register") + .withArgs( + account0.address, + DAI, + singleAssetVault.address, + curve.address, + refundRatio1, + encodedCurveDetails, + encodedVaultDAIArgs + ); + expect(await hub.count()).to.be.equal(1); + const details = await hub.getDetails(1); + expect(details.active).to.be.equal(true); + expect(details.owner).to.be.equal(account0.address); + expect(details.vault).to.be.equal(singleAssetVault.address); + expect(details.asset).to.be.equal(DAI); + expect(details.curve).to.be.equal(curve.address); + expect(details.refundRatio).to.be.equal(refundRatio1); + expect(details.updating).to.be.equal(false); + expect(details.startTime).to.be.equal(0); + expect(details.endTime).to.be.equal(0); + expect(details.endCooldown).to.be.equal(0); + expect(details.reconfigure).to.be.equal(false); + expect(details.targetCurve).to.be.equal(ethers.constants.AddressZero); + expect(details.targetRefundRatio).to.be.equal(0); + }); + }); + + describe("setWarmup()", () => { + it("Should revert to setWarmup if not owner", async () => { + const tx = hub.connect(account1).setWarmup(duration); + await expect(tx).to.be.revertedWith("Ownable: caller is not the owner"); + }); + it("Should revert to setWarmup if same as before", async () => { + const oldWarmup = await hub.getWarmup(); + const tx = hub.setWarmup(oldWarmup); + await expect(tx).to.be.revertedWith("warmup_ == _warmup"); + }); + it("Should be able to setWarmup", async () => { + const tx = await hub.setWarmup(duration); + await tx.wait(); + expect(await hub.getWarmup()).to.be.equal(duration); + }); + }); + + describe("setDuration()", () => { + it("Should revert to setDuration if not owner", async () => { + const tx = hub.connect(account1).setDuration(duration); + await expect(tx).to.be.revertedWith("Ownable: caller is not the owner"); + }); + it("Should revert to setDuration if same as before", async () => { + const oldWarmup = await hub.getDuration(); + const tx = hub.setDuration(oldWarmup); + await expect(tx).to.be.revertedWith("duration_ == _duration"); + }); + it("Should be able to setDuration", async () => { + const tx = await hub.setDuration(duration); + await tx.wait(); + expect(await hub.getDuration()).to.be.equal(duration); + }); + }); + + describe("setCooldown()", () => { + it("Should revert to setCooldown if not owner", async () => { + const tx = hub.connect(account1).setCooldown(duration); + await expect(tx).to.be.revertedWith("Ownable: caller is not the owner"); + }); + it("Should revert to setCooldown if same as before", async () => { + const oldWarmup = await hub.getCooldown(); + const tx = hub.setCooldown(oldWarmup); + await expect(tx).to.be.revertedWith("cooldown_ == _cooldown"); + }); + it("Should be able to setCooldown", async () => { + const tx = await hub.setCooldown(duration); + await tx.wait(); + expect(await hub.getCooldown()).to.be.equal(duration); }); }); describe("initUpdate()", () => { - it("Fails when nothing to update", async () => { - // TODO: Hub to check + it("Should revert when sender is not owner", async () => { + const tx = hub + .connect(account1) + .initUpdate(hubId, curve.address, refundRatio2, encodedCurveDetails); + await expect(tx).to.be.revertedWith("!owner"); + }); + + it("Should revert when nothing to update", async () => { + const tx = hub.initUpdate(hubId, curve.address, 0, "0x"); + await expect(tx).to.be.revertedWith("Nothing to update"); + // FIXME Hub.sol, -109 fix the conditions + }); + + it("Should revert from invalid _refundRatio", async () => { + const tx1 = hub.initUpdate( + hubId, + curve.address, + 10 ** 7, + encodedCurveDetails + ); + const tx2 = hub.initUpdate( + hubId, + curve.address, + refundRatio1, + encodedCurveDetails + ); + await expect(tx1).to.be.revertedWith("_targetRefundRatio >= MAX"); + await expect(tx2).to.be.revertedWith("_targetRefundRatio == refundRatio"); + }); + + it("Should revert on ICurve.initReconfigure() from invalid encodedCurveDetails", async () => { + const badEncodedCurveDetails = ethers.utils.defaultAbiCoder.encode( + ["uint32"], + [0] + ); + const tx = hub.initUpdate( + hubId, + ethers.constants.AddressZero, + 0, + badEncodedCurveDetails + ); + await expect(tx).to.be.revertedWith("!reserveWeight"); + // TODO as this revert is caused by external contracts, do they need to be covered here? + }); + + it("Should revert when curve is not approved", async () => { + const tx = hub.initUpdate( + hubId, + account0.address, // invalid curve address + refundRatio2, + encodedCurveDetails + ); + await expect(tx).to.be.revertedWith("_targetCurve !approved"); + }); + + it("Should revert on ICurve.register() from invalid encodedCurveDetails", async () => { + const badEncodedCurveDetails = ethers.utils.defaultAbiCoder.encode( + ["uint256", "uint32"], + [0, 0] + ); + const tx = hub.initUpdate( + hubId, + curve.address, + refundRatio2, + badEncodedCurveDetails + ); + await expect(tx).to.be.revertedWith("!baseY"); + // TODO as this revert is caused by external contracts, do they need to be covered here? }); - it("fails on ICurve.initReconfigure() from invalid encodedCurveDetails", async () => {}); + // FIXME hub.sol l-141 + it("Should be able to update with new refundRation", async () => { + const tx = await hub.initUpdate( + hubId, + curve.address, + refundRatio2, + encodedCurveDetails + ); + const receipt = await tx.wait(); + const block = await ethers.provider.getBlock(receipt.blockNumber); + const expectedStartTime = block.timestamp + duration; + const expectedEndTime = block.timestamp + duration + duration; + const expectedEndCooldownTime = + block.timestamp + duration + duration + duration; - it("fails on ICurve.register() from invalid encodedCurveDetails", async () => {}); + expect(tx) + .to.emit(hub, "InitUpdate") + .withArgs( + hubId, + curve.address, + refundRatio2, + encodedCurveDetails, + false, + expectedStartTime, + expectedEndTime, + expectedEndCooldownTime + ); - it("", async () => { - // TODO: call initUpdate() + const details = await hub.getDetails(1); + expect(details.active).to.be.equal(true); + expect(details.owner).to.be.equal(account0.address); + expect(details.vault).to.be.equal(singleAssetVault.address); + expect(details.asset).to.be.equal(DAI); + expect(details.curve).to.be.equal(curve.address); + expect(details.refundRatio).to.be.equal(refundRatio1); + expect(details.updating).to.be.equal(true); + expect(details.startTime).to.be.equal(expectedStartTime); + expect(details.endTime).to.be.equal(expectedEndTime); + expect(details.endCooldown).to.be.equal(expectedEndCooldownTime); + expect(details.reconfigure).to.be.equal(false); + expect(details.targetCurve).to.be.equal(curve.address); + expect(details.targetRefundRatio).to.be.equal(refundRatio2); }); - it("Cannot be called during warmup, duration, and cooldown", async () => { + it("Should revert to called during warmup, duration, and cooldown", async () => { // TODO: fast fwd to warmup, duration, cooldown and use expect() for each // calling initUpdate() to revert }); - it("Sets target values to values if finishUpdate() never after from first update", async () => {}); + xit("Sets target values to values if finishUpdate() never after from first update", async () => {}); - it("Can be called a second time after cooldown", async () => { + xit("Can be called a second time after cooldown", async () => { // TODO: fast fwd to after cooldown and call initUpdate() }); }); describe("cancelUpdate()", () => { - it("Cannot be called by non-owner", async () => { + xit("Cannot be called by non-owner", async () => { // TODO }); - it("Can only be called when updating and during the warmup period", async () => { + xit("Can only be called when updating and during the warmup period", async () => { // TODO }); - it("Correctly cancels a hub update and resets hub struct update values", async () => { + xit("Correctly cancels a hub update and resets hub struct update values", async () => { // TODO }); }); describe("finishUpdate()", () => { - it("Should revert if all arguments are the same", async () => { + xit("Should revert if all arguments are the same", async () => { // TODO }); - it("Doesn't trigger during warmup or duration", async () => { + xit("Doesn't trigger during warmup or duration", async () => { // TODO }); - it("Trigger once when mint() called during cooldown", async () => { + xit("Trigger once when mint() called during cooldown", async () => { // TODO }); - it("Trigger once when burn() called during cooldown", async () => { + xit("Trigger once when burn() called during cooldown", async () => { // TODO }); - it("Trigger once when mint() called if no mint() / burn() called during cooldown", async () => { + xit("Trigger once when mint() called if no mint() / burn() called during cooldown", async () => { // TODO }); - it("Trigger once when burn() called if no mint() / burn() called during cooldown", async () => { + xit("Trigger once when burn() called if no mint() / burn() called during cooldown", async () => { // TODO }); - it("Correctly set HubDetails when called during cooldown", async () => { + xit("Correctly set HubDetails when called during cooldown", async () => { // TODO }); - it("Correctly set HubDetails when called after cooldown", async () => { + xit("Correctly set HubDetails when called after cooldown", async () => { // TODO }); - it("Correctly set HubDetails when called during second initUpdate()", async () => { + xit("Correctly set HubDetails when called during second initUpdate()", async () => { // TODO }); }); describe("transferHubOwnership()", () => { - it("Cannot be called by non-owner", async () => { + xit("Cannot be called by non-owner", async () => { // TODO }); - it("Cannot be set to the current owner", async () => { + xit("Cannot be set to the current owner", async () => { // TODO }); - it("Successfully transfers hub ownership", async () => { + xit("Successfully transfers hub ownership", async () => { // TODO }); }); diff --git a/test/utils/hubSetup.ts b/test/utils/hubSetup.ts index 2c8cf3b5..1c43b39c 100644 --- a/test/utils/hubSetup.ts +++ b/test/utils/hubSetup.ts @@ -63,6 +63,82 @@ export async function hubSetup( account3: SignerWithAddress; tokenHolder: Signer; tokenWhale: string; +}> { + const { + tokenAddr, + weightedAverage, + meTokenRegistry, + meTokenFactory, + curveRegistry, + vaultRegistry, + migrationRegistry, + singleAssetVault, + foundry, + fee, + hub, + token, + account0, + account1, + account2, + account3, + tokenHolder, + tokenWhale, + } = await hubSetupWithoutRegister(curve, fees, erc20Address, erc20Whale); + + await hub.register( + account0.address, + tokenAddr, + singleAssetVault.address, + curve.address, + refundRatio, //refund ratio + encodedCurveDetails, + encodedVaultArgs + ); + return { + tokenAddr, + weightedAverage, + meTokenRegistry, + meTokenFactory, + curveRegistry, + vaultRegistry, + migrationRegistry, + singleAssetVault, + foundry, + fee, + hub, + token, + account0, + account1, + account2, + account3, + tokenHolder, + tokenWhale, + }; +} +export async function hubSetupWithoutRegister( + curve: ICurve, + fees?: number[], + erc20Address?: string, + erc20Whale?: string +): Promise<{ + tokenAddr: string; + weightedAverage: WeightedAverage; + meTokenRegistry: MeTokenRegistry; + meTokenFactory: MeTokenFactory; + curveRegistry: CurveRegistry; + vaultRegistry: VaultRegistry; + migrationRegistry: MigrationRegistry; + singleAssetVault: SingleAssetVault; + foundry: Foundry; + hub: Hub; + token: ERC20; + fee: Fees; + account0: SignerWithAddress; + account1: SignerWithAddress; + account2: SignerWithAddress; + account3: SignerWithAddress; + tokenHolder: Signer; + tokenWhale: string; }> { if (!erc20Address || !erc20Whale) { let DAI; @@ -134,15 +210,6 @@ export async function hubSetup( curveRegistry.address ); - await hub.register( - account0.address, - tokenAddr, - singleAssetVault.address, - curve.address, - refundRatio, //refund ratio - encodedCurveDetails, - encodedVaultArgs - ); return { tokenAddr, weightedAverage, From afc7cd307f74899297d797f22cb518ec4b257e54 Mon Sep 17 00:00:00 2001 From: Parv Date: Tue, 7 Dec 2021 21:36:38 +0530 Subject: [PATCH 05/15] feat(hub.sol): optimisation --- contracts/Hub.sol | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/contracts/Hub.sol b/contracts/Hub.sol index 96fd6ac2..136957f9 100644 --- a/contracts/Hub.sol +++ b/contracts/Hub.sol @@ -91,15 +91,7 @@ contract Hub is IHub, Ownable, Initializable { Details.Hub storage hub_ = _hubs[_id]; require(msg.sender == hub_.owner, "!owner"); if (hub_.updating && block.timestamp > hub_.endTime) { - Details.Hub memory hubUpdated = finishUpdate(_id); - hub_.refundRatio = hubUpdated.refundRatio; - hub_.targetRefundRatio = hubUpdated.targetRefundRatio; - hub_.curve = hubUpdated.curve; - hub_.targetCurve = hubUpdated.targetCurve; - hub_.reconfigure = hubUpdated.reconfigure; - hub_.updating = hubUpdated.updating; - hub_.startTime = hubUpdated.startTime; - hub_.endTime = hubUpdated.endTime; + finishUpdate(_id); } require(!hub_.updating, "already updating"); require(block.timestamp >= hub_.endCooldown, "Still cooling down"); @@ -120,6 +112,7 @@ contract Hub is IHub, Ownable, Initializable { _targetRefundRatio != hub_.refundRatio, "_targetRefundRatio == refundRatio" ); + hub_.targetRefundRatio = _targetRefundRatio; } bool reconfigure; if (_encodedCurveDetails.length > 0) { @@ -136,10 +129,6 @@ contract Hub is IHub, Ownable, Initializable { } } - if (_targetRefundRatio != 0) { - hub_.targetRefundRatio = _targetRefundRatio; - } - hub_.reconfigure = reconfigure; hub_.updating = true; hub_.startTime = block.timestamp + _warmup; From a6d3b5e31b91086303b985ff3e0d06945471a8be Mon Sep 17 00:00:00 2001 From: Parv Date: Tue, 7 Dec 2021 22:13:15 +0530 Subject: [PATCH 06/15] feat(hub.sol): fix bug - setting targetCurve to zero addr in cancelUpdate --- contracts/Hub.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/Hub.sol b/contracts/Hub.sol index 136957f9..8d21e8d4 100644 --- a/contracts/Hub.sol +++ b/contracts/Hub.sol @@ -156,6 +156,7 @@ contract Hub is IHub, Ownable, Initializable { hub_.targetRefundRatio = 0; hub_.reconfigure = false; + hub_.targetCurve = address(0); hub_.updating = false; hub_.startTime = 0; hub_.endTime = 0; From e94248596abfaf845b118b462d6152b3faf61752 Mon Sep 17 00:00:00 2001 From: Parv Date: Tue, 7 Dec 2021 22:21:41 +0530 Subject: [PATCH 07/15] feat(hub): add incremental hub testcases --- test/contracts/Hub.ts | 152 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 141 insertions(+), 11 deletions(-) diff --git a/test/contracts/Hub.ts b/test/contracts/Hub.ts index caff784c..f262f049 100644 --- a/test/contracts/Hub.ts +++ b/test/contracts/Hub.ts @@ -14,6 +14,7 @@ import { MigrationRegistry } from "../../artifacts/types/MigrationRegistry"; import { deploy } from "../utils/helpers"; import { hubSetup, hubSetupWithoutRegister } from "../utils/hubSetup"; import { expect } from "chai"; +import { mineBlock } from "../utils/hardhatNode"; /* const paginationFactory = await ethers.getContractFactory("Pagination", {}); @@ -371,8 +372,7 @@ describe("Hub.sol", () => { // TODO as this revert is caused by external contracts, do they need to be covered here? }); - // FIXME hub.sol l-141 - it("Should be able to update with new refundRation", async () => { + it("Should be able to initUpdate with new refundRatio", async () => { const tx = await hub.initUpdate( hubId, curve.address, @@ -418,25 +418,155 @@ describe("Hub.sol", () => { it("Should revert to called during warmup, duration, and cooldown", async () => { // TODO: fast fwd to warmup, duration, cooldown and use expect() for each // calling initUpdate() to revert + const txBeforeStartTime = hub.initUpdate( + hubId, + curve.address, + refundRatio2, + encodedCurveDetails + ); + const details = await hub.getDetails(1); + + await expect(txBeforeStartTime).to.be.revertedWith("already updating"); + let block = await ethers.provider.getBlock("latest"); + + // fast fwd to startTime | warmup + await mineBlock(details.startTime.toNumber() + 1); + const txAfterStartTime = hub.initUpdate( + hubId, + curve.address, + refundRatio2, + encodedCurveDetails + ); + await expect(txAfterStartTime).to.be.revertedWith("already updating"); + block = await ethers.provider.getBlock("latest"); + expect(details.startTime).to.be.lt(block.timestamp); + + // fast fwd to endTime - 1 + await mineBlock(details.endTime.toNumber() - 1); + const txBeforeEndTime = hub.initUpdate( + hubId, + curve.address, + refundRatio2, + encodedCurveDetails + ); + await expect(txBeforeEndTime).to.be.revertedWith("already updating"); + block = await ethers.provider.getBlock("latest"); + expect(details.endTime).to.be.gte(block.timestamp); + + // fast fwd to endTime | duration + await mineBlock(details.endTime.toNumber() + 1); + const txAfterEndTime = hub.initUpdate( + hubId, + curve.address, + refundRatio2, + encodedCurveDetails + ); + await expect(txAfterEndTime).to.be.revertedWith("Still cooling down"); + block = await ethers.provider.getBlock("latest"); + expect(details.endTime).to.be.lt(block.timestamp); + + // fast fwd to endCooldown - 2 + await mineBlock(details.endCooldown.toNumber() - 2); + const txBeforeEndCooldown = hub.initUpdate( + hubId, + curve.address, + refundRatio2, + encodedCurveDetails + ); + await expect(txBeforeEndCooldown).to.be.revertedWith( + "Still cooling down" + ); + block = await ethers.provider.getBlock("latest"); + expect(details.endTime).to.be.lt(block.timestamp); }); - xit("Sets target values to values if finishUpdate() never after from first update", async () => {}); + it("Should first finishUpdate (if not) before next initUpdate", async () => { + let details = await hub.getDetails(1); + const newEncodedCurveDetails = ethers.utils.defaultAbiCoder.encode( + ["uint32"], + [reserveWeight / 2] + ); + + // fast fwd to endCooldown - 2 + await mineBlock(details.endCooldown.toNumber()); + const txAfterEndCooldown = await hub.initUpdate( + hubId, + ethers.constants.AddressZero, + 0, + newEncodedCurveDetails + ); + + const receipt = await txAfterEndCooldown.wait(); + let block = await ethers.provider.getBlock("latest"); + expect(details.endCooldown).to.be.lte(block.timestamp); - xit("Can be called a second time after cooldown", async () => { - // TODO: fast fwd to after cooldown and call initUpdate() + block = await ethers.provider.getBlock(receipt.blockNumber); + const expectedStartTime = block.timestamp + duration; + const expectedEndTime = block.timestamp + duration + duration; + const expectedEndCooldownTime = + block.timestamp + duration + duration + duration; + + expect(txAfterEndCooldown) + .to.emit(hub, "InitUpdate") + .withArgs( + hubId, + ethers.constants.AddressZero, + 0, + newEncodedCurveDetails, + true, + expectedStartTime, + expectedEndTime, + expectedEndCooldownTime + ); + + details = await hub.getDetails(1); + expect(details.active).to.be.equal(true); + expect(details.owner).to.be.equal(account0.address); + expect(details.vault).to.be.equal(singleAssetVault.address); + expect(details.asset).to.be.equal(DAI); + expect(details.curve).to.be.equal(curve.address); + expect(details.refundRatio).to.be.equal(refundRatio2); + expect(details.updating).to.be.equal(true); + expect(details.startTime).to.be.equal(expectedStartTime); + expect(details.endTime).to.be.equal(expectedEndTime); + expect(details.endCooldown).to.be.equal(expectedEndCooldownTime); + expect(details.reconfigure).to.be.equal(true); + expect(details.targetCurve).to.be.equal(curve.address); + expect(details.targetRefundRatio).to.be.equal(0); }); }); describe("cancelUpdate()", () => { - xit("Cannot be called by non-owner", async () => { - // TODO + it("should revert when called by non-owner", async () => { + const tx = hub.connect(account1).cancelUpdate(hubId); + await expect(tx).to.be.revertedWith("!owner"); }); - xit("Can only be called when updating and during the warmup period", async () => { - // TODO + it("should correctly cancels hub update and resets hub struct update values", async () => { + const tx = await hub.cancelUpdate(hubId); + await tx.wait(); + + expect(tx).to.emit(hub, "CancelUpdate").withArgs(hubId); + + const details = await hub.getDetails(1); + expect(details.active).to.be.equal(true); + expect(details.owner).to.be.equal(account0.address); + expect(details.vault).to.be.equal(singleAssetVault.address); + expect(details.asset).to.be.equal(DAI); + expect(details.curve).to.be.equal(curve.address); + expect(details.refundRatio).to.be.equal(refundRatio2); + expect(details.updating).to.be.equal(false); + expect(details.startTime).to.be.equal(0); + expect(details.endTime).to.be.equal(0); + expect(details.endCooldown).to.be.equal(0); + expect(details.reconfigure).to.be.equal(false); + expect(details.targetCurve).to.be.equal(ethers.constants.AddressZero); + expect(details.targetRefundRatio).to.be.equal(0); }); - xit("Correctly cancels a hub update and resets hub struct update values", async () => { - // TODO + it("should revert when not updating", async () => { + const tx = hub.cancelUpdate(hubId); + await expect(tx).to.be.revertedWith("!updating"); }); + it("should revert after warmup period"); }); describe("finishUpdate()", () => { From 72878aabd0c4f2223ae3cecab2e6e031d76f3c9e Mon Sep 17 00:00:00 2001 From: Carl Farterson Date: Tue, 7 Dec 2021 13:12:59 -0800 Subject: [PATCH 08/15] test(hub): fix pending/broken tests --- test/contracts/Hub.ts | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/test/contracts/Hub.ts b/test/contracts/Hub.ts index f262f049..2fd80dd3 100644 --- a/test/contracts/Hub.ts +++ b/test/contracts/Hub.ts @@ -563,55 +563,54 @@ describe("Hub.sol", () => { expect(details.targetRefundRatio).to.be.equal(0); }); it("should revert when not updating", async () => { - const tx = hub.cancelUpdate(hubId); - await expect(tx).to.be.revertedWith("!updating"); + await expect(hub.cancelUpdate(hubId)).to.be.revertedWith("!updating"); }); - it("should revert after warmup period"); + it("should revert after warmup period", async () => {}); }); describe("finishUpdate()", () => { - xit("Should revert if all arguments are the same", async () => { + it("Should revert if all arguments are the same", async () => { // TODO }); - xit("Doesn't trigger during warmup or duration", async () => { + it("Doesn't trigger during warmup or duration", async () => { // TODO }); - xit("Trigger once when mint() called during cooldown", async () => { + it("Trigger once when mint() called during cooldown", async () => { // TODO }); - xit("Trigger once when burn() called during cooldown", async () => { + it("Trigger once when burn() called during cooldown", async () => { // TODO }); - xit("Trigger once when mint() called if no mint() / burn() called during cooldown", async () => { + it("Trigger once when mint() called if no mint() / burn() called during cooldown", async () => { // TODO }); - xit("Trigger once when burn() called if no mint() / burn() called during cooldown", async () => { + it("Trigger once when burn() called if no mint() / burn() called during cooldown", async () => { // TODO }); - xit("Correctly set HubDetails when called during cooldown", async () => { + it("Correctly set HubDetails when called during cooldown", async () => { // TODO }); - xit("Correctly set HubDetails when called after cooldown", async () => { + it("Correctly set HubDetails when called after cooldown", async () => { // TODO }); - xit("Correctly set HubDetails when called during second initUpdate()", async () => { + it("Correctly set HubDetails when called during second initUpdate()", async () => { // TODO }); }); describe("transferHubOwnership()", () => { - xit("Cannot be called by non-owner", async () => { + it("Cannot be called by non-owner", async () => { // TODO }); - xit("Cannot be set to the current owner", async () => { + it("Cannot be set to the current owner", async () => { // TODO }); - xit("Successfully transfers hub ownership", async () => { + it("Successfully transfers hub ownership", async () => { // TODO }); }); From 60290c6164c1ebac77d0fe0d8c5a8036176717bf Mon Sep 17 00:00:00 2001 From: Parv Date: Wed, 8 Dec 2021 11:58:14 +0530 Subject: [PATCH 09/15] fix(Hub.sol): fix bug in transferHubOwnership --- contracts/Hub.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Hub.sol b/contracts/Hub.sol index 8d21e8d4..7fce97a1 100644 --- a/contracts/Hub.sol +++ b/contracts/Hub.sol @@ -168,7 +168,7 @@ contract Hub is IHub, Ownable, Initializable { function transferHubOwnership(uint256 _id, address _newOwner) external { Details.Hub storage hub_ = _hubs[_id]; require(msg.sender == hub_.owner, "!owner"); - require(msg.sender != hub_.owner, "Same owner"); + require(_newOwner != hub_.owner, "Same owner"); hub_.owner = _newOwner; emit TransferHubOwnership(_id, _newOwner); From 9c304bef19e0353710aa72630df6b2e6d5477ee2 Mon Sep 17 00:00:00 2001 From: Parv Date: Wed, 8 Dec 2021 12:14:48 +0530 Subject: [PATCH 10/15] feat(hub): add incremental hub testcases --- test/contracts/Hub.ts | 185 ++++++++++++++++++++++++++++++------------ 1 file changed, 131 insertions(+), 54 deletions(-) diff --git a/test/contracts/Hub.ts b/test/contracts/Hub.ts index 2fd80dd3..5159c274 100644 --- a/test/contracts/Hub.ts +++ b/test/contracts/Hub.ts @@ -3,16 +3,11 @@ import { Hub } from "../../artifacts/types/Hub"; import { Foundry } from "../../artifacts/types/Foundry"; import { CurveRegistry } from "../../artifacts/types/CurveRegistry"; import { VaultRegistry } from "../../artifacts/types/VaultRegistry"; -import { Signer, BigNumber } from "ethers"; -import { ERC20 } from "../../artifacts/types/ERC20"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { BancorZeroCurve } from "../../artifacts/types/BancorZeroCurve"; -import { MeTokenRegistry } from "../../artifacts/types/MeTokenRegistry"; -import { MeToken } from "../../artifacts/types/MeToken"; import { SingleAssetVault } from "../../artifacts/types/SingleAssetVault"; -import { MigrationRegistry } from "../../artifacts/types/MigrationRegistry"; import { deploy } from "../utils/helpers"; -import { hubSetup, hubSetupWithoutRegister } from "../utils/hubSetup"; +import { hubSetupWithoutRegister } from "../utils/hubSetup"; import { expect } from "chai"; import { mineBlock } from "../utils/hardhatNode"; @@ -29,23 +24,13 @@ const policyFactory = await ethers.getContractFactory("PolicyLib", { describe("Hub.sol", () => { let DAI: string; - let DAIWhale: string; let WETH: string; - let WETHWhale: string; - let daiHolder: Signer; - let dai: ERC20; let account0: SignerWithAddress; let account1: SignerWithAddress; - let account2: SignerWithAddress; let curve: BancorZeroCurve; - let meTokenRegistry: MeTokenRegistry; let foundry: Foundry; - let token: ERC20; - let meToken: MeToken; - let tokenHolder: Signer; let hub: Hub; let singleAssetVault: SingleAssetVault; - let migrationRegistry: MigrationRegistry; let curveRegistry: CurveRegistry; let vaultRegistry: VaultRegistry; let encodedVaultDAIArgs: string; @@ -53,25 +38,17 @@ describe("Hub.sol", () => { let encodedCurveDetails: string; const hubId = 1; - const name = "Carl meToken"; - const symbol = "CARL"; const refundRatio1 = 250000; const refundRatio2 = 240000; - const initRefundRatio = 50000; const PRECISION = ethers.utils.parseEther("1"); - const amount = ethers.utils.parseEther("10"); - const amount1 = ethers.utils.parseEther("100"); - const amount2 = ethers.utils.parseEther("6.9"); const duration = 60 * 60; - // TODO: pass in curve arguments to function - // TODO: then loop over array of set of curve arguments const MAX_WEIGHT = 1000000; const reserveWeight = MAX_WEIGHT / 2; const baseY = PRECISION.div(1000); before(async () => { - ({ DAI, DAIWhale, WETH, WETHWhale } = await getNamedAccounts()); + ({ DAI, WETH } = await getNamedAccounts()); encodedVaultDAIArgs = ethers.utils.defaultAbiCoder.encode( ["address"], [DAI] @@ -80,24 +57,18 @@ describe("Hub.sol", () => { ["address"], [WETH] ); - // TODO: pass in name of curve to deploy, encodedCurveDetails to general func encodedCurveDetails = ethers.utils.defaultAbiCoder.encode( ["uint256", "uint32"], [baseY, reserveWeight] ); curve = await deploy("BancorZeroCurve"); ({ - token, - tokenHolder, hub, foundry, account0, account1, - account2, - meTokenRegistry, vaultRegistry, curveRegistry, - migrationRegistry, singleAssetVault, } = await hubSetupWithoutRegister(curve)); }); @@ -232,8 +203,8 @@ describe("Hub.sol", () => { encodedCurveDetails, encodedVaultDAIArgs ); - expect(await hub.count()).to.be.equal(1); - const details = await hub.getDetails(1); + expect(await hub.count()).to.be.equal(hubId); + const details = await hub.getDetails(hubId); expect(details.active).to.be.equal(true); expect(details.owner).to.be.equal(account0.address); expect(details.vault).to.be.equal(singleAssetVault.address); @@ -312,7 +283,7 @@ describe("Hub.sol", () => { it("Should revert when nothing to update", async () => { const tx = hub.initUpdate(hubId, curve.address, 0, "0x"); await expect(tx).to.be.revertedWith("Nothing to update"); - // FIXME Hub.sol, -109 fix the conditions + // FIXME Hub.sol, -109 fix the require conditions }); it("Should revert from invalid _refundRatio", async () => { @@ -399,7 +370,7 @@ describe("Hub.sol", () => { expectedEndCooldownTime ); - const details = await hub.getDetails(1); + const details = await hub.getDetails(hubId); expect(details.active).to.be.equal(true); expect(details.owner).to.be.equal(account0.address); expect(details.vault).to.be.equal(singleAssetVault.address); @@ -416,7 +387,6 @@ describe("Hub.sol", () => { }); it("Should revert to called during warmup, duration, and cooldown", async () => { - // TODO: fast fwd to warmup, duration, cooldown and use expect() for each // calling initUpdate() to revert const txBeforeStartTime = hub.initUpdate( hubId, @@ -424,7 +394,7 @@ describe("Hub.sol", () => { refundRatio2, encodedCurveDetails ); - const details = await hub.getDetails(1); + const details = await hub.getDetails(hubId); await expect(txBeforeStartTime).to.be.revertedWith("already updating"); let block = await ethers.provider.getBlock("latest"); @@ -480,8 +450,8 @@ describe("Hub.sol", () => { expect(details.endTime).to.be.lt(block.timestamp); }); - it("Should first finishUpdate (if not) before next initUpdate", async () => { - let details = await hub.getDetails(1); + it("Should first finishUpdate (if not) before next initUpdate and set correct Hub details", async () => { + let details = await hub.getDetails(hubId); const newEncodedCurveDetails = ethers.utils.defaultAbiCoder.encode( ["uint32"], [reserveWeight / 2] @@ -507,6 +477,8 @@ describe("Hub.sol", () => { block.timestamp + duration + duration + duration; expect(txAfterEndCooldown) + .to.emit(hub, "FinishUpdate") + .withArgs(1) .to.emit(hub, "InitUpdate") .withArgs( hubId, @@ -519,7 +491,7 @@ describe("Hub.sol", () => { expectedEndCooldownTime ); - details = await hub.getDetails(1); + details = await hub.getDetails(hubId); expect(details.active).to.be.equal(true); expect(details.owner).to.be.equal(account0.address); expect(details.vault).to.be.equal(singleAssetVault.address); @@ -547,7 +519,7 @@ describe("Hub.sol", () => { expect(tx).to.emit(hub, "CancelUpdate").withArgs(hubId); - const details = await hub.getDetails(1); + const details = await hub.getDetails(hubId); expect(details.active).to.be.equal(true); expect(details.owner).to.be.equal(account0.address); expect(details.vault).to.be.equal(singleAssetVault.address); @@ -565,15 +537,81 @@ describe("Hub.sol", () => { it("should revert when not updating", async () => { await expect(hub.cancelUpdate(hubId)).to.be.revertedWith("!updating"); }); - it("should revert after warmup period", async () => {}); + it("should revert after warmup period", async () => { + // create a update + const newEncodedCurveDetails = ethers.utils.defaultAbiCoder.encode( + ["uint32"], + [reserveWeight / 2] + ); + const tx = await hub.initUpdate( + hubId, + ethers.constants.AddressZero, + 0, + newEncodedCurveDetails + ); + const receipt = await tx.wait(); + + let block = await ethers.provider.getBlock(receipt.blockNumber); + const expectedStartTime = block.timestamp + duration; + const expectedEndTime = block.timestamp + duration + duration; + const expectedEndCooldownTime = + block.timestamp + duration + duration + duration; + + expect(tx) + .to.emit(hub, "InitUpdate") + .withArgs( + hubId, + ethers.constants.AddressZero, + 0, + newEncodedCurveDetails, + true, + expectedStartTime, + expectedEndTime, + expectedEndCooldownTime + ); + + const details = await hub.getDetails(hubId); + expect(details.active).to.be.equal(true); + expect(details.owner).to.be.equal(account0.address); + expect(details.vault).to.be.equal(singleAssetVault.address); + expect(details.asset).to.be.equal(DAI); + expect(details.curve).to.be.equal(curve.address); + expect(details.refundRatio).to.be.equal(refundRatio2); + expect(details.updating).to.be.equal(true); + expect(details.startTime).to.be.equal(expectedStartTime); + expect(details.endTime).to.be.equal(expectedEndTime); + expect(details.endCooldown).to.be.equal(expectedEndCooldownTime); + expect(details.reconfigure).to.be.equal(true); + expect(details.targetCurve).to.be.equal(ethers.constants.AddressZero); + expect(details.targetRefundRatio).to.be.equal(0); + + // increase time beyond warmup period + await mineBlock(details.startTime.toNumber() + 1); + block = await ethers.provider.getBlock("latest"); + expect(details.startTime).to.be.lt(block.timestamp); + + // revert on cancelUpdate + const cancelUpdateTx = hub.cancelUpdate(hubId); + await expect(cancelUpdateTx).to.be.revertedWith("Update has started"); + }); }); describe("finishUpdate()", () => { it("Should revert if all arguments are the same", async () => { // TODO }); - it("Doesn't trigger during warmup or duration", async () => { - // TODO + it("should revert before endTime, during warmup and duration", async () => { + // increase time before endTime + const details = await hub.getDetails(hubId); + + await mineBlock(details.endTime.toNumber() - 2); + const block = await ethers.provider.getBlock("latest"); + expect(details.endTime).to.be.gt(block.timestamp); + + // revert on finishUpdate + await expect(hub.finishUpdate(hubId)).to.be.revertedWith( + "Still updating" + ); }); it("Trigger once when mint() called during cooldown", async () => { @@ -592,26 +630,65 @@ describe("Hub.sol", () => { // TODO }); - it("Correctly set HubDetails when called during cooldown", async () => { - // TODO + it("should correctly set HubDetails when called during cooldown", async () => { + // increase time after endTime + const oldDetails = await hub.getDetails(hubId); + await mineBlock(oldDetails.endTime.toNumber() + 2); + const block = await ethers.provider.getBlock("latest"); + expect(oldDetails.endTime).to.be.lt(block.timestamp); + + const finishUpdateTx = await hub.finishUpdate(hubId); + await finishUpdateTx.wait(); + + expect(finishUpdateTx).to.emit(hub, "FinishUpdate").withArgs(hubId); + + const newDetails = await hub.getDetails(hubId); + expect(newDetails.active).to.be.equal(true); + expect(newDetails.owner).to.be.equal(account0.address); + expect(newDetails.vault).to.be.equal(singleAssetVault.address); + expect(newDetails.asset).to.be.equal(DAI); + expect(newDetails.curve).to.be.equal(curve.address); + expect(newDetails.refundRatio).to.be.equal(refundRatio2); + expect(newDetails.updating).to.be.equal(false); + expect(newDetails.startTime).to.be.equal(0); + expect(newDetails.endTime).to.be.equal(0); + expect(newDetails.endCooldown).to.be.equal(oldDetails.endCooldown); + expect(newDetails.reconfigure).to.be.equal(false); + expect(newDetails.targetCurve).to.be.equal(ethers.constants.AddressZero); + expect(newDetails.targetRefundRatio).to.be.equal(0); }); it("Correctly set HubDetails when called after cooldown", async () => { - // TODO + // TODO Not required as would be same as above }); it("Correctly set HubDetails when called during second initUpdate()", async () => { - // TODO + // TODO Covered in initUpdate() describe }); }); describe("transferHubOwnership()", () => { - it("Cannot be called by non-owner", async () => { - // TODO + it("should revert when called by non-owner", async () => { + await expect( + hub.connect(account1).transferHubOwnership(hubId, account1.address) + ).to.be.revertedWith("!owner"); }); - it("Cannot be set to the current owner", async () => { - // TODO + it("should revert when set to the current owner", async () => { + await expect( + hub.transferHubOwnership(hubId, account0.address) + ).to.be.revertedWith("Same owner"); }); - it("Successfully transfers hub ownership", async () => { - // TODO + it("should transfers hub ownership", async () => { + const transferHubOwnershipTx = await hub.transferHubOwnership( + hubId, + account1.address + ); + await transferHubOwnershipTx.wait(); + + expect(transferHubOwnershipTx) + .to.emit(hub, "TransferHubOwnership") + .withArgs(hubId, account1.address); + + const newDetails = await hub.getDetails(hubId); + expect(newDetails.owner).to.be.equal(account1.address); }); }); }); From 1ba6f99b96379f3cea54504e4e909f9e6ba31478 Mon Sep 17 00:00:00 2001 From: Parv Date: Wed, 8 Dec 2021 16:49:00 +0530 Subject: [PATCH 11/15] fix(Hub.sol): fix require bug --- contracts/Hub.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/Hub.sol b/contracts/Hub.sol index 7fce97a1..cd0bd668 100644 --- a/contracts/Hub.sol +++ b/contracts/Hub.sol @@ -97,9 +97,7 @@ contract Hub is IHub, Ownable, Initializable { require(block.timestamp >= hub_.endCooldown, "Still cooling down"); // Make sure at least one of the values is different require( - (_targetRefundRatio != 0) || - (_targetCurve != hub_.curve) || - (_encodedCurveDetails.length > 0), + (_targetRefundRatio != 0) || (_encodedCurveDetails.length > 0), "Nothing to update" ); From 5d2cb620038763e4bdb534236f92e5ba926c9d36 Mon Sep 17 00:00:00 2001 From: Parv Date: Wed, 8 Dec 2021 18:01:15 +0530 Subject: [PATCH 12/15] feat(hub): add incremental hub testcases --- test/contracts/Hub.ts | 57 ++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 36 deletions(-) diff --git a/test/contracts/Hub.ts b/test/contracts/Hub.ts index 5159c274..effb4894 100644 --- a/test/contracts/Hub.ts +++ b/test/contracts/Hub.ts @@ -139,8 +139,6 @@ describe("Hub.sol", () => { encodedVaultDAIArgs ); await expect(tx).to.be.revertedWith("!_encodedDetails"); - - // TODO as this revert is caused by external contracts, do they need to be covered here? }); it("Should revert from invalid encodedVaultArgs", async () => { // Invalid _encodedVaultArgs @@ -192,7 +190,7 @@ describe("Hub.sol", () => { ); await tx.wait(); - expect(tx) + await expect(tx) .to.emit(hub, "Register") .withArgs( account0.address, @@ -283,7 +281,6 @@ describe("Hub.sol", () => { it("Should revert when nothing to update", async () => { const tx = hub.initUpdate(hubId, curve.address, 0, "0x"); await expect(tx).to.be.revertedWith("Nothing to update"); - // FIXME Hub.sol, -109 fix the require conditions }); it("Should revert from invalid _refundRatio", async () => { @@ -315,7 +312,6 @@ describe("Hub.sol", () => { badEncodedCurveDetails ); await expect(tx).to.be.revertedWith("!reserveWeight"); - // TODO as this revert is caused by external contracts, do they need to be covered here? }); it("Should revert when curve is not approved", async () => { @@ -340,7 +336,6 @@ describe("Hub.sol", () => { badEncodedCurveDetails ); await expect(tx).to.be.revertedWith("!baseY"); - // TODO as this revert is caused by external contracts, do they need to be covered here? }); it("Should be able to initUpdate with new refundRatio", async () => { @@ -357,7 +352,7 @@ describe("Hub.sol", () => { const expectedEndCooldownTime = block.timestamp + duration + duration + duration; - expect(tx) + await expect(tx) .to.emit(hub, "InitUpdate") .withArgs( hubId, @@ -452,18 +447,14 @@ describe("Hub.sol", () => { it("Should first finishUpdate (if not) before next initUpdate and set correct Hub details", async () => { let details = await hub.getDetails(hubId); - const newEncodedCurveDetails = ethers.utils.defaultAbiCoder.encode( - ["uint32"], - [reserveWeight / 2] - ); // fast fwd to endCooldown - 2 await mineBlock(details.endCooldown.toNumber()); const txAfterEndCooldown = await hub.initUpdate( hubId, ethers.constants.AddressZero, - 0, - newEncodedCurveDetails + refundRatio1, + "0x" ); const receipt = await txAfterEndCooldown.wait(); @@ -476,16 +467,16 @@ describe("Hub.sol", () => { const expectedEndCooldownTime = block.timestamp + duration + duration + duration; - expect(txAfterEndCooldown) + await expect(txAfterEndCooldown) .to.emit(hub, "FinishUpdate") .withArgs(1) .to.emit(hub, "InitUpdate") .withArgs( hubId, ethers.constants.AddressZero, - 0, - newEncodedCurveDetails, - true, + refundRatio1, + "0x", + false, expectedStartTime, expectedEndTime, expectedEndCooldownTime @@ -502,9 +493,9 @@ describe("Hub.sol", () => { expect(details.startTime).to.be.equal(expectedStartTime); expect(details.endTime).to.be.equal(expectedEndTime); expect(details.endCooldown).to.be.equal(expectedEndCooldownTime); - expect(details.reconfigure).to.be.equal(true); + expect(details.reconfigure).to.be.equal(false); expect(details.targetCurve).to.be.equal(curve.address); - expect(details.targetRefundRatio).to.be.equal(0); + expect(details.targetRefundRatio).to.be.equal(refundRatio1); }); }); @@ -517,7 +508,7 @@ describe("Hub.sol", () => { const tx = await hub.cancelUpdate(hubId); await tx.wait(); - expect(tx).to.emit(hub, "CancelUpdate").withArgs(hubId); + await expect(tx).to.emit(hub, "CancelUpdate").withArgs(hubId); const details = await hub.getDetails(hubId); expect(details.active).to.be.equal(true); @@ -557,7 +548,7 @@ describe("Hub.sol", () => { const expectedEndCooldownTime = block.timestamp + duration + duration + duration; - expect(tx) + await expect(tx) .to.emit(hub, "InitUpdate") .withArgs( hubId, @@ -597,7 +588,7 @@ describe("Hub.sol", () => { }); describe("finishUpdate()", () => { - it("Should revert if all arguments are the same", async () => { + xit("Should revert if all arguments are the same", async () => { // TODO }); it("should revert before endTime, during warmup and duration", async () => { @@ -614,20 +605,20 @@ describe("Hub.sol", () => { ); }); - it("Trigger once when mint() called during cooldown", async () => { + xit("Trigger once when mint() called during cooldown", async () => { // TODO }); - it("Trigger once when burn() called during cooldown", async () => { + xit("Trigger once when burn() called during cooldown", async () => { // TODO }); - it("Trigger once when mint() called if no mint() / burn() called during cooldown", async () => { - // TODO + xit("Trigger once when mint() called if no mint() / burn() called during cooldown", async () => { + // TODO first mint should finish update. }); - it("Trigger once when burn() called if no mint() / burn() called during cooldown", async () => { - // TODO + xit("Trigger once when burn() called if no mint() / burn() called during cooldown", async () => { + // TODO no more updating, should not call finish }); it("should correctly set HubDetails when called during cooldown", async () => { @@ -640,7 +631,7 @@ describe("Hub.sol", () => { const finishUpdateTx = await hub.finishUpdate(hubId); await finishUpdateTx.wait(); - expect(finishUpdateTx).to.emit(hub, "FinishUpdate").withArgs(hubId); + await expect(finishUpdateTx).to.emit(hub, "FinishUpdate").withArgs(hubId); const newDetails = await hub.getDetails(hubId); expect(newDetails.active).to.be.equal(true); @@ -657,12 +648,6 @@ describe("Hub.sol", () => { expect(newDetails.targetCurve).to.be.equal(ethers.constants.AddressZero); expect(newDetails.targetRefundRatio).to.be.equal(0); }); - it("Correctly set HubDetails when called after cooldown", async () => { - // TODO Not required as would be same as above - }); - it("Correctly set HubDetails when called during second initUpdate()", async () => { - // TODO Covered in initUpdate() describe - }); }); describe("transferHubOwnership()", () => { @@ -683,7 +668,7 @@ describe("Hub.sol", () => { ); await transferHubOwnershipTx.wait(); - expect(transferHubOwnershipTx) + await expect(transferHubOwnershipTx) .to.emit(hub, "TransferHubOwnership") .withArgs(hubId, account1.address); From 15b43c0b536f4a0f00b7977414344c5158b630ae Mon Sep 17 00:00:00 2001 From: Parv Date: Wed, 8 Dec 2021 21:41:08 +0530 Subject: [PATCH 13/15] feat(hub): complete testcases --- test/contracts/Hub.ts | 148 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 128 insertions(+), 20 deletions(-) diff --git a/test/contracts/Hub.ts b/test/contracts/Hub.ts index effb4894..6debcb83 100644 --- a/test/contracts/Hub.ts +++ b/test/contracts/Hub.ts @@ -6,10 +6,14 @@ import { VaultRegistry } from "../../artifacts/types/VaultRegistry"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { BancorZeroCurve } from "../../artifacts/types/BancorZeroCurve"; import { SingleAssetVault } from "../../artifacts/types/SingleAssetVault"; -import { deploy } from "../utils/helpers"; +import { deploy, getContractAt } from "../utils/helpers"; import { hubSetupWithoutRegister } from "../utils/hubSetup"; import { expect } from "chai"; import { mineBlock } from "../utils/hardhatNode"; +import { ERC20 } from "../../artifacts/types/ERC20"; +import { Signer } from "@ethersproject/abstract-signer"; +import { MeTokenRegistry } from "../../artifacts/types/MeTokenRegistry"; +import { MeToken } from "../../artifacts/types/MeToken"; /* const paginationFactory = await ethers.getContractFactory("Pagination", {}); @@ -27,6 +31,7 @@ describe("Hub.sol", () => { let WETH: string; let account0: SignerWithAddress; let account1: SignerWithAddress; + let account2: SignerWithAddress; let curve: BancorZeroCurve; let foundry: Foundry; let hub: Hub; @@ -36,6 +41,11 @@ describe("Hub.sol", () => { let encodedVaultDAIArgs: string; let encodedVaultWETHArgs: string; let encodedCurveDetails: string; + let token: ERC20; + let dai: ERC20; + let tokenHolder: Signer; + let meTokenRegistry: MeTokenRegistry; + let meToken: MeToken; const hubId = 1; const refundRatio1 = 250000; @@ -46,6 +56,9 @@ describe("Hub.sol", () => { const MAX_WEIGHT = 1000000; const reserveWeight = MAX_WEIGHT / 2; const baseY = PRECISION.div(1000); + const amount = ethers.utils.parseEther("100"); + const name = "Carl meToken"; + const symbol = "CARL"; before(async () => { ({ DAI, WETH } = await getNamedAccounts()); @@ -63,10 +76,14 @@ describe("Hub.sol", () => { ); curve = await deploy("BancorZeroCurve"); ({ + token, + tokenHolder, hub, foundry, account0, account1, + account2, + meTokenRegistry, vaultRegistry, curveRegistry, singleAssetVault, @@ -220,6 +237,26 @@ describe("Hub.sol", () => { }); describe("setWarmup()", () => { + before(async () => { + // required in later testing + + dai = token; + await dai.connect(tokenHolder).transfer(account0.address, amount); + await dai.connect(tokenHolder).transfer(account1.address, amount); + await dai.connect(tokenHolder).transfer(account2.address, amount); + await dai.connect(account1).approve(foundry.address, amount); + await dai.connect(account2).approve(foundry.address, amount); + await dai.connect(account1).approve(meTokenRegistry.address, amount); + // account0 is registering a metoken + const tx = await meTokenRegistry + .connect(account0) + .subscribe(name, symbol, hubId, 0); + const meTokenAddr = await meTokenRegistry.getOwnerMeToken( + account0.address + ); + + meToken = await getContractAt("MeToken", meTokenAddr); + }); it("Should revert to setWarmup if not owner", async () => { const tx = hub.connect(account1).setWarmup(duration); await expect(tx).to.be.revertedWith("Ownable: caller is not the owner"); @@ -588,9 +625,6 @@ describe("Hub.sol", () => { }); describe("finishUpdate()", () => { - xit("Should revert if all arguments are the same", async () => { - // TODO - }); it("should revert before endTime, during warmup and duration", async () => { // increase time before endTime const details = await hub.getDetails(hubId); @@ -605,22 +639,6 @@ describe("Hub.sol", () => { ); }); - xit("Trigger once when mint() called during cooldown", async () => { - // TODO - }); - - xit("Trigger once when burn() called during cooldown", async () => { - // TODO - }); - - xit("Trigger once when mint() called if no mint() / burn() called during cooldown", async () => { - // TODO first mint should finish update. - }); - - xit("Trigger once when burn() called if no mint() / burn() called during cooldown", async () => { - // TODO no more updating, should not call finish - }); - it("should correctly set HubDetails when called during cooldown", async () => { // increase time after endTime const oldDetails = await hub.getDetails(hubId); @@ -648,6 +666,96 @@ describe("Hub.sol", () => { expect(newDetails.targetCurve).to.be.equal(ethers.constants.AddressZero); expect(newDetails.targetRefundRatio).to.be.equal(0); }); + + describe("finishUpdate() from mint | burn", () => { + let toggle = false; // for generating different weight each time + beforeEach(async () => { + const oldDetails = await hub.getDetails(hubId); + await mineBlock(oldDetails.endCooldown.toNumber() + 10); + + const newEncodedCurveDetails = ethers.utils.defaultAbiCoder.encode( + ["uint32"], + [reserveWeight / (toggle ? 2 : 1)] + ); + toggle = !toggle; + const tx = await hub.initUpdate( + hubId, + ethers.constants.AddressZero, + 0, + newEncodedCurveDetails + ); + await tx.wait(); + + // increase time after endTime + const details = await hub.getDetails(hubId); + await mineBlock(details.endTime.toNumber() + 2); + const block = await ethers.provider.getBlock("latest"); + expect(details.endTime).to.be.lt(block.timestamp); + expect(details.endCooldown).to.be.gt(block.timestamp); + }); + + it("Trigger once when mint() called during cooldown", async () => { + const amount = ethers.utils.parseEther("100"); + await dai.connect(tokenHolder).transfer(account2.address, amount); + // need an approve of metoken registry first + await dai.connect(account2).approve(foundry.address, amount); + + const tx = await foundry + .connect(account2) + .mint(meToken.address, amount, account2.address); + + await tx.wait(); + await expect(tx).to.emit(hub, "FinishUpdate").withArgs(hubId); + }); + + it("Trigger once when burn() called during cooldown", async () => { + const amount = ethers.utils.parseEther("10"); + + const tx = await foundry + .connect(account2) + .burn(meToken.address, amount, account2.address); + + await tx.wait(); + await expect(tx).to.emit(hub, "FinishUpdate").withArgs(hubId); + }); + + it("Trigger once when mint() called if no mint() / burn() called during cooldown", async () => { + // increase time after endCooldown + const details = await hub.getDetails(hubId); + await mineBlock(details.endCooldown.toNumber() + 2); + const block = await ethers.provider.getBlock("latest"); + expect(details.endCooldown).to.be.lt(block.timestamp); + + const amount = ethers.utils.parseEther("100"); + await dai.connect(tokenHolder).transfer(account2.address, amount); + // need an approve of metoken registry first + await dai.connect(account2).approve(foundry.address, amount); + + const tx = await foundry + .connect(account2) + .mint(meToken.address, amount, account2.address); + + await tx.wait(); + await expect(tx).to.emit(hub, "FinishUpdate").withArgs(hubId); + }); + + it("Trigger once when burn() called if no mint() / burn() called during cooldown", async () => { + // increase time after endCooldown + const details = await hub.getDetails(hubId); + await mineBlock(details.endCooldown.toNumber() + 2); + const block = await ethers.provider.getBlock("latest"); + expect(details.endCooldown).to.be.lt(block.timestamp); + + const amount = ethers.utils.parseEther("10"); + + const tx = await foundry + .connect(account2) + .burn(meToken.address, amount, account2.address); + + await tx.wait(); + await expect(tx).to.emit(hub, "FinishUpdate").withArgs(hubId); + }); + }); }); describe("transferHubOwnership()", () => { From 979ed8e5320abc4124a191434937aea05147474a Mon Sep 17 00:00:00 2001 From: Parv Date: Wed, 8 Dec 2021 21:50:06 +0530 Subject: [PATCH 14/15] feat(hub): consistent descriptions --- test/contracts/Hub.ts | 54 +++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/test/contracts/Hub.ts b/test/contracts/Hub.ts index 6debcb83..15f7949e 100644 --- a/test/contracts/Hub.ts +++ b/test/contracts/Hub.ts @@ -119,7 +119,7 @@ describe("Hub.sol", () => { }); describe("register()", () => { - it("Should revert from invalid address arguments", async () => { + it("should revert from invalid address arguments", async () => { // Un-approved curve let tx = hub.register( account0.address, @@ -144,7 +144,7 @@ describe("Hub.sol", () => { ); await expect(tx).to.be.revertedWith("_vault !approved"); }); - it("Should revert from invalid encodedCurveDetails", async () => { + it("should revert from invalid encodedCurveDetails", async () => { // Invalid _encodedCurveDetails for particular curve let tx = hub.register( account0.address, @@ -157,7 +157,7 @@ describe("Hub.sol", () => { ); await expect(tx).to.be.revertedWith("!_encodedDetails"); }); - it("Should revert from invalid encodedVaultArgs", async () => { + it("should revert from invalid encodedVaultArgs", async () => { // Invalid _encodedVaultArgs const tx = hub.register( account0.address, @@ -170,7 +170,7 @@ describe("Hub.sol", () => { ); await expect(tx).to.be.revertedWith("asset !valid"); }); - it("Should revert from invalid _refundRatio", async () => { + it("should revert from invalid _refundRatio", async () => { // _refundRatio > MAX_REFUND_RATIO let tx = hub.register( account0.address, @@ -195,7 +195,7 @@ describe("Hub.sol", () => { ); await expect(tx).to.be.revertedWith("_refundRatio == 0"); }); - it("Should be able to register", async () => { + it("should be able to register", async () => { const tx = await hub.register( account0.address, DAI, @@ -257,16 +257,16 @@ describe("Hub.sol", () => { meToken = await getContractAt("MeToken", meTokenAddr); }); - it("Should revert to setWarmup if not owner", async () => { + it("should revert to setWarmup if not owner", async () => { const tx = hub.connect(account1).setWarmup(duration); await expect(tx).to.be.revertedWith("Ownable: caller is not the owner"); }); - it("Should revert to setWarmup if same as before", async () => { + it("should revert to setWarmup if same as before", async () => { const oldWarmup = await hub.getWarmup(); const tx = hub.setWarmup(oldWarmup); await expect(tx).to.be.revertedWith("warmup_ == _warmup"); }); - it("Should be able to setWarmup", async () => { + it("should be able to setWarmup", async () => { const tx = await hub.setWarmup(duration); await tx.wait(); expect(await hub.getWarmup()).to.be.equal(duration); @@ -274,16 +274,16 @@ describe("Hub.sol", () => { }); describe("setDuration()", () => { - it("Should revert to setDuration if not owner", async () => { + it("should revert to setDuration if not owner", async () => { const tx = hub.connect(account1).setDuration(duration); await expect(tx).to.be.revertedWith("Ownable: caller is not the owner"); }); - it("Should revert to setDuration if same as before", async () => { + it("should revert to setDuration if same as before", async () => { const oldWarmup = await hub.getDuration(); const tx = hub.setDuration(oldWarmup); await expect(tx).to.be.revertedWith("duration_ == _duration"); }); - it("Should be able to setDuration", async () => { + it("should be able to setDuration", async () => { const tx = await hub.setDuration(duration); await tx.wait(); expect(await hub.getDuration()).to.be.equal(duration); @@ -291,16 +291,16 @@ describe("Hub.sol", () => { }); describe("setCooldown()", () => { - it("Should revert to setCooldown if not owner", async () => { + it("should revert to setCooldown if not owner", async () => { const tx = hub.connect(account1).setCooldown(duration); await expect(tx).to.be.revertedWith("Ownable: caller is not the owner"); }); - it("Should revert to setCooldown if same as before", async () => { + it("should revert to setCooldown if same as before", async () => { const oldWarmup = await hub.getCooldown(); const tx = hub.setCooldown(oldWarmup); await expect(tx).to.be.revertedWith("cooldown_ == _cooldown"); }); - it("Should be able to setCooldown", async () => { + it("should be able to setCooldown", async () => { const tx = await hub.setCooldown(duration); await tx.wait(); expect(await hub.getCooldown()).to.be.equal(duration); @@ -308,19 +308,19 @@ describe("Hub.sol", () => { }); describe("initUpdate()", () => { - it("Should revert when sender is not owner", async () => { + it("should revert when sender is not owner", async () => { const tx = hub .connect(account1) .initUpdate(hubId, curve.address, refundRatio2, encodedCurveDetails); await expect(tx).to.be.revertedWith("!owner"); }); - it("Should revert when nothing to update", async () => { + it("should revert when nothing to update", async () => { const tx = hub.initUpdate(hubId, curve.address, 0, "0x"); await expect(tx).to.be.revertedWith("Nothing to update"); }); - it("Should revert from invalid _refundRatio", async () => { + it("should revert from invalid _refundRatio", async () => { const tx1 = hub.initUpdate( hubId, curve.address, @@ -337,7 +337,7 @@ describe("Hub.sol", () => { await expect(tx2).to.be.revertedWith("_targetRefundRatio == refundRatio"); }); - it("Should revert on ICurve.initReconfigure() from invalid encodedCurveDetails", async () => { + it("should revert on ICurve.initReconfigure() from invalid encodedCurveDetails", async () => { const badEncodedCurveDetails = ethers.utils.defaultAbiCoder.encode( ["uint32"], [0] @@ -351,7 +351,7 @@ describe("Hub.sol", () => { await expect(tx).to.be.revertedWith("!reserveWeight"); }); - it("Should revert when curve is not approved", async () => { + it("should revert when curve is not approved", async () => { const tx = hub.initUpdate( hubId, account0.address, // invalid curve address @@ -361,7 +361,7 @@ describe("Hub.sol", () => { await expect(tx).to.be.revertedWith("_targetCurve !approved"); }); - it("Should revert on ICurve.register() from invalid encodedCurveDetails", async () => { + it("should revert on ICurve.register() from invalid encodedCurveDetails", async () => { const badEncodedCurveDetails = ethers.utils.defaultAbiCoder.encode( ["uint256", "uint32"], [0, 0] @@ -375,7 +375,7 @@ describe("Hub.sol", () => { await expect(tx).to.be.revertedWith("!baseY"); }); - it("Should be able to initUpdate with new refundRatio", async () => { + it("should be able to initUpdate with new refundRatio", async () => { const tx = await hub.initUpdate( hubId, curve.address, @@ -418,7 +418,7 @@ describe("Hub.sol", () => { expect(details.targetRefundRatio).to.be.equal(refundRatio2); }); - it("Should revert to called during warmup, duration, and cooldown", async () => { + it("should revert to called during warmup, duration, and cooldown", async () => { // calling initUpdate() to revert const txBeforeStartTime = hub.initUpdate( hubId, @@ -482,7 +482,7 @@ describe("Hub.sol", () => { expect(details.endTime).to.be.lt(block.timestamp); }); - it("Should first finishUpdate (if not) before next initUpdate and set correct Hub details", async () => { + it("should first finishUpdate (if not) before next initUpdate and set correct Hub details", async () => { let details = await hub.getDetails(hubId); // fast fwd to endCooldown - 2 @@ -694,7 +694,7 @@ describe("Hub.sol", () => { expect(details.endCooldown).to.be.gt(block.timestamp); }); - it("Trigger once when mint() called during cooldown", async () => { + it("should trigger finishUpdate() once when mint() called during cooldown", async () => { const amount = ethers.utils.parseEther("100"); await dai.connect(tokenHolder).transfer(account2.address, amount); // need an approve of metoken registry first @@ -708,7 +708,7 @@ describe("Hub.sol", () => { await expect(tx).to.emit(hub, "FinishUpdate").withArgs(hubId); }); - it("Trigger once when burn() called during cooldown", async () => { + it("should trigger finishUpdate() once when burn() called during cooldown", async () => { const amount = ethers.utils.parseEther("10"); const tx = await foundry @@ -719,7 +719,7 @@ describe("Hub.sol", () => { await expect(tx).to.emit(hub, "FinishUpdate").withArgs(hubId); }); - it("Trigger once when mint() called if no mint() / burn() called during cooldown", async () => { + it("should trigger finishUpdate() once after cooldown when mint() called if no mint() / burn() called during cooldown", async () => { // increase time after endCooldown const details = await hub.getDetails(hubId); await mineBlock(details.endCooldown.toNumber() + 2); @@ -739,7 +739,7 @@ describe("Hub.sol", () => { await expect(tx).to.emit(hub, "FinishUpdate").withArgs(hubId); }); - it("Trigger once when burn() called if no mint() / burn() called during cooldown", async () => { + it("should trigger finishUpdate() once after cooldown when burn() called if no mint() / burn() called during cooldown", async () => { // increase time after endCooldown const details = await hub.getDetails(hubId); await mineBlock(details.endCooldown.toNumber() + 2); From 00178d4e97a6daf9d31ec88724176a6eeaef7b1b Mon Sep 17 00:00:00 2001 From: Parv Date: Thu, 9 Dec 2021 19:13:14 +0530 Subject: [PATCH 15/15] fix(Hub.ts): rename curve --- test/contracts/Hub.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/contracts/Hub.ts b/test/contracts/Hub.ts index 15f7949e..051aa99e 100644 --- a/test/contracts/Hub.ts +++ b/test/contracts/Hub.ts @@ -4,7 +4,7 @@ import { Foundry } from "../../artifacts/types/Foundry"; import { CurveRegistry } from "../../artifacts/types/CurveRegistry"; import { VaultRegistry } from "../../artifacts/types/VaultRegistry"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { BancorZeroCurve } from "../../artifacts/types/BancorZeroCurve"; +import { BancorABDK } from "../../artifacts/types/BancorABDK"; import { SingleAssetVault } from "../../artifacts/types/SingleAssetVault"; import { deploy, getContractAt } from "../utils/helpers"; import { hubSetupWithoutRegister } from "../utils/hubSetup"; @@ -32,7 +32,7 @@ describe("Hub.sol", () => { let account0: SignerWithAddress; let account1: SignerWithAddress; let account2: SignerWithAddress; - let curve: BancorZeroCurve; + let curve: BancorABDK; let foundry: Foundry; let hub: Hub; let singleAssetVault: SingleAssetVault; @@ -74,7 +74,7 @@ describe("Hub.sol", () => { ["uint256", "uint32"], [baseY, reserveWeight] ); - curve = await deploy("BancorZeroCurve"); + curve = await deploy("BancorABDK"); ({ token, tokenHolder,