diff --git a/contracts/package.json b/contracts/package.json index 959294772..dafef1717 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -7,7 +7,7 @@ "lib": "lib" }, "scripts": { - "test": "hardhat test", + "test": "hardhat test --parallel", "coverage": "hardhat coverage" }, "repository": { diff --git a/contracts/test/AccessControlTest.js b/contracts/test/AccessControlTest.js index e8b23ddd6..d33be811a 100644 --- a/contracts/test/AccessControlTest.js +++ b/contracts/test/AccessControlTest.js @@ -1,13 +1,8 @@ -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const testHelpers = require("../utils/testHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); +const { TestHelper: th } = require("../utils/testHelpers.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); const TroveManagerTester = artifacts.require("TroveManagerTester"); -const th = testHelpers.TestHelper; -const timeValues = testHelpers.TimeValues; - -const dec = th.dec; -const toBN = th.toBN; +const { dec, toBN } = th; /* The majority of access control tests are contained in this file. However, tests for restrictions on the Liquity admin address's capabilities during the first year are found in: @@ -17,55 +12,53 @@ test/launchSequenceTest/DuringLockupPeriodTest.js */ contract( "Access Control: Liquity functions with the caller restricted to Liquity contract(s)", async (accounts) => { - const [owner, alice, bob, carol] = accounts; + const fundedAccounts = accounts.slice(0, 10); + + const [owner, alice, bob, carol] = fundedAccounts; const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice( 997, 1000 ); - let coreContracts; + let contracts; let priceFeed; let boldToken; let sortedTroves; let troveManager; - let nameRegistry; let activePool; let stabilityPool; let defaultPool; - let functionCaller; let borrowerOperations; - before(async () => { - coreContracts = await deploymentHelper.deployLiquityCore(); - coreContracts.troveManager = await TroveManagerTester.new(); - // TODO: coreContracts = await deploymentHelper.deployBoldTokenTester(coreContracts) - - priceFeed = coreContracts.priceFeed; - boldToken = coreContracts.boldToken; - sortedTroves = coreContracts.sortedTroves; - troveManager = coreContracts.troveManager; - nameRegistry = coreContracts.nameRegistry; - activePool = coreContracts.activePool; - stabilityPool = coreContracts.stabilityPool; - defaultPool = coreContracts.defaultPool; - functionCaller = coreContracts.functionCaller; - borrowerOperations = coreContracts.borrowerOperations; - - await deploymentHelper.connectCoreContracts(coreContracts); - - - await fundAccounts(accounts.slice(0, 10), coreContracts.WETH); - - for (const account of accounts.slice(0, 10)) { - await th.openTrove(coreContracts, { - extraBoldAmount: toBN(dec(20000, 18)), - ICR: toBN(dec(2, 18)), - extraParams: { from: account }, - }); + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + mocks: { TroveManager: TroveManagerTester }, + callback: async (contracts) => { + await Promise.all(fundedAccounts.map( + (account) => th.openTrove(contracts, { + extraBoldAmount: toBN(dec(20000, 18)), + ICR: toBN(dec(2, 18)), + extraParams: { from: account }, + }) + )) } }); + beforeEach(async () => { + const result = await deployFixture(); + + contracts = result.contracts; + priceFeed = contracts.priceFeed; + boldToken = contracts.boldToken; + sortedTroves = contracts.sortedTroves; + troveManager = contracts.troveManager; + activePool = contracts.activePool; + stabilityPool = contracts.stabilityPool; + defaultPool = contracts.defaultPool; + borrowerOperations = contracts.borrowerOperations; + }); + describe("BorrowerOperations", async (accounts) => { it("moveETHGainToTrove(): reverts when called by an account that is not StabilityPool", async () => { // Attempt call from alice diff --git a/contracts/test/BorrowerOperationsTest.js b/contracts/test/BorrowerOperationsTest.js index 9949240f5..2906809d5 100644 --- a/contracts/test/BorrowerOperationsTest.js +++ b/contracts/test/BorrowerOperationsTest.js @@ -1,23 +1,16 @@ -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); -const testHelpers = require("../utils/testHelpers.js"); +const { TestHelper: th } = require("../utils/testHelpers.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); const BorrowerOperationsTester = artifacts.require( "./BorrowerOperationsTester.sol" ); const TroveManagerTester = artifacts.require("TroveManagerTester"); -const th = testHelpers.TestHelper; - -const dec = th.dec; -const toBN = th.toBN; -const mv = testHelpers.MoneyValues; -const timeValues = testHelpers.TimeValues; - -const ZERO_ADDRESS = th.ZERO_ADDRESS; -const assertRevert = th.assertRevert; +const { dec, toBN, assertRevert } = th; contract("BorrowerOperations", async (accounts) => { + const accountsToFund = accounts.slice(0, 17); + const [ owner, alice, @@ -36,21 +29,23 @@ contract("BorrowerOperations", async (accounts) => { frontEnd_1, frontEnd_2, frontEnd_3, - ] = accounts; + ] = accountsToFund; const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice(997, 1000); + let contracts + let priceFeed; let boldToken; let sortedTroves; let troveManager; let activePool; - let stabilityPool; let defaultPool; let borrowerOperations; - let lqtyToken; - let contracts; + let BOLD_GAS_COMPENSATION; + let MIN_NET_DEBT; + let BORROWING_FEE_FLOOR; const getOpenTroveBoldAmount = async (totalDebt) => th.getOpenTroveBoldAmount(contracts, totalDebt); @@ -65,57 +60,47 @@ contract("BorrowerOperations", async (accounts) => { th.getTroveEntireDebt(contracts, trove); const getTroveStake = async (trove) => th.getTroveStake(contracts, trove); - let BOLD_GAS_COMPENSATION; - let MIN_NET_DEBT; - let BORROWING_FEE_FLOOR; - - before(async () => {}); + const deployFixture = createDeployAndFundFixture({ + accounts: accountsToFund, + mocks: { + BorrowerOperations: BorrowerOperationsTester, + TroveManager: TroveManagerTester, + }, + callback: async (contracts) => { + const { borrowerOperations } = contracts; + const [ + BOLD_GAS_COMPENSATION, + MIN_NET_DEBT, + BORROWING_FEE_FLOOR, + ] = await Promise.all([ + borrowerOperations.BOLD_GAS_COMPENSATION(), + borrowerOperations.MIN_NET_DEBT(), + borrowerOperations.BORROWING_FEE_FLOOR(), + ]); + return { + BOLD_GAS_COMPENSATION, + MIN_NET_DEBT, + BORROWING_FEE_FLOOR, + } + }, + }); const testCorpus = () => { beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.borrowerOperations = await BorrowerOperationsTester.new(contracts.WETH.address); - contracts.troveManager = await TroveManagerTester.new(); - contracts = await deploymentHelper.deployBoldToken(contracts); - - await deploymentHelper.connectCoreContracts(contracts); - - priceFeed = contracts.priceFeedTestnet; - boldToken = contracts.boldToken; - sortedTroves = contracts.sortedTroves; - troveManager = contracts.troveManager; - activePool = contracts.activePool; - stabilityPool = contracts.stabilityPool; - defaultPool = contracts.defaultPool; - borrowerOperations = contracts.borrowerOperations; - hintHelpers = contracts.hintHelpers; - - BOLD_GAS_COMPENSATION = await borrowerOperations.BOLD_GAS_COMPENSATION(); - MIN_NET_DEBT = await borrowerOperations.MIN_NET_DEBT(); - BORROWING_FEE_FLOOR = await borrowerOperations.BORROWING_FEE_FLOOR(); - - await fundAccounts([ - owner, - alice, - bob, - carol, - dennis, - whale, - A, - B, - C, - D, - E, - F, - G, - H, - frontEnd_1, - frontEnd_2, - frontEnd_3, - bountyAddress, - lpRewardsAddress, - multisig, - ], contracts.WETH); + const result = await deployFixture() + + contracts = result.contracts + priceFeed = contracts.priceFeedTestnet + boldToken = contracts.boldToken + sortedTroves = contracts.sortedTroves + troveManager = contracts.troveManager + activePool = contracts.activePool + defaultPool = contracts.defaultPool + borrowerOperations = contracts.borrowerOperations + + BOLD_GAS_COMPENSATION = result.BOLD_GAS_COMPENSATION + MIN_NET_DEBT = result.MIN_NET_DEBT + BORROWING_FEE_FLOOR = result.BORROWING_FEE_FLOOR }); it("addColl(): reverts when top-up would leave trove with ICR < MCR", async () => { @@ -4401,7 +4386,7 @@ contract("BorrowerOperations", async (accounts) => { ); const liqPrice = th.toBN(dec(100,18)) - th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) + // th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) await priceFeed.setPrice(liqPrice); // Confirm we are in Normal Mode assert.isFalse(await troveManager.checkRecoveryMode(liqPrice)) @@ -4460,7 +4445,7 @@ contract("BorrowerOperations", async (accounts) => { ); const liqPrice = th.toBN(dec(100,18)) - th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) + // th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) await priceFeed.setPrice(liqPrice); // Confirm we are in Normal Mode assert.isFalse(await troveManager.checkRecoveryMode(liqPrice)) @@ -4519,7 +4504,7 @@ contract("BorrowerOperations", async (accounts) => { ); const liqPrice = th.toBN(dec(100,18)) - th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) + // th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) await priceFeed.setPrice(liqPrice); // Confirm we are in Normal Mode assert.isFalse(await troveManager.checkRecoveryMode(liqPrice)) @@ -4577,7 +4562,7 @@ contract("BorrowerOperations", async (accounts) => { ); const liqPrice = th.toBN(dec(100,18)) - th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) + // th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) await priceFeed.setPrice(liqPrice); // Confirm we are in Normal Mode assert.isFalse(await troveManager.checkRecoveryMode(liqPrice)) @@ -4636,7 +4621,7 @@ contract("BorrowerOperations", async (accounts) => { ); const liqPrice = th.toBN(dec(100,18)) - th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) + // th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) await priceFeed.setPrice(liqPrice); // Confirm we are in Normal Mode assert.isFalse(await troveManager.checkRecoveryMode(liqPrice)) @@ -4695,7 +4680,7 @@ contract("BorrowerOperations", async (accounts) => { ); const liqPrice = th.toBN(dec(100,18)) - th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) + // th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) await priceFeed.setPrice(liqPrice); // Confirm we are in Normal Mode assert.isFalse(await troveManager.checkRecoveryMode(liqPrice)) @@ -4754,7 +4739,7 @@ contract("BorrowerOperations", async (accounts) => { ); const liqPrice = th.toBN(dec(100,18)) - th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) + // th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) await priceFeed.setPrice(liqPrice); // Confirm we are in Normal Mode assert.isFalse(await troveManager.checkRecoveryMode(liqPrice)) @@ -4813,7 +4798,7 @@ contract("BorrowerOperations", async (accounts) => { ); const liqPrice = th.toBN(dec(100,18)) - th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) + // th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) await priceFeed.setPrice(liqPrice); // Confirm we are in Normal Mode assert.isFalse(await troveManager.checkRecoveryMode(liqPrice)) @@ -4872,7 +4857,7 @@ contract("BorrowerOperations", async (accounts) => { ); const liqPrice = th.toBN(dec(100,18)) - th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) + // th.logBN("Bob ICR before liq", await troveManager.getCurrentICR(bob, liqPrice)) await priceFeed.setPrice(liqPrice); // Confirm we are in Normal Mode assert.isFalse(await troveManager.checkRecoveryMode(liqPrice)) @@ -4904,9 +4889,7 @@ contract("BorrowerOperations", async (accounts) => { }); }; - describe("Test", async () => { - testCorpus(); - }); + testCorpus(); }); contract("Reset chain state", async (accounts) => {}); diff --git a/contracts/test/CollSurplusPool.js b/contracts/test/CollSurplusPool.js index 57e1d968a..6e2894833 100644 --- a/contracts/test/CollSurplusPool.js +++ b/contracts/test/CollSurplusPool.js @@ -1,51 +1,42 @@ const { time } = require('@nomicfoundation/hardhat-network-helpers'); -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const testHelpers = require("../utils/testHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); +const { + MoneyValues: mv, + TestHelper: th, + TimeValues: timeValues, +} = require("../utils/testHelpers.js"); -const th = testHelpers.TestHelper; -const dec = th.dec; -const toBN = th.toBN; -const mv = testHelpers.MoneyValues; -const timeValues = testHelpers.TimeValues; +const { dec, toBN } = th; const TroveManagerTester = artifacts.require("TroveManagerTester"); -const BoldToken = artifacts.require("BoldToken"); contract("CollSurplusPool", async (accounts) => { - const [owner, A, B, C, D, E] = accounts; + const fundedAccounts = accounts.slice(0, 6); + + const [owner, A, B, C, D, E] = fundedAccounts; const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice(997, 1000); + let contracts; let borrowerOperations; - let priceFeed; let collSurplusPool; - - let contracts; + let priceFeed; const getOpenTroveBoldAmount = async (totalDebt) => th.getOpenTroveBoldAmount(contracts, totalDebt); const openTrove = async (params) => th.openTrove(contracts, params); + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + mocks: { TroveManager: TroveManagerTester }, + }); + beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.troveManager = await TroveManagerTester.new(); - contracts.boldToken = await BoldToken.new( - contracts.troveManager.address, - contracts.stabilityPool.address, - contracts.borrowerOperations.address, - contracts.activePool.address - ); - - priceFeed = contracts.priceFeedTestnet; - collSurplusPool = contracts.collSurplusPool; + const result = await deployFixture(); + contracts = result.contracts; borrowerOperations = contracts.borrowerOperations; - - await deploymentHelper.connectCoreContracts(contracts); - await fundAccounts([ - owner, A, B, C, D, E, - bountyAddress, lpRewardsAddress, multisig - ], contracts.WETH); + collSurplusPool = contracts.collSurplusPool; + priceFeed = contracts.priceFeedTestnet; }); it("CollSurplusPool: claimColl(): Reverts if caller is not Borrower Operations", async () => { diff --git a/contracts/test/FeeArithmeticTest.js b/contracts/test/FeeArithmeticTest.js index b1e17cc3e..5ee8a5a5a 100644 --- a/contracts/test/FeeArithmeticTest.js +++ b/contracts/test/FeeArithmeticTest.js @@ -1,8 +1,8 @@ const { time } = require('@nomicfoundation/hardhat-network-helpers'); const Decimal = require("decimal.js"); -const deploymentHelper = require("../utils/deploymentHelpers.js") const { BNConverter } = require("../utils/BNConverter.js") const testHelpers = require("../utils/testHelpers.js") +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); const TroveManagerTester = artifacts.require("./TroveManagerTester.sol") const LiquityMathTester = artifacts.require("./LiquityMathTester.sol") @@ -331,17 +331,23 @@ contract('Fee arithmetic tests', async accounts => { [919877008002166000, 85, 826094891277916], ] - before(async () => { - troveManagerTester = await TroveManagerTester.new() - TroveManagerTester.setAsDeployed(troveManagerTester) + const deployFixture = createDeployAndFundFixture({ + callback: async () => { + const troveManagerTester = await TroveManagerTester.new() + TroveManagerTester.setAsDeployed(troveManagerTester) - mathTester = await LiquityMathTester.new() - LiquityMathTester.setAsDeployed(mathTester) - }) + const mathTester = await LiquityMathTester.new() + LiquityMathTester.setAsDeployed(mathTester) + + return { mathTester, troveManagerTester } + } + }); beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore() - await deploymentHelper.connectCoreContracts(contracts) + const result = await deployFixture() + contracts = result.contracts + troveManagerTester = result.troveManagerTester + mathTester = result.mathTester }) it("minutesPassedSinceLastFeeOp(): returns minutes passed for no time increase", async () => { diff --git a/contracts/test/GasCompensationTest.js b/contracts/test/GasCompensationTest.js index 2519ae4d7..5c65f77f2 100644 --- a/contracts/test/GasCompensationTest.js +++ b/contracts/test/GasCompensationTest.js @@ -1,22 +1,18 @@ -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const testHelpers = require("../utils/testHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); +const { TestHelper: th, MoneyValues: mv } = require("../utils/testHelpers.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); const TroveManagerTester = artifacts.require("./TroveManagerTester.sol"); const BorrowerOperationsTester = artifacts.require( "./BorrowerOperationsTester.sol" ); -const BoldToken = artifacts.require("BoldToken"); const ERC20 = artifacts.require("./ERC20MinterMock.sol"); -const th = testHelpers.TestHelper; -const dec = th.dec; -const toBN = th.toBN; -const mv = testHelpers.MoneyValues; -const ZERO_ADDRESS = th.ZERO_ADDRESS; +const { dec, toBN, ZERO_ADDRESS } = th; const GAS_PRICE = 10000000; contract("Gas compensation tests", async (accounts) => { + const fundedAccounts = accounts.slice(0, 16); + const [ owner, liquidator, @@ -34,20 +30,18 @@ contract("Gas compensation tests", async (accounts) => { defaulter_3, defaulter_4, whale, - ] = accounts; + ] = fundedAccounts; const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice(997, 1000); + let contracts; + let priceFeed; let boldToken; - let sortedTroves; let troveManager; - let activePool; let stabilityPool; - let defaultPool; let borrowerOperations; - let contracts; let troveManagerTester; let borrowerOperationsTester; @@ -61,6 +55,11 @@ contract("Gas compensation tests", async (accounts) => { } }; + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + mocks: { TroveManager: TroveManagerTester }, + }); + before(async () => { troveManagerTester = await TroveManagerTester.new(); const WETH = await ERC20.new("WETH", "WETH"); @@ -71,44 +70,13 @@ contract("Gas compensation tests", async (accounts) => { }); beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.troveManager = await TroveManagerTester.new(); - contracts.boldToken = await BoldToken.new( - contracts.troveManager.address, - contracts.stabilityPool.address, - contracts.borrowerOperations.address, - contracts.activePool.address - ); - + const result = await deployFixture(); + contracts = result.contracts; priceFeed = contracts.priceFeedTestnet; boldToken = contracts.boldToken; - sortedTroves = contracts.sortedTroves; troveManager = contracts.troveManager; - activePool = contracts.activePool; stabilityPool = contracts.stabilityPool; - defaultPool = contracts.defaultPool; borrowerOperations = contracts.borrowerOperations; - - await deploymentHelper.connectCoreContracts(contracts); - - await fundAccounts([ - owner, - liquidator, - alice, - bob, - carol, - dennis, - erin, - flyn, - graham, - harriet, - ida, - defaulter_1, - defaulter_2, - defaulter_3, - defaulter_4, - whale, - ], contracts.WETH); }); // --- Raw gas compensation calculations --- diff --git a/contracts/test/HintHelpers_getApproxHintTest.js b/contracts/test/HintHelpers_getApproxHintTest.js index b1e2f5847..81acfdee1 100644 --- a/contracts/test/HintHelpers_getApproxHintTest.js +++ b/contracts/test/HintHelpers_getApproxHintTest.js @@ -1,15 +1,11 @@ -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const testHelpers = require("../utils/testHelpers.js"); +const { TestHelper: th } = require("../utils/testHelpers.js"); const { fundAccounts } = require("../utils/fundAccounts.js"); -const th = testHelpers.TestHelper; const { dec, toBN } = th; -const moneyVals = testHelpers.MoneyValues; let latestRandomSeed = 31337; const TroveManagerTester = artifacts.require("TroveManagerTester"); -const BoldToken = artifacts.require("BoldToken"); const INITIAL_PRICE = dec(100, 18); @@ -26,7 +22,7 @@ contract.skip("HintHelpers", async (accounts) => { let contracts; - let numAccounts; + let numAccounts = 10; const getNetBorrowingAmount = async (debtWithFee) => th.getNetBorrowingAmount(contracts, debtWithFee); @@ -93,33 +89,24 @@ contract.skip("HintHelpers", async (accounts) => { // console.timeEnd('makeTrovesInSequence') }; - before(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.troveManager = await TroveManagerTester.new(); - contracts.boldToken = await BoldToken.new( - contracts.troveManager.address, - contracts.stabilityPool.address, - contracts.borrowerOperations.address, - contracts.activePool.address - ); - + const deployFixture = createDeployAndFundFixture({ + accounts: [owner, bountyAddress, lpRewardsAddress, multisig], + mocks: { TroveManager: TroveManagerTester }, + callback: async (contracts) => { + await priceFeed.setPrice(INITIAL_PRICE); + await makeTrovesInSequence(accounts, numAccounts); + // await makeTrovesInParallel(accounts, numAccounts) + } + }); + + beforeEach(async () => { + const result = await deployFixture(); + contracts = result.contracts; sortedTroves = contracts.sortedTroves; troveManager = contracts.troveManager; borrowerOperations = contracts.borrowerOperations; hintHelpers = contracts.hintHelpers; priceFeed = contracts.priceFeedTestnet; - - await deploymentHelper.connectCoreContracts(contracts); - - await fundAccounts([ - owner, bountyAddress, lpRewardsAddress, multisig - ], contracts.WETH); - - numAccounts = 10; - - await priceFeed.setPrice(INITIAL_PRICE); - await makeTrovesInSequence(accounts, numAccounts); - // await makeTrovesInParallel(accounts, numAccounts) }); it("setup: makes accounts with nominal ICRs increasing by 1% consecutively", async () => { diff --git a/contracts/test/PoolsTest.js b/contracts/test/PoolsTest.js index e4d35e33d..ccadd9172 100644 --- a/contracts/test/PoolsTest.js +++ b/contracts/test/PoolsTest.js @@ -4,36 +4,38 @@ const DefaultPool = artifacts.require("./DefaultPool.sol") const NonPayableSwitch = artifacts.require("./NonPayableSwitch.sol") const ERC20 = artifacts.require("./ERC20MinterMock.sol"); -const testHelpers = require("../utils/testHelpers.js") +const { loadFixture } = require("@nomicfoundation/hardhat-network-helpers"); +const { TestHelper: th } = require("../utils/testHelpers.js") -const th = testHelpers.TestHelper -const dec = th.dec +const { dec } = th const _minus_1_Ether = web3.utils.toWei('-1', 'ether') contract('StabilityPool', async accounts => { - /* mock* are EOA’s, temporarily used to call protected functions. - TODO: Replace with mock contracts, and later complete transactions from EOA - */ - let stabilityPool - let WETH const [owner, alice] = accounts; - beforeEach(async () => { - WETH = await ERC20.new("WETH", "WETH"); - stabilityPool = await StabilityPool.new(WETH.address) - const mockActivePoolAddress = (await NonPayableSwitch.new()).address - const dumbContractAddress = (await NonPayableSwitch.new()).address + const deployFixture = async () => { + /* mock* are EOA’s, temporarily used to call protected functions. + TODO: Replace with mock contracts, and later complete transactions from EOA + */ + const WETH = await ERC20.new("WETH", "WETH"); + const stabilityPool = await StabilityPool.new(WETH.address) + const { address: mockActivePoolAddress } = await NonPayableSwitch.new() + const { address: dumbContractAddress } = await NonPayableSwitch.new() await stabilityPool.setAddresses(dumbContractAddress, dumbContractAddress, mockActivePoolAddress, dumbContractAddress, dumbContractAddress, dumbContractAddress) - }) + + return stabilityPool + } it('getETHBalance(): gets the recorded ETH balance', async () => { + const stabilityPool = await loadFixture(deployFixture) const recordedETHBalance = await stabilityPool.getETHBalance() assert.equal(recordedETHBalance, 0) }) it('getTotalBoldDeposits(): gets the recorded BOLD balance', async () => { + const stabilityPool = await loadFixture(deployFixture) const recordedETHBalance = await stabilityPool.getTotalBoldDeposits() assert.equal(recordedETHBalance, 0) }) @@ -44,13 +46,24 @@ contract('ActivePool', async accounts => { let activePool, mockBorrowerOperations, mockTroveManager, WETH const [owner, alice] = accounts; - beforeEach(async () => { - WETH = await ERC20.new("WETH", "WETH"); - activePool = await ActivePool.new(WETH.address) - mockBorrowerOperations = await NonPayableSwitch.new() - mockTroveManager = await NonPayableSwitch.new() - const dumbContractAddress = (await NonPayableSwitch.new()).address + + const deployFixture = async () => { + const WETH = await ERC20.new("WETH", "WETH"); + const activePool = await ActivePool.new(WETH.address) + const mockBorrowerOperations = await NonPayableSwitch.new() + const mockTroveManager = await NonPayableSwitch.new() + const { address: dumbContractAddress } = await NonPayableSwitch.new() await activePool.setAddresses(mockBorrowerOperations.address, mockTroveManager.address, dumbContractAddress, dumbContractAddress, dumbContractAddress, dumbContractAddress) + + return { activePool, mockBorrowerOperations, mockTroveManager, WETH } + } + + beforeEach(async () => { + const result = await loadFixture(deployFixture) + WETH = result.WETH + activePool = result.activePool + mockBorrowerOperations = result.mockBorrowerOperations + mockTroveManager = result.mockTroveManager }) it('getETHBalance(): gets the recorded ETH balance', async () => { @@ -116,7 +129,7 @@ contract('ActivePool', async accounts => { assert.equal(activePool_BalanceBeforeTx, dec(2, 'ether')) // send ether from pool to alice - th.logBN("eth bal", await WETH.balanceOf(activePool.address)) + // th.logBN("eth bal", await WETH.balanceOf(activePool.address)) //await activePool.sendETH(alice, dec(1, 'ether'), { from: mockBorrowerOperationsAddress }) const sendETHData = th.getTransactionData('sendETH(address,uint256)', [alice, web3.utils.toHex(dec(1, 'ether'))]) const tx2 = await mockBorrowerOperations.forward(activePool.address, sendETHData, { from: owner }) @@ -134,16 +147,27 @@ contract('ActivePool', async accounts => { contract('DefaultPool', async accounts => { - let defaultPool, mockTroveManager, mockActivePool, WETH + let defaultPool, mockTroveManager, mockActivePool, WETH const [owner, alice] = accounts; - beforeEach(async () => { - WETH = await ERC20.new("WETH", "WETH"); - defaultPool = await DefaultPool.new(WETH.address) - mockTroveManager = await NonPayableSwitch.new() - mockActivePool = await NonPayableSwitch.new() + + const deployFixture = async () => { + const WETH = await ERC20.new("WETH", "WETH"); + const defaultPool = await DefaultPool.new(WETH.address) + const mockTroveManager = await NonPayableSwitch.new() + const mockActivePool = await NonPayableSwitch.new() await mockActivePool.setETH(WETH.address) await defaultPool.setAddresses(mockTroveManager.address, mockActivePool.address) + + return { defaultPool, mockTroveManager, mockActivePool, WETH } + } + + beforeEach(async () => { + const result = await loadFixture(deployFixture) + WETH = result.WETH + defaultPool = result.defaultPool + mockTroveManager = result.mockTroveManager + mockActivePool = result.mockActivePool }) it('getETHBalance(): gets the recorded BOLD balance', async () => { diff --git a/contracts/test/SP_P_TruncationTest.js b/contracts/test/SP_P_TruncationTest.js index f98bdb227..f1b90f640 100644 --- a/contracts/test/SP_P_TruncationTest.js +++ b/contracts/test/SP_P_TruncationTest.js @@ -1,12 +1,7 @@ -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const testHelpers = require("../utils/testHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); +const { TestHelper: th } = require("../utils/testHelpers.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); -const th = testHelpers.TestHelper; -const timeValues = testHelpers.TimeValues; -const dec = th.dec; -const toBN = th.toBN; -const getDifference = th.getDifference; +const { dec } = th; const TroveManagerTester = artifacts.require("TroveManagerTester"); const BoldToken = artifacts.require("BoldToken"); @@ -14,7 +9,9 @@ const BoldToken = artifacts.require("BoldToken"); const GAS_PRICE = 10000000; contract("StabilityPool Scale Factor issue tests", async (accounts) => { - const [owner, whale, A, B, C, D, E, F, F1, F2, F3] = accounts; + const fundedAccounts = accounts.slice(0, 11); + + const [owner, whale, A, B, C, D, E, F, F1, F2, F3] = fundedAccounts; const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice(997, 1000); @@ -35,32 +32,28 @@ contract("StabilityPool Scale Factor issue tests", async (accounts) => { const getBoldAmountForDesiredDebt = async (desiredDebt) => (await getOpenTroveBoldAmount(dec(desiredDebt, 18))); - describe("Scale Factor issue tests", async () => { - beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.troveManager = await TroveManagerTester.new(); - contracts.boldToken = await BoldToken.new( - contracts.troveManager.address, - contracts.stabilityPool.address, - contracts.borrowerOperations.address, - contracts.activePool.address - ); - - priceFeed = contracts.priceFeedTestnet; - boldToken = contracts.boldToken; - stabilityPool = contracts.stabilityPool; - sortedTroves = contracts.sortedTroves; - troveManager = contracts.troveManager; - stabilityPool = contracts.stabilityPool; - borrowerOperations = contracts.borrowerOperations; - - await deploymentHelper.connectCoreContracts(contracts); - - await fundAccounts([owner, whale, A, B, C, D, E, F, F1, F2, F3], contracts.WETH); + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + callback: async (contracts) => { + await contracts.priceFeed.setPrice(dec(200, 18)); + }, + mocks: { + TroveManager: TroveManagerTester, + } + }); - await priceFeed.setPrice(dec(200, 18)); - }); + beforeEach(async () => { + const result = await deployFixture(); + contracts = result.contracts; + priceFeed = contracts.priceFeed; + boldToken = contracts.boldToken; + stabilityPool = contracts.stabilityPool; + sortedTroves = contracts.sortedTroves; + troveManager = contracts.troveManager; + borrowerOperations = contracts.borrowerOperations; + }); + describe("Scale Factor issue tests", async () => { it.skip("1. Liquidation succeeds after P reduced to 1", async () => { // Whale opens Trove with 100k ETH and sends 50k Bold to A await th.openTroveWrapper(contracts, diff --git a/contracts/test/SortedTrovesTest.js b/contracts/test/SortedTrovesTest.js index 8569a74c6..f5aaacc92 100644 --- a/contracts/test/SortedTrovesTest.js +++ b/contracts/test/SortedTrovesTest.js @@ -1,17 +1,15 @@ -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); -const testHelpers = require("../utils/testHelpers.js"); +const { TestHelper: th } = require("../utils/testHelpers.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); const SortedTroves = artifacts.require("SortedTroves"); const SortedTrovesTester = artifacts.require("SortedTrovesTester"); const TroveManagerTester = artifacts.require("TroveManagerTester"); -const BoldToken = artifacts.require("BoldToken"); -const th = testHelpers.TestHelper; -const dec = th.dec; -const toBN = th.toBN; +const { dec, toBN } = th; contract("SortedTroves", async (accounts) => { + const fundedAccounts = accounts.slice(0, 28); + const assertSortedListIsOrdered = async (contracts) => { const price = await contracts.priceFeedTestnet.getPrice(); @@ -23,14 +21,14 @@ contract("SortedTroves", async (accounts) => { const troveICR = await contracts.troveManager.getCurrentICR(trove, price); const prevTroveICR = await contracts.troveManager.getCurrentICR( prevTrove, - price + price, ); assert.isTrue(prevTroveICR.gte(troveICR)); const troveNICR = await contracts.troveManager.getNominalICR(trove); const prevTroveNICR = await contracts.troveManager.getNominalICR( - prevTrove + prevTrove, ); assert.isTrue(prevTroveNICR.gte(troveNICR)); @@ -66,7 +64,7 @@ contract("SortedTroves", async (accounts) => { I, J, whale, - ] = accounts; + ] = fundedAccounts; let priceFeed; let sortedTroves; @@ -78,60 +76,22 @@ contract("SortedTroves", async (accounts) => { let contracts; + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + mocks: { TroveManager: TroveManagerTester }, + }); + const openTrove = async (params) => th.openTrove(contracts, params); describe("SortedTroves", () => { beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.troveManager = await TroveManagerTester.new(); - contracts.boldToken = await BoldToken.new( - contracts.troveManager.address, - contracts.stabilityPool.address, - contracts.borrowerOperations.address, - contracts.activePool.address - ); - + const result = await deployFixture(); + contracts = result.contracts; priceFeed = contracts.priceFeedTestnet; sortedTroves = contracts.sortedTroves; troveManager = contracts.troveManager; borrowerOperations = contracts.borrowerOperations; boldToken = contracts.boldToken; - - await deploymentHelper.connectCoreContracts(contracts); - - await fundAccounts( - [ - owner, - alice, - bob, - carol, - dennis, - erin, - flyn, - graham, - harriet, - ida, - defaulter_1, - defaulter_2, - defaulter_3, - defaulter_4, - A, - B, - C, - D, - E, - F, - G, - H, - I, - J, - whale, - bountyAddress, - lpRewardsAddress, - multisig, - ], - contracts.WETH - ); }); it("contains(): returns true for addresses that have opened troves", async () => { @@ -305,11 +265,23 @@ contract("SortedTroves", async (accounts) => { ICR: toBN(dec(500, 18)), extraParams: { from: whale }, }); - const { troveId: ATroveId } = await openTrove({ ICR: toBN(dec(10, 18)), extraParams: { from: A, annualInterestRate: toBN(dec(1,18))}}); // 100% interest rate - const { troveId: BTroveId } = await openTrove({ ICR: toBN(dec(5, 18)), extraParams: { from: B , annualInterestRate: toBN(dec(75, 16))}}); // 75% interest rate - const { troveId: CTroveId } = await openTrove({ ICR: toBN(dec(250, 16)), extraParams: { from: C, annualInterestRate: toBN(dec(5, 17))}}); // 50% interest rate - await openTrove({ ICR: toBN(dec(166, 16)), extraParams: { from: D, annualInterestRate: toBN(dec(25,16))}}); // 25% interest rate - const { troveId: ETroveId } = await openTrove({ ICR: toBN(dec(125, 16)), extraParams: { from: E, annualInterestRate: toBN(dec(1, 16))}}); // 1% interest rate + const { troveId: ATroveId } = await openTrove({ + ICR: toBN(dec(10, 18)), + extraParams: { from: A, annualInterestRate: toBN(dec(1, 18)) }, + }); // 100% interest rate + const { troveId: BTroveId } = await openTrove({ + ICR: toBN(dec(5, 18)), + extraParams: { from: B, annualInterestRate: toBN(dec(75, 16)) }, + }); // 75% interest rate + const { troveId: CTroveId } = await openTrove({ + ICR: toBN(dec(250, 16)), + extraParams: { from: C, annualInterestRate: toBN(dec(5, 17)) }, + }); // 50% interest rate + await openTrove({ ICR: toBN(dec(166, 16)), extraParams: { from: D, annualInterestRate: toBN(dec(25, 16)) } }); // 25% interest rate + const { troveId: ETroveId } = await openTrove({ + ICR: toBN(dec(125, 16)), + extraParams: { from: E, annualInterestRate: toBN(dec(1, 16)) }, + }); // 1% interest rate // Expect a trove with 60% interest rate to be inserted between B and C const targetAnnualIRate = toBN(dec(60, 16)); @@ -332,7 +304,7 @@ contract("SortedTroves", async (accounts) => { }); describe("SortedTroves with mock dependencies", () => { - let sortedTrovesTester; + let sortedTrovesTester; beforeEach(async () => { sortedTroves = await SortedTroves.new(); @@ -345,7 +317,7 @@ contract("SortedTroves", async (accounts) => { beforeEach("set addresses", async () => { await sortedTroves.setAddresses( sortedTrovesTester.address, - sortedTrovesTester.address + sortedTrovesTester.address, ); }); @@ -353,28 +325,33 @@ contract("SortedTroves", async (accounts) => { await sortedTrovesTester.insert(alice, 1, alice, alice); await th.assertRevert( sortedTrovesTester.insert(alice, 1, alice, alice), - "SortedTroves: List already contains the node" + "SortedTroves: List already contains the node", ); }); it("insert(): fails if id is zero", async () => { await th.assertRevert( sortedTrovesTester.insert(toBN(0), 1, alice, alice), - "SortedTroves: Id cannot be zero" + "SortedTroves: Id cannot be zero", ); }); it("remove(): fails if id is not in the list", async () => { await th.assertRevert( sortedTrovesTester.remove(th.addressToTroveId(alice)), - "SortedTroves: List does not contain the id" + "SortedTroves: List does not contain the id", ); }); it("reInsert(): fails if list doesn’t contain the node", async () => { await th.assertRevert( - sortedTrovesTester.reInsert(th.addressToTroveId(alice), 1, th.addressToTroveId(alice), th.addressToTroveId(alice)), - "SortedTroves: List does not contain the id" + sortedTrovesTester.reInsert( + th.addressToTroveId(alice), + 1, + th.addressToTroveId(alice), + th.addressToTroveId(alice), + ), + "SortedTroves: List does not contain the id", ); }); diff --git a/contracts/test/StabilityPoolTest.js b/contracts/test/StabilityPoolTest.js index 9f8cfdfae..d19f4840e 100644 --- a/contracts/test/StabilityPoolTest.js +++ b/contracts/test/StabilityPoolTest.js @@ -1,15 +1,14 @@ const { time } = require('@nomicfoundation/hardhat-network-helpers'); -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const testHelpers = require("../utils/testHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); -const th = testHelpers.TestHelper; -const dec = th.dec; -const toBN = th.toBN; -const mv = testHelpers.MoneyValues; -const timeValues = testHelpers.TimeValues; +const { + MoneyValues: mv, + TestHelper: th, + TimeValues: timeValues, +} = require("../utils/testHelpers.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); + +const { dec, toBN } = th; const TroveManagerTester = artifacts.require("TroveManagerTester"); -const BoldToken = artifacts.require("BoldToken"); const NonPayableSwitch = artifacts.require("NonPayableSwitch.sol"); const ZERO = toBN("0"); @@ -23,6 +22,8 @@ const getFrontEndTag = async (stabilityPool, depositor) => { }; contract("StabilityPool", async (accounts) => { + const fundedAccounts = accounts.slice(0, 20); + const [ owner, defaulter_1, @@ -44,11 +45,12 @@ contract("StabilityPool", async (accounts) => { frontEnd_1, frontEnd_2, frontEnd_3, - ] = accounts; + ] = fundedAccounts; const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice(997, 1000); const frontEnds = [frontEnd_1, frontEnd_2, frontEnd_3]; + let contracts; let priceFeed; let boldToken; @@ -59,29 +61,21 @@ contract("StabilityPool", async (accounts) => { let defaultPool; let borrowerOperations; - let gasPriceInWei; - const getOpenTroveBoldAmount = async (totalDebt) => th.getOpenTroveBoldAmount(contracts, totalDebt); const openTrove = async (params) => th.openTrove(contracts, params); const assertRevert = th.assertRevert; - describe("Stability Pool Mechanisms", async () => { - before(async () => { - gasPriceInWei = await web3.eth.getGasPrice(); - }); + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts.slice(0, 20), + mocks: { TroveManager: TroveManagerTester } + }); + describe("Stability Pool Mechanisms", async () => { beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.troveManager = await TroveManagerTester.new(); - contracts.boldToken = await BoldToken.new( - contracts.troveManager.address, - contracts.stabilityPool.address, - contracts.borrowerOperations.address, - contracts.activePool.address - ); - - priceFeed = contracts.priceFeedTestnet; + const result = await deployFixture() + contracts = result.contracts; + priceFeed = contracts.priceFeed; boldToken = contracts.boldToken; sortedTroves = contracts.sortedTroves; troveManager = contracts.troveManager; @@ -89,32 +83,6 @@ contract("StabilityPool", async (accounts) => { stabilityPool = contracts.stabilityPool; defaultPool = contracts.defaultPool; borrowerOperations = contracts.borrowerOperations; - hintHelpers = contracts.hintHelpers; - - await deploymentHelper.connectCoreContracts(contracts); - - await fundAccounts([ - owner, - defaulter_1, - defaulter_2, - defaulter_3, - whale, - alice, - bob, - carol, - dennis, - erin, - flyn, - A, - B, - C, - D, - E, - F, - frontEnd_1, - frontEnd_2, - frontEnd_3, - ], contracts.WETH); }); // --- provideToSP() --- diff --git a/contracts/test/StabilityPool_SPWithdrawalTest.js b/contracts/test/StabilityPool_SPWithdrawalTest.js index 8f98f8c89..1a3a719f7 100644 --- a/contracts/test/StabilityPool_SPWithdrawalTest.js +++ b/contracts/test/StabilityPool_SPWithdrawalTest.js @@ -1,14 +1,15 @@ -const deploymentHelper = require("../utils/deploymentHelpers.js") const testHelpers = require("../utils/testHelpers.js") -const { fundAccounts } = require("../utils/fundAccounts.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); const TroveManagerTester = artifacts.require("./TroveManagerTester.sol") const { dec, toBN } = testHelpers.TestHelper const th = testHelpers.TestHelper contract('StabilityPool - Withdrawal of stability deposit - Reward calculations', async accounts => { + const fundedAccounts = accounts.slice(0, 22); - const [owner, + const [ + owner, defaulter_1, defaulter_2, defaulter_3, @@ -31,7 +32,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' D, E, F - ] = accounts; + ] = fundedAccounts; const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice(997, 1000) @@ -39,66 +40,27 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' let priceFeed let boldToken - let sortedTroves let troveManager - let activePool let stabilityPool - let defaultPool - let borrowerOperations - - let gasPriceInWei const ZERO_ADDRESS = th.ZERO_ADDRESS const getOpenTroveBoldAmount = async (totalDebt) => th.getOpenTroveBoldAmount(contracts, totalDebt) - describe("Stability Pool Withdrawal", async () => { + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + mocks: { TroveManager: TroveManagerTester } + }); - before(async () => { - gasPriceInWei = await web3.eth.getGasPrice() - }) + describe("Stability Pool Withdrawal", async () => { beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore() - contracts.troveManager = await TroveManagerTester.new() - contracts = await deploymentHelper.deployBoldToken(contracts) - + const result = await deployFixture() + contracts = result.contracts priceFeed = contracts.priceFeedTestnet boldToken = contracts.boldToken - sortedTroves = contracts.sortedTroves troveManager = contracts.troveManager - activePool = contracts.activePool stabilityPool = contracts.stabilityPool - defaultPool = contracts.defaultPool - borrowerOperations = contracts.borrowerOperations - - await deploymentHelper.connectCoreContracts(contracts) - - await fundAccounts([ - owner, - defaulter_1, - defaulter_2, - defaulter_3, - defaulter_4, - defaulter_5, - defaulter_6, - whale, - // whale_2, - alice, - bob, - carol, - dennis, - erin, - flyn, - graham, - harriet, - A, - B, - C, - D, - E, - F - ], contracts.WETH); }) // --- Compounding tests --- @@ -501,7 +463,6 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' const carol_ETHWithdrawn = th.getEventArgByName(txC, 'ETHGainWithdrawn', '_ETH').toString() const dennis_ETHWithdrawn = th.getEventArgByName(txD, 'ETHGainWithdrawn', '_ETH').toString() - console.log() assert.isAtMost(th.getDifference((await boldToken.balanceOf(alice)).toString(), '1666666666666666666666'), 100000) assert.isAtMost(th.getDifference((await boldToken.balanceOf(bob)).toString(), '1666666666666666666666'), 100000) assert.isAtMost(th.getDifference((await boldToken.balanceOf(carol)).toString(), '1666666666666666666666'), 100000) @@ -1490,7 +1451,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' assert.isTrue(txL1.receipt.status) const aliceDeposit = (await stabilityPool.getCompoundedBoldDeposit(alice)).toString() - console.log(`alice deposit: ${aliceDeposit}`) + // console.log(`alice deposit: ${aliceDeposit}`) assert.equal(aliceDeposit, 0) }) diff --git a/contracts/test/StabilityPool_SPWithdrawalToCDPTest.js b/contracts/test/StabilityPool_SPWithdrawalToCDPTest.js index e0f057e32..93e489ccf 100644 --- a/contracts/test/StabilityPool_SPWithdrawalToCDPTest.js +++ b/contracts/test/StabilityPool_SPWithdrawalToCDPTest.js @@ -1,14 +1,15 @@ -const deploymentHelper = require("../utils/deploymentHelpers.js") const testHelpers = require("../utils/testHelpers.js") -const { fundAccounts } = require("../utils/fundAccounts.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); const TroveManagerTester = artifacts.require("./TroveManagerTester.sol") const { dec, toBN } = testHelpers.TestHelper const th = testHelpers.TestHelper contract('StabilityPool - Withdrawal of stability deposit - Reward calculations', async accounts => { + const fundedAccounts = accounts.slice(0, 22); - const [owner, + const [ + owner, defaulter_1, defaulter_2, defaulter_3, @@ -31,7 +32,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' D, E, F - ] = accounts; + ] = fundedAccounts; const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice(997, 1000) @@ -39,12 +40,8 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' let priceFeed let boldToken - let sortedTroves let troveManager - let activePool let stabilityPool - let defaultPool - let borrowerOperations let gasPriceInWei @@ -52,6 +49,11 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' const getOpenTroveBoldAmount = async (totalDebt) => th.getOpenTroveBoldAmount(contracts, totalDebt) + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + mocks: { TroveManager: TroveManagerTester } + }); + describe("Stability Pool Withdrawal", async () => { before(async () => { @@ -59,46 +61,12 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' }) beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore() - contracts.troveManager = await TroveManagerTester.new() - contracts = await deploymentHelper.deployBoldToken(contracts) - + const result = await deployFixture() + contracts = result.contracts priceFeed = contracts.priceFeedTestnet boldToken = contracts.boldToken - sortedTroves = contracts.sortedTroves troveManager = contracts.troveManager - activePool = contracts.activePool stabilityPool = contracts.stabilityPool - defaultPool = contracts.defaultPool - borrowerOperations = contracts.borrowerOperations - - await deploymentHelper.connectCoreContracts(contracts) - - await fundAccounts([ - owner, - defaulter_1, - defaulter_2, - defaulter_3, - defaulter_4, - defaulter_5, - defaulter_6, - whale, - // whale_2, - alice, - bob, - carol, - dennis, - erin, - flyn, - graham, - harriet, - A, - B, - C, - D, - E, - F - ], contracts.WETH); }) // --- Compounding tests --- @@ -547,7 +515,6 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' const carol_ETHWithdrawn = th.getEventArgByName(txC, 'ETHGainWithdrawn', '_ETH').toString() const dennis_ETHWithdrawn = th.getEventArgByName(txD, 'ETHGainWithdrawn', '_ETH').toString() - console.log() assert.isAtMost(th.getDifference((await stabilityPool.getCompoundedBoldDeposit(alice)).toString(), '1666666666666666666666'), 100000) assert.isAtMost(th.getDifference((await stabilityPool.getCompoundedBoldDeposit(bob)).toString(), '1666666666666666666666'), 100000) assert.isAtMost(th.getDifference((await stabilityPool.getCompoundedBoldDeposit(carol)).toString(), '1666666666666666666666'), 100000) @@ -1624,7 +1591,7 @@ contract('StabilityPool - Withdrawal of stability deposit - Reward calculations' assert.isTrue(txL1.receipt.status) const aliceDeposit = (await stabilityPool.getCompoundedBoldDeposit(alice)).toString() - console.log(`alice deposit: ${aliceDeposit}`) + // console.log(`alice deposit: ${aliceDeposit}`) assert.equal(aliceDeposit, 0) }) diff --git a/contracts/test/TroveManagerTest.js b/contracts/test/TroveManagerTest.js index b63058df1..4cedbf19a 100644 --- a/contracts/test/TroveManagerTest.js +++ b/contracts/test/TroveManagerTest.js @@ -1,16 +1,18 @@ const { time } = require('@nomicfoundation/hardhat-network-helpers'); -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const testHelpers = require("../utils/testHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); +const { + MoneyValues: mv, + TestHelper: th, + TimeValues: timeValues, +} = require("../utils/testHelpers.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); + const TroveManagerTester = artifacts.require("./TroveManagerTester.sol"); -const BoldToken = artifacts.require("./BoldToken.sol"); -const th = testHelpers.TestHelper; -const dec = th.dec; -const toBN = th.toBN; -const assertRevert = th.assertRevert; -const mv = testHelpers.MoneyValues; -const timeValues = testHelpers.TimeValues; +const { + assertRevert, + dec, + toBN, +} = th; const GAS_PRICE = 10000000; @@ -22,6 +24,8 @@ const GAS_PRICE = 10000000; * */ contract("TroveManager", async (accounts) => { + const fundedAccounts = accounts.slice(0, 20); + const _18_zeros = "000000000000000000"; const ZERO_ADDRESS = th.ZERO_ADDRESS; @@ -46,78 +50,41 @@ contract("TroveManager", async (accounts) => { C, D, E, - ] = accounts; - - const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice(997, 1000); - - let priceFeed; - let boldToken; - let sortedTroves; - let troveManager; - let activePool; - let stabilityPool; - let collSurplusPool; - let defaultPool; - let borrowerOperations; - let hintHelpers; - - let contracts; - - const getOpenTroveTotalDebt = async (boldAmount) => - th.getOpenTroveTotalDebt(contracts, boldAmount); - const getOpenTroveBoldAmount = async (totalDebt) => - th.getOpenTroveBoldAmount(contracts, totalDebt); - const getActualDebtFromComposite = async (compositeDebt) => - th.getActualDebtFromComposite(compositeDebt, contracts); - const getNetBorrowingAmount = async (debtWithFee) => - th.getNetBorrowingAmount(contracts, debtWithFee); + ] = fundedAccounts; + + let contracts + + let priceFeed + let boldToken + let sortedTroves + let troveManager + let activePool + let stabilityPool + let defaultPool + let borrowerOperations + + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + mocks: { TroveManager: TroveManagerTester, } + }); + const getOpenTroveTotalDebt = async (boldAmount) => th.getOpenTroveTotalDebt(contracts, boldAmount); + const getOpenTroveBoldAmount = async (totalDebt) => th.getOpenTroveBoldAmount(contracts, totalDebt); + const getActualDebtFromComposite = async (compositeDebt) => th.getActualDebtFromComposite(compositeDebt, contracts); + const getNetBorrowingAmount = async (debtWithFee) => th.getNetBorrowingAmount(contracts, debtWithFee); const openTrove = async (params) => th.openTrove(contracts, params); const withdrawBold = async (params) => th.withdrawBold(contracts, params); beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.troveManager = await TroveManagerTester.new(); - contracts.boldToken = await BoldToken.new( - contracts.troveManager.address, - contracts.stabilityPool.address, - contracts.borrowerOperations.address, - contracts.activePool.address - ) - - priceFeed = contracts.priceFeedTestnet; - boldToken = contracts.boldToken; - sortedTroves = contracts.sortedTroves; - troveManager = contracts.troveManager; - activePool = contracts.activePool; - stabilityPool = contracts.stabilityPool; - defaultPool = contracts.defaultPool; - collSurplusPool = contracts.collSurplusPool; - borrowerOperations = contracts.borrowerOperations; - hintHelpers = contracts.hintHelpers; - - await deploymentHelper.connectCoreContracts(contracts); - await fundAccounts([ - owner, - alice, - bob, - carol, - dennis, - erin, - flyn, - graham, - harriet, - ida, - defaulter_1, - defaulter_2, - defaulter_3, - defaulter_4, - whale, - A, - B, - C, - D, - E, - ], contracts.WETH); + const result = await deployFixture() + contracts = result.contracts + priceFeed = contracts.priceFeedTestnet + boldToken = contracts.boldToken + sortedTroves = contracts.sortedTroves + troveManager = contracts.troveManager + activePool = contracts.activePool + stabilityPool = contracts.stabilityPool + defaultPool = contracts.defaultPool + borrowerOperations = contracts.borrowerOperations }); it("liquidate(): closes a Trove that has ICR < MCR", async () => { @@ -436,7 +403,7 @@ contract("TroveManager", async (accounts) => { ); assert.isTrue(await sortedTroves.contains(bobTroveId)); - th.logBN("bob icr", await troveManager.getCurrentICR(bob, await priceFeed.getPrice())); + // th.logBN("bob icr", await troveManager.getCurrentICR(bob, await priceFeed.getPrice())); // Bob now withdraws Bold, bringing his ICR to 1.11 const { increasedTotalDebt: B_increasedTotalDebt } = await withdrawBold({ ICR: toBN(dec(111, 16)), @@ -1618,7 +1585,7 @@ contract("TroveManager", async (accounts) => { totalCollNonDefaulters .add(th.applyLiquidationFee(totalCollDefaulters)) .mul(price) - .div(totalDebt) + .div(totalDebt), ), 1000 ); diff --git a/contracts/test/TroveManager_LiquidationRewardsTest.js b/contracts/test/TroveManager_LiquidationRewardsTest.js index 80e4f414c..7e217e195 100644 --- a/contracts/test/TroveManager_LiquidationRewardsTest.js +++ b/contracts/test/TroveManager_LiquidationRewardsTest.js @@ -1,19 +1,14 @@ -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const testHelpers = require("../utils/testHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); - -const th = testHelpers.TestHelper; -const dec = th.dec; -const toBN = th.toBN; -const getDifference = th.getDifference; -const mv = testHelpers.MoneyValues; +const { TestHelper: th } = require("../utils/testHelpers.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); const TroveManagerTester = artifacts.require("TroveManagerTester"); -const BoldToken = artifacts.require("BoldToken"); -contract( - "TroveManager - Redistribution reward calculations", +const { dec, getDifference, toBN } = th; + +contract( "TroveManager - Redistribution reward calculations", async (accounts) => { + const fundedAccounts = accounts.slice(0, 20); + const [ owner, alice, @@ -35,25 +30,18 @@ contract( defaulter_2, defaulter_3, defaulter_4, - ] = accounts; - - const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice( - 997, - 1000 - ); - - let priceFeed; - let boldToken; - let sortedTroves; - let troveManager; - let nameRegistry; - let activePool; - let stabilityPool; - let defaultPool; - let functionCaller; - let borrowerOperations; - - let contracts; + ] = fundedAccounts; + + let contracts + + let priceFeed + let boldToken + let sortedTroves + let troveManager + let activePool + let stabilityPool + let defaultPool + let borrowerOperations const getOpenTroveBoldAmount = async (totalDebt) => th.getOpenTroveBoldAmount(contracts, totalDebt); @@ -61,51 +49,25 @@ contract( th.getNetBorrowingAmount(contracts, debtWithFee); const openTrove = async (params) => th.openTrove(contracts, params); + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + mocks: { + TroveManager: TroveManagerTester, + } + }); + beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.troveManager = await TroveManagerTester.new(); - contracts.boldToken = await BoldToken.new( - contracts.troveManager.address, - contracts.stabilityPool.address, - contracts.borrowerOperations.address, - contracts.activePool.address - ); - - priceFeed = contracts.priceFeedTestnet; - boldToken = contracts.boldToken; - sortedTroves = contracts.sortedTroves; - troveManager = contracts.troveManager; - nameRegistry = contracts.nameRegistry; - activePool = contracts.activePool; - stabilityPool = contracts.stabilityPool; - defaultPool = contracts.defaultPool; - functionCaller = contracts.functionCaller; - borrowerOperations = contracts.borrowerOperations; - - await deploymentHelper.connectCoreContracts(contracts); - - await fundAccounts([ - owner, - alice, - bob, - carol, - dennis, - erin, - freddy, - greta, - harry, - ida, - A, - B, - C, - D, - E, - whale, - defaulter_1, - defaulter_2, - defaulter_3, - defaulter_4, - ], contracts.WETH); + const result = await deployFixture(); + + contracts = result.contracts + priceFeed = contracts.priceFeed + boldToken = contracts.boldToken + sortedTroves = contracts.sortedTroves + troveManager = contracts.troveManager + activePool = contracts.activePool + stabilityPool = contracts.stabilityPool + defaultPool = contracts.defaultPool + borrowerOperations = contracts.borrowerOperations }); it("redistribution: A, B Open. B Liquidated. C, D Open. D Liquidated. Distributes correct rewards", async () => { diff --git a/contracts/test/TroveManager_RecoveryModeTest.js b/contracts/test/TroveManager_RecoveryModeTest.js index 7669b760e..71fff691c 100644 --- a/contracts/test/TroveManager_RecoveryModeTest.js +++ b/contracts/test/TroveManager_RecoveryModeTest.js @@ -1,19 +1,18 @@ const { time } = require('@nomicfoundation/hardhat-network-helpers'); -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const testHelpers = require("../utils/testHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); +const { + MoneyValues: mv, + TestHelper: th, + TimeValues: timeValues, +} = require("../utils/testHelpers.js"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); -const th = testHelpers.TestHelper; -const dec = th.dec; -const toBN = th.toBN; -const assertRevert = th.assertRevert; -const mv = testHelpers.MoneyValues; -const timeValues = testHelpers.TimeValues; +const { assertRevert, dec, toBN } = th; const TroveManagerTester = artifacts.require("./TroveManagerTester"); -const BoldToken = artifacts.require("./BoldToken.sol"); contract.skip("TroveManager - in Recovery Mode", async (accounts) => { + const fundedAccounts = accounts.slice(0, 24); + const _1_Ether = web3.utils.toWei("1", "ether"); const _2_Ether = web3.utils.toWei("2", "ether"); const _3_Ether = web3.utils.toWei("3", "ether"); @@ -27,7 +26,6 @@ contract.skip("TroveManager - in Recovery Mode", async (accounts) => { const _25_Ether = web3.utils.toWei("25", "ether"); const _30_Ether = web3.utils.toWei("30", "ether"); - const ZERO_ADDRESS = th.ZERO_ADDRESS; const [ owner, alice, @@ -53,7 +51,7 @@ contract.skip("TroveManager - in Recovery Mode", async (accounts) => { G, H, I, - ] = accounts; + ] = fundedAccounts; const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice(997, 1000); @@ -76,16 +74,14 @@ contract.skip("TroveManager - in Recovery Mode", async (accounts) => { th.getNetBorrowingAmount(contracts, debtWithFee); const openTrove = async (params) => th.openTrove(contracts, params); + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + mocks: { TroveManager: TroveManagerTester }, + }); + beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.troveManager = await TroveManagerTester.new(); - contracts.boldToken = await BoldToken.new( - contracts.troveManager.address, - contracts.stabilityPool.address, - contracts.borrowerOperations.address, - contracts.activePool.address - ); - + const result = await deployFixture(); + contracts = result.contracts; priceFeed = contracts.priceFeedTestnet; boldToken = contracts.boldToken; sortedTroves = contracts.sortedTroves; @@ -96,35 +92,6 @@ contract.skip("TroveManager - in Recovery Mode", async (accounts) => { functionCaller = contracts.functionCaller; borrowerOperations = contracts.borrowerOperations; collSurplusPool = contracts.collSurplusPool; - - await deploymentHelper.connectCoreContracts(contracts); - - await fundAccounts([ - owner, - alice, - bob, - carol, - dennis, - erin, - freddy, - greta, - harry, - ida, - whale, - defaulter_1, - defaulter_2, - defaulter_3, - defaulter_4, - A, - B, - C, - D, - E, - F, - G, - H, - I, - ], contracts.WETH); }); it("checkRecoveryMode(): Returns true if TCR falls below CCR", async () => { diff --git a/contracts/test/TroveManager_RecoveryMode_Batch_Liqudation_Test.js b/contracts/test/TroveManager_RecoveryMode_Batch_Liqudation_Test.js index eb631593c..b0084a679 100644 --- a/contracts/test/TroveManager_RecoveryMode_Batch_Liqudation_Test.js +++ b/contracts/test/TroveManager_RecoveryMode_Batch_Liqudation_Test.js @@ -1,14 +1,15 @@ -const deploymentHelper = require("../utils/deploymentHelpers.js"); const { TestHelper: th, MoneyValues: mv } = require("../utils/testHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); -const { toBN, dec, ZERO_ADDRESS } = th; +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); + +const { toBN, dec } = th; const TroveManagerTester = artifacts.require("./TroveManagerTester"); -const BoldToken = artifacts.require("./BoldToken.sol"); contract.skip( "TroveManager - in Recovery Mode - back to normal mode in 1 tx", async (accounts) => { + const fundedAccounts = accounts.slice(0, 24); + const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice( 997, 1000 @@ -38,7 +39,7 @@ contract.skip( G, H, I, - ] = accounts; + ] = fundedAccounts; let contracts; let troveManager; @@ -48,49 +49,18 @@ contract.skip( const openTrove = async (params) => th.openTrove(contracts, params); + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + mocks: { TroveManager: TroveManagerTester }, + }); + beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.troveManager = await TroveManagerTester.new(); - contracts.boldToken = await BoldToken.new( - contracts.troveManager.address, - contracts.stabilityPool.address, - contracts.borrowerOperations.address, - contracts.activePool.address - ); - + const result = await deployFixture(); + contracts = result.contracts; troveManager = contracts.troveManager; stabilityPool = contracts.stabilityPool; priceFeed = contracts.priceFeedTestnet; sortedTroves = contracts.sortedTroves; - - await deploymentHelper.connectCoreContracts(contracts); - - await fundAccounts([ - owner, - alice, - bob, - carol, - dennis, - erin, - freddy, - greta, - harry, - ida, - whale, - defaulter_1, - defaulter_2, - defaulter_3, - defaulter_4, - A, - B, - C, - D, - E, - F, - G, - H, - I, - ], contracts.WETH); }); context("Batch liquidations", () => { diff --git a/contracts/test/stakeDeclineTest.js b/contracts/test/stakeDeclineTest.js index c2cb84de3..0063446c3 100644 --- a/contracts/test/stakeDeclineTest.js +++ b/contracts/test/stakeDeclineTest.js @@ -1,15 +1,8 @@ -const deploymentHelper = require("../utils/deploymentHelpers.js"); -const testHelpers = require("../utils/testHelpers.js"); -const { fundAccounts } = require("../utils/fundAccounts.js"); +const { TestHelper: th } = require("../utils/testHelpers.js"); const TroveManagerTester = artifacts.require("./TroveManagerTester.sol"); -const BoldToken = artifacts.require("./BoldToken.sol"); +const { createDeployAndFundFixture } = require("../utils/testFixtures.js"); -const th = testHelpers.TestHelper; -const dec = th.dec; -const toBN = th.toBN; -const assertRevert = th.assertRevert; -const mv = testHelpers.MoneyValues; -const timeValues = testHelpers.TimeValues; +const { dec, toBN, ZERO_ADDRESS } = th; /* NOTE: Some tests involving ETH redemption fees do not test for specific fee values. * Some only test that the fees are non-zero when they should occur. @@ -19,11 +12,13 @@ const timeValues = testHelpers.TimeValues; * */ contract("TroveManager", async (accounts) => { - const ZERO_ADDRESS = th.ZERO_ADDRESS; - const [owner, A, B, C, D, E, F] = accounts.slice(0, 7); + const fundedAccounts = accounts.slice(0, 7); + + const [owner, A, B, C, D, E, F] = fundedAccounts; const [bountyAddress, lpRewardsAddress, multisig] = accounts.slice(997, 1000); + let contracts; let priceFeed; let boldToken; let sortedTroves; @@ -35,8 +30,6 @@ contract("TroveManager", async (accounts) => { let borrowerOperations; let hintHelpers; - let contracts; - const getOpenTroveBoldAmount = async (totalDebt) => th.getOpenTroveBoldAmount(contracts, totalDebt); @@ -48,16 +41,14 @@ contract("TroveManager", async (accounts) => { return ratio; }; - beforeEach(async () => { - contracts = await deploymentHelper.deployLiquityCore(); - contracts.troveManager = await TroveManagerTester.new(); - contracts.boldToken = await BoldToken.new( - contracts.troveManager.address, - contracts.stabilityPool.address, - contracts.borrowerOperations.address, - contracts.activePool.address - ) + const deployFixture = createDeployAndFundFixture({ + accounts: fundedAccounts, + mocks: { TroveManager: TroveManagerTester }, + }); + beforeEach(async () => { + const result = await deployFixture(); + contracts = result.contracts; priceFeed = contracts.priceFeedTestnet; boldToken = contracts.boldToken; sortedTroves = contracts.sortedTroves; @@ -68,10 +59,6 @@ contract("TroveManager", async (accounts) => { collSurplusPool = contracts.collSurplusPool; borrowerOperations = contracts.borrowerOperations; hintHelpers = contracts.hintHelpers; - - await deploymentHelper.connectCoreContracts(contracts); - - await fundAccounts([owner, A, B, C, D, E, F], contracts.WETH); }); it("A given trove's stake decline is negligible with adjustments and tiny liquidations", async () => { @@ -151,19 +138,19 @@ contract("TroveManager", async (accounts) => { ); await troveManager.liquidate(ATroveId); - console.log( - `totalStakesSnapshot after L1: ${await troveManager.totalStakesSnapshot()}` - ); - console.log( - `totalCollateralSnapshot after L1: ${await troveManager.totalCollateralSnapshot()}` - ); - console.log(`Snapshots ratio after L1: ${await getSnapshotsRatio()}`); - console.log( - `B pending ETH reward after L1: ${await troveManager.getPendingETHReward( - B - )}` - ); - console.log(`B stake after L1: ${(await troveManager.Troves(BTroveId))[2]}`); + // console.log( + // `totalStakesSnapshot after L1: ${await troveManager.totalStakesSnapshot()}` + // ); + // console.log( + // `totalCollateralSnapshot after L1: ${await troveManager.totalCollateralSnapshot()}` + // ); + // console.log(`Snapshots ratio after L1: ${await getSnapshotsRatio()}`); + // console.log( + // `B pending ETH reward after L1: ${await troveManager.getPendingETHReward( + // B + // )}` + // ); + // console.log(`B stake after L1: ${(await troveManager.Troves(BTroveId))[2]}`); // adjust trove B 1 wei: apply rewards await borrowerOperations.adjustTrove( @@ -175,20 +162,20 @@ contract("TroveManager", async (accounts) => { false, { from: B } ); // B repays 1 wei - console.log(`B stake after A1: ${(await troveManager.Troves(BTroveId))[2]}`); - console.log(`Snapshots ratio after A1: ${await getSnapshotsRatio()}`); + // console.log(`B stake after A1: ${(await troveManager.Troves(BTroveId))[2]}`); + // console.log(`Snapshots ratio after A1: ${await getSnapshotsRatio()}`); // Loop over tiny troves, and alternately: // - Liquidate a tiny trove // - Adjust B's collateral by 1 wei for (let [idx, trove] of tinyTroves.entries()) { await troveManager.liquidate(th.addressToTroveId(trove)); - console.log( - `B stake after L${idx + 2}: ${(await troveManager.Troves(BTroveId))[2]}` - ); - console.log( - `Snapshots ratio after L${idx + 2}: ${await getSnapshotsRatio()}` - ); + // console.log( + // `B stake after L${idx + 2}: ${(await troveManager.Troves(BTroveId))[2]}` + // ); + // console.log( + // `Snapshots ratio after L${idx + 2}: ${await getSnapshotsRatio()}` + // ); await borrowerOperations.adjustTrove( BTroveId, th._100pct, @@ -198,9 +185,9 @@ contract("TroveManager", async (accounts) => { false, { from: B } ); // A repays 1 wei - console.log( - `B stake after A${idx + 2}: ${(await troveManager.Troves(B))[2]}` - ); + // console.log( + // `B stake after A${idx + 2}: ${(await troveManager.Troves(B))[2]}` + // ); } }); diff --git a/contracts/utils/deploymentHelpers.js b/contracts/utils/deploymentHelpers.js index 4b10454cc..a53b88dd8 100644 --- a/contracts/utils/deploymentHelpers.js +++ b/contracts/utils/deploymentHelpers.js @@ -24,33 +24,58 @@ const { fundAccounts } = require("./fundAccounts.js"); const maxBytes32 = "0x" + "f".repeat(64); class DeploymentHelper { - static async deployLiquityCore() { - return await this.deployLiquityCoreHardhat(); + static async deployLiquityCore(mocks = {}) { + return await this.deployLiquityCoreHardhat(mocks); } - static async deployLiquityCoreHardhat() { + static async deployLiquityCoreHardhat(mocks = { + PriceFeed: PriceFeedMock, // PriceFeed gets a mock by default + }) { const WETH = await ERC20.new("WETH", "WETH"); - // Borrowing contracts - const activePool = await ActivePool.new(WETH.address); - const borrowerOperations = await BorrowerOperations.new(WETH.address); - const collSurplusPool = await CollSurplusPool.new(WETH.address); - const defaultPool = await DefaultPool.new(WETH.address); - const gasPool = await GasPool.new(); - const priceFeedTestnet = await PriceFeedTestnet.new(); - const priceFeed = await PriceFeedMock.new(); - const sortedTroves = await SortedTroves.new(); - const stabilityPool = await StabilityPool.new(WETH.address); - const troveManager = await TroveManager.new(); - const boldToken = await BoldToken.new( - troveManager.address, - stabilityPool.address, - borrowerOperations.address, - activePool.address + // Contracts, with mocks overriding defaults + const Contracts = Object.fromEntries( + Object.entries({ + ActivePool, + BorrowerOperations, + CollSurplusPool, + DefaultPool, + GasPool, + PriceFeedTestnet, + PriceFeedMock, + SortedTroves, + StabilityPool, + TroveManager, + BoldToken, + HintHelpers, + }) + .map(([name, contract]) => [ + name, + mocks[name] ?? contract + ]) ); - const mockInterestRouter = await MockInterestRouter.new(); - const hintHelpers = await HintHelpers.new(); + // Borrowing contracts + const activePool = await Contracts.ActivePool.new(WETH.address); + const borrowerOperations = await Contracts.BorrowerOperations.new(WETH.address); + const collSurplusPool = await Contracts.CollSurplusPool.new(WETH.address); + const defaultPool = await Contracts.DefaultPool.new(WETH.address); + const gasPool = await Contracts.GasPool.new(); + const priceFeedTestnet = await Contracts.PriceFeedTestnet.new(); + const priceFeed = await Contracts.PriceFeedMock.new(); + const sortedTroves = await Contracts.SortedTroves.new(); + const stabilityPool = await Contracts.StabilityPool.new(WETH.address); + const troveManager = await Contracts.TroveManager.new(); + + const { boldToken } = await this.deployBoldToken({ + troveManager, + stabilityPool, + borrowerOperations, + activePool, + }, Contracts.BoldToken) + + const mockInterestRouter = await MockInterestRouter.new(); + const hintHelpers = await Contracts.HintHelpers.new(); // // Needed? // const price = await priceFeed.getPrice(); @@ -63,17 +88,17 @@ class DeploymentHelper { // TODO: setAsDeployed all above? - BoldToken.setAsDeployed(boldToken); - DefaultPool.setAsDeployed(defaultPool); - PriceFeedTestnet.setAsDeployed(priceFeedTestnet); - SortedTroves.setAsDeployed(sortedTroves); - TroveManager.setAsDeployed(troveManager); - ActivePool.setAsDeployed(activePool); - StabilityPool.setAsDeployed(stabilityPool); - GasPool.setAsDeployed(gasPool); - CollSurplusPool.setAsDeployed(collSurplusPool); - BorrowerOperations.setAsDeployed(borrowerOperations); - HintHelpers.setAsDeployed(hintHelpers); + Contracts.BoldToken.setAsDeployed(boldToken); + Contracts.DefaultPool.setAsDeployed(defaultPool); + Contracts.PriceFeedTestnet.setAsDeployed(priceFeedTestnet); + Contracts.SortedTroves.setAsDeployed(sortedTroves); + Contracts.TroveManager.setAsDeployed(troveManager); + Contracts.ActivePool.setAsDeployed(activePool); + Contracts.StabilityPool.setAsDeployed(stabilityPool); + Contracts.GasPool.setAsDeployed(gasPool); + Contracts.CollSurplusPool.setAsDeployed(collSurplusPool); + Contracts.BorrowerOperations.setAsDeployed(borrowerOperations); + Contracts.HintHelpers.setAsDeployed(hintHelpers); MockInterestRouter.setAsDeployed(mockInterestRouter); const coreContracts = { @@ -94,8 +119,8 @@ class DeploymentHelper { return coreContracts; } - static async deployBoldToken(contracts) { - contracts.boldToken = await BoldToken.new( + static async deployBoldToken(contracts, MockedBoldToken = BoldToken) { + contracts.boldToken = await MockedBoldToken.new( contracts.troveManager.address, contracts.stabilityPool.address, contracts.borrowerOperations.address, diff --git a/contracts/utils/fundAccounts.js b/contracts/utils/fundAccounts.js index e8f689f16..4f0f6e49f 100644 --- a/contracts/utils/fundAccounts.js +++ b/contracts/utils/fundAccounts.js @@ -1,15 +1,9 @@ -const _1e36Str = "1000000000000000000000000000000000000"; - const fundAccounts = async (accounts, token) => { - // const areAccountsAlreadyFunded = await token - // .balanceOf(accounts[0]) - // .gte(_1e36Str); - // if (areAccountsAlreadyFunded) return; - - // console.log("Funding accounts with stETH"); - return accounts.forEach(async (account) => { - await token.mint(account, _1e36Str); - }); + return Promise.all( + accounts.map((account) => ( + token.mint(account, String(10n ** 36n)) + )) + ); }; module.exports = { fundAccounts }; diff --git a/contracts/utils/testFixtures.js b/contracts/utils/testFixtures.js new file mode 100644 index 000000000..02170c0d7 --- /dev/null +++ b/contracts/utils/testFixtures.js @@ -0,0 +1,28 @@ +const { loadFixture } = require("@nomicfoundation/hardhat-network-helpers"); +const deploymentHelper = require("./deploymentHelpers.js"); +const { fundAccounts } = require("./fundAccounts.js"); + +// Returns a fixture utility to be called in every test. +// The callback parameter can be used to run code after the +// deployment. They take the contracts as a parameter, which +// can be modified as needed. The returned object will be merged +// with the object returned by the fixture loader utility. +function createDeployAndFundFixture({ + accounts = [], + callback = async () => null, + mocks = {}, // e.g. { Contract: MockContract } +} = {}) { + const fixture = async () => { + const contracts = await deploymentHelper.deployLiquityCore(mocks); + await deploymentHelper.connectCoreContracts(contracts); + contracts.priceFeed = contracts.priceFeedTestnet; + await fundAccounts(accounts, contracts.WETH); + const callbackResult = await callback(contracts); + return { contracts, ...callbackResult }; + }; + return () => loadFixture(fixture); +} + +module.exports = { + createDeployAndFundFixture, +};