Skip to content
This repository has been archived by the owner on Oct 6, 2023. It is now read-only.

Commit

Permalink
AP-745: Improve test speed by utilizing snapshot testing (#359)
Browse files Browse the repository at this point in the history
* Use snapshots in IndexFund

* Normalize test data index funds between tests

* Refactor test snapshots

* Remove unnecessary changes

* Use snapshots in AccountsUpdate

* Add snapshot tests + refactor to AccountsAllowance

* Add snapshot tests + refactor to AccountsCreateEndowment

* Add snapshot tests  AccountsDepositWithdrawEndowments

* Add snapshot tests + refactor to AccountsGasManager

* Add snapshot tests + refactor to AccountsStrategy

* Add snapshot tests + refactor AccountsSwapRouter

* Add snapshot tests + refactor AccountsUpdateEndowments

* Add snapshot tests + refactor AccountsUpdateEndowmentSettingsController

* Add snapshot tests + refactor AccountsUpdateStatusEndowments

* Add snapshot tests + refactor to GasFwd

* Refactor GasFwdFactory

* Add snapshot tests + refactor to LocalRegistrar

* Add snapshot tests + refactor to Router

* Add snapshot tests + refactor to Halo

* Remove SignerWithAddress from IndexFund.ts

* Add snapshot tests + refactor to FluxStrategy

* Add snapshot tests + refactor to Vault
  • Loading branch information
Nenad Misic authored Sep 19, 2023
1 parent 7c5b02d commit 3970403
Show file tree
Hide file tree
Showing 18 changed files with 839 additions and 689 deletions.
66 changes: 57 additions & 9 deletions test/core/IndexFund.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import {FakeContract, smock} from "@defi-wonderland/smock";
import {impersonateAccount, setBalance, time} from "@nomicfoundation/hardhat-network-helpers";
import {
SnapshotRestorer,
impersonateAccount,
setBalance,
takeSnapshot,
time,
} from "@nomicfoundation/hardhat-network-helpers";
import {expect} from "chai";
import {Signer} from "ethers";
import hre from "hardhat";
Expand Down Expand Up @@ -31,11 +37,11 @@ describe("IndexFund", function () {
let proxyAdmin: Signer;
let user: Signer;

let accountsDepositWithdrawEndowments: AccountsDepositWithdrawEndowments;
let registrar: FakeContract<Registrar>;
let wmatic: FakeContract<DummyWMATIC>;
let token: FakeContract<IERC20>;

let accountsDepositWithdrawEndowments: AccountsDepositWithdrawEndowments;
let state: TestFacetProxyContract;
let facet: IndexFund;

Expand Down Expand Up @@ -134,9 +140,7 @@ describe("IndexFund", function () {
reentrancyGuardLocked: false,
})
);
});

beforeEach(async () => {
const proxy = await deployIndexFundAsProxy();
facet = IndexFund__factory.connect(proxy.address, owner);

Expand All @@ -152,6 +156,16 @@ describe("IndexFund", function () {
registrar.isTokenAccepted.whenCalledWith(token.address).returns(true);
});

let snapshot: SnapshotRestorer;

beforeEach(async () => {
snapshot = await takeSnapshot();
});

afterEach(async () => {
await snapshot.restore();
});

describe("Deploying the contract", function () {
it("Deploying the contract as an upgradable proxy", async function () {
const proxy = await deployIndexFundAsProxy();
Expand Down Expand Up @@ -289,7 +303,11 @@ describe("IndexFund", function () {
});

describe("Updating an existing Fund's endowment members", function () {
beforeEach(async function () {
let rootSnapshot: SnapshotRestorer;

before(async function () {
rootSnapshot = await takeSnapshot();

// create 2 funds (1 active and 1 expired)
let currTime = await time.latest();
await wait(facet.createIndexFund("Test Fund #1", "Test fund", [2, 3], true, 50, 0));
Expand All @@ -299,6 +317,10 @@ describe("IndexFund", function () {
await time.increase(42069); // move time forward so Fund #2 is @ expiry
});

after(async () => {
await rootSnapshot.restore();
});

it("reverts when the message sender is not the owner", async function () {
await expect(facet.connect(user).updateFundMembers(1, [1, 2], [])).to.be.revertedWith(
"Ownable: caller is not the owner"
Expand Down Expand Up @@ -333,7 +355,11 @@ describe("IndexFund", function () {
});

describe("Removing an existing Fund", function () {
beforeEach(async function () {
let rootSnapshot: SnapshotRestorer;

before(async function () {
rootSnapshot = await takeSnapshot();

// create 2 funds (1 active and 1 expired)
let currTime = await time.latest();
await wait(facet.createIndexFund("Test Fund #1", "Test fund", [2, 3], true, 50, 0));
Expand All @@ -343,6 +369,10 @@ describe("IndexFund", function () {
await time.increase(42069); // move time forward so Fund #2 is @ expiry
});

after(async () => {
await rootSnapshot.restore();
});

it("reverts when the message sender is not the owner", async function () {
await expect(facet.connect(user).removeIndexFund(1)).to.be.revertedWith(
"Ownable: caller is not the owner"
Expand All @@ -359,7 +389,11 @@ describe("IndexFund", function () {
});

describe("Removing an endowment from all involved Funds", function () {
beforeEach(async function () {
let rootSnapshot: SnapshotRestorer;

before(async function () {
rootSnapshot = await takeSnapshot();

// create 2 funds (1 active and 1 expired)
let currTime = await time.latest();
await wait(facet.createIndexFund("Test Fund #1", "Test fund", [2, 3], true, 50, 0));
Expand All @@ -369,6 +403,10 @@ describe("IndexFund", function () {
await time.increase(42069); // move time forward so Fund #2 is @ expiry
});

after(async () => {
await rootSnapshot.restore();
});

it("reverts when the message sender is not the accounts contract", async function () {
await expect(facet.removeMember(1)).to.be.revertedWith("Unauthorized");
});
Expand All @@ -394,7 +432,11 @@ describe("IndexFund", function () {
});

describe("When a user deposits tokens to a Fund", function () {
beforeEach(async function () {
let rootSnapshot: SnapshotRestorer;

before(async function () {
rootSnapshot = await takeSnapshot();

let currTime = await time.latest();
// create 1 active, non-rotating fund
await wait(facet.createIndexFund("Test Fund #1", "Test fund", [2, 3], false, 50, 0));
Expand All @@ -405,6 +447,10 @@ describe("IndexFund", function () {
await time.increase(42069); // move time forward so Fund #2 is @ expiry
});

after(async () => {
await rootSnapshot.restore();
});

it("reverts when amount is zero", async function () {
await expect(facet.depositERC20(1, token.address, 0)).to.be.revertedWith(
"Amount to donate must be greater than zero"
Expand All @@ -416,6 +462,8 @@ describe("IndexFund", function () {
await expect(facet.depositERC20(1, token.address, 100)).to.be.revertedWith(
"Unaccepted Token"
);
// reset isTokenAccepted behavior
registrar.isTokenAccepted.whenCalledWith(token.address).returns(true);
});

it("reverts when fund passed is expired", async function () {
Expand Down Expand Up @@ -509,7 +557,7 @@ describe("IndexFund", function () {
// test with a LARGER donation amount for gas-usage and rotation stress-tests
await expect(
facet.depositERC20(0, token.address, 1000000, {
gasPrice: 100000,
// gasPrice: 100000, @Nenad: Just wondering, why is manual gas price needed?
gasLimit: 10000000,
})
)
Expand Down
94 changes: 59 additions & 35 deletions test/core/accounts/AccountsAllowance.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {FakeContract, smock} from "@defi-wonderland/smock";
import {time} from "@nomicfoundation/hardhat-network-helpers";
import {SnapshotRestorer, takeSnapshot, time} from "@nomicfoundation/hardhat-network-helpers";
import {expect} from "chai";
import {Signer} from "ethers";
import hre from "hardhat";
Expand Down Expand Up @@ -36,9 +36,7 @@ describe("AccountsAllowance", function () {
user = signers.apTeam2;

proxyAdmin = await getProxyAdminOwner(hre);
});

beforeEach(async function () {
tokenFake = await smock.fake<IERC20>(IERC20__factory.createInterface());

const Facet = new AccountsAllowance__factory(accOwner);
Expand Down Expand Up @@ -72,6 +70,16 @@ describe("AccountsAllowance", function () {
await wait(state.setAllowlist(ACCOUNT_ID, 2, [await user.getAddress()])); // maturity
});

let snapshot: SnapshotRestorer;

beforeEach(async () => {
snapshot = await takeSnapshot();
});

afterEach(async () => {
await snapshot.restore();
});

describe("Test cases for `manageAllowances`", function () {
it("reverts when the endowment is closed", async function () {
await wait(
Expand Down Expand Up @@ -124,12 +132,21 @@ describe("AccountsAllowance", function () {
10
)
).to.be.revertedWith("Invalid Token");
});

it("reverts when the token dne", async function () {
await expect(
facet.manageAllowances(ACCOUNT_ID, await user.getAddress(), genWallet().address, 10)
).to.be.revertedWith("Invalid Token");
});

it("reverts when the token liquid balance is 0", async function () {
await wait(state.setEndowmentTokenBalance(ACCOUNT_ID, tokenFake.address, 100, 0));
await expect(
facet.manageAllowances(ACCOUNT_ID, await user.getAddress(), tokenFake.address, 10)
).to.be.revertedWith("Invalid Token");
});

it("reverts when the spender is not in allowlistedBeneficiaries of a non-mature endowment", async function () {
await expect(
facet.manageAllowances(ACCOUNT_ID, await proxyAdmin.getAddress(), tokenFake.address, 10)
Expand Down Expand Up @@ -181,22 +198,22 @@ describe("AccountsAllowance", function () {
[true, false].forEach((isMature) => {
const maturityStatus = isMature ? "mature" : "non-mature";

beforeEach(async () => {
if (!isMature) {
return;
async function setMaturityTimeIfNecessary() {
if (isMature) {
let currTime = await time.latest();
const endow = await state.getEndowmentDetails(ACCOUNT_ID);
await wait(
state.setEndowmentDetails(ACCOUNT_ID, {
...endow,
maturityTime: currTime,
})
);
}

let currTime = await time.latest();
const endow = await state.getEndowmentDetails(ACCOUNT_ID);
await wait(
state.setEndowmentDetails(ACCOUNT_ID, {
...endow,
maturityTime: currTime,
})
);
});
}

it(`passes when try to increase a valid token's allowance within range of liquid balance available for a ${maturityStatus} endowment`, async function () {
await setMaturityTimeIfNecessary();

await expect(
facet.manageAllowances(ACCOUNT_ID, await user.getAddress(), tokenFake.address, 10)
)
Expand All @@ -222,6 +239,8 @@ describe("AccountsAllowance", function () {
});

it(`passes when try to decrease an existing spender's allowance for a ${maturityStatus} endowment`, async function () {
await setMaturityTimeIfNecessary();

// now we allocate some token allowance to the user address to spend from
await wait(
state.setTokenAllowance(ACCOUNT_ID, await user.getAddress(), tokenFake.address, 10, 10)
Expand Down Expand Up @@ -255,36 +274,39 @@ describe("AccountsAllowance", function () {
});

describe("Test cases for `spendAllowance`", function () {
it("reverts when try to spend token that is invalid(zero address) or dne in allowances", async function () {
// try to spend an allowance that is invalid (Zero Address)
let rootSnapshot: SnapshotRestorer;

before(async () => {
rootSnapshot = await takeSnapshot();
await wait(
state.setTokenAllowance(ACCOUNT_ID, await user.getAddress(), tokenFake.address, 10, 10)
);
});

after(async () => {
await rootSnapshot.restore();
});

it("reverts when try to spend token that is invalid (zero address)", async function () {
await expect(
facet.spendAllowance(ACCOUNT_ID, ethers.constants.AddressZero, 10, await user.getAddress())
).to.be.revertedWith("Invalid Token");
});

// try to spend an allowance for a token that dne
it("reverts when try to spend token that dne in allowances", async function () {
await expect(
facet.spendAllowance(ACCOUNT_ID, genWallet().address, 10, await user.getAddress())
).to.be.revertedWith("Invalid Token");
});

it("reverts when try to spend zero amount of allowance", async function () {
// now we allocate some token allowance to the user address to spend from
await wait(
state.setTokenAllowance(ACCOUNT_ID, await user.getAddress(), tokenFake.address, 10, 10)
);

// try to spend zero allowance
await expect(
facet.spendAllowance(ACCOUNT_ID, tokenFake.address, 0, await user.getAddress())
).to.be.revertedWith("Zero Amount");
});

it("reverts when try to spend more allowance than is available for token", async function () {
// now we allocate some token allowance to the user address to spend from
await wait(
state.setTokenAllowance(ACCOUNT_ID, await user.getAddress(), tokenFake.address, 10, 10)
);

// try to spend more allowance than user was allocated
await expect(
facet
Expand All @@ -294,11 +316,6 @@ describe("AccountsAllowance", function () {
});

it("passes when spend less than or equal to the allowance available for token", async function () {
// now we allocate some token allowance to the user address to spend from
await wait(
state.setTokenAllowance(ACCOUNT_ID, await user.getAddress(), tokenFake.address, 10, 10)
);

// mint tokens so that the contract can transfer them to recipient
tokenFake.transfer.returns(true);

Expand Down Expand Up @@ -328,12 +345,19 @@ describe("AccountsAllowance", function () {
});

describe("upon queryAllowance", function () {
beforeEach(async () => {
let rootSnapshot: SnapshotRestorer;

before(async () => {
rootSnapshot = await takeSnapshot();
await wait(
state.setTokenAllowance(ACCOUNT_ID, await user.getAddress(), tokenFake.address, 10, 10)
);
});

after(async () => {
await rootSnapshot.restore();
});

it("returns 0 (zero) for non-existent endowment", async () => {
const nonExistentEndowId = 200;
expect(
Expand Down
Loading

0 comments on commit 3970403

Please sign in to comment.