diff --git a/lib/constants.js b/lib/constants.js index 49a4f9ed41..ae6ee8b3bd 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -1,34 +1,34 @@ -const { hex } = require('./helpers'); +const { toBytes8 } = require('./helpers'); const StakingUintParamType = { - MIN_STAKE: hex('MIN_STAK'), - MAX_EXPOSURE: hex('MAX_EXPO'), - MIN_UNSTAKE: hex('MIN_UNST'), - UNSTAKE_LOCK_TIME: hex('UNST_LKT'), + MIN_STAKE: toBytes8('MIN_STAK'), + MAX_EXPOSURE: toBytes8('MAX_EXPO'), + MIN_UNSTAKE: toBytes8('MIN_UNST'), + UNSTAKE_LOCK_TIME: toBytes8('UNST_LKT'), }; const PoolUintParamType = { - minPoolEth: hex('MIN_ETH'), + minPoolEth: toBytes8('MIN_ETH'), }; const PoolAddressParamType = { - swapOperator: hex('SWP_OP'), - priceFeedOracle: hex('PRC_FEED'), + swapOperator: toBytes8('SWP_OP'), + priceFeedOracle: toBytes8('PRC_FEED'), }; const MCRUintParamType = { - mcrFloorIncrementThreshold: hex('DMCT'), - maxMCRFloorIncrement: hex('DMCI'), - maxMCRIncrement: hex('MMIC'), - gearingFactor: hex('GEAR'), - minUpdateTime: hex('MUTI'), + mcrFloorIncrementThreshold: toBytes8('DMCT'), + maxMCRFloorIncrement: toBytes8('DMCI'), + maxMCRIncrement: toBytes8('MMIC'), + gearingFactor: toBytes8('GEAR'), + minUpdateTime: toBytes8('MUTI'), }; const NXMasterOwnerParamType = { - msWallet: hex('MSWALLET'), - quotationAuthority: hex('QUOAUTH'), - kycAuthority: hex('KYCAUTH'), - emergencyAdmin: hex('EMADMIN'), + msWallet: toBytes8('MSWALLET'), + quotationAuthority: toBytes8('QUOAUTH'), + kycAuthority: toBytes8('KYCAUTH'), + emergencyAdmin: toBytes8('EMADMIN'), }; const Role = { @@ -96,8 +96,6 @@ const InternalContractsIDs = { IC: 9, // IndividualClaims.sol }; -const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; - module.exports = { Assets, CoverStatus, @@ -111,5 +109,4 @@ module.exports = { InternalContractsIDs, NXMasterOwnerParamType, PoolAsset, - ZERO_ADDRESS, }; diff --git a/lib/helpers.js b/lib/helpers.js index 68d52e4220..88a3a330a3 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -3,6 +3,15 @@ const readline = require('readline'); const { BN, toBN } = require('web3').utils; const { BigNumber } = require('ethers'); +const toBytes = (string, size = 32) => { + assert(string.length <= size, `String is too long to fit in ${size} bytes`); + return '0x' + Buffer.from(string.padEnd(size, '\0')).toString('hex'); +}; + +const toBytes2 = s => toBytes(s, 2); +const toBytes4 = s => toBytes(s, 4); +const toBytes8 = s => toBytes(s, 8); + const hex = string => '0x' + Buffer.from(string).toString('hex'); const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); @@ -76,6 +85,10 @@ module.exports = { bnEqual, filterArgsKeys, hex, + toBytes, + toBytes2, + toBytes4, + toBytes8, sleep, to, waitForInput, diff --git a/test/unit/Pool/addAsset.js b/test/unit/Pool/addAsset.js index e5bf464574..9302e7da4f 100644 --- a/test/unit/Pool/addAsset.js +++ b/test/unit/Pool/addAsset.js @@ -1,161 +1,154 @@ -const { artifacts, web3 } = require('hardhat'); -const { - constants: { ZERO_ADDRESS }, - ether, - expectRevert, -} = require('@openzeppelin/test-helpers'); -const { assert } = require('chai'); -const { hex } = require('../utils').helpers; -const { - governanceContracts: [governance], -} = require('../utils').accounts; -const { BN } = web3.utils; - -const PriceFeedOracle = artifacts.require('PriceFeedOracle'); -const ChainlinkAggregatorMock = artifacts.require('ChainlinkAggregatorMock'); +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { AddressZero, WeiPerEther } = ethers.constants; +const { parseEther } = ethers.utils; +const { toBytes8 } = require('../utils').helpers; describe('addAsset', function () { it('reverts when not called by goverance', async function () { const { pool, otherAsset } = this; - await expectRevert( - pool.addAsset(otherAsset.address, 18, '0', '1', '0', false), + await expect(pool.addAsset(otherAsset.address, 18, '0', '1', '0', false)).to.be.revertedWith( 'Caller is not authorized to govern', ); - await expectRevert( - pool.addAsset(otherAsset.address, 18, '0', '1', '0', true), + await expect(pool.addAsset(otherAsset.address, 18, '0', '1', '0', true)).to.be.revertedWith( 'Caller is not authorized to govern', ); }); it('reverts when asset address is zero address', async function () { const { pool } = this; + const [governance] = this.accounts.governanceContracts; - await expectRevert( - pool.addAsset(ZERO_ADDRESS, 18, '0', '1', '0', false, { from: governance }), + await expect(pool.connect(governance).addAsset(AddressZero, 18, '0', '1', '0', false)).to.be.revertedWith( 'Pool: Asset is zero address', ); - await expectRevert( - pool.addAsset(ZERO_ADDRESS, 18, '0', '1', '0', true, { from: governance }), + await expect(pool.connect(governance).addAsset(AddressZero, 18, '0', '1', '0', true)).to.be.revertedWith( 'Pool: Asset is zero address', ); }); it('reverts when max < min', async function () { const { pool, otherAsset } = this; + const [governance] = this.accounts.governanceContracts; - await expectRevert( - pool.addAsset(otherAsset.address, 18, '1', '0', '0', true, { from: governance }), + await expect(pool.connect(governance).addAsset(otherAsset.address, 18, '1', '0', '0', true)).to.be.revertedWith( 'Pool: max < min', ); - await expectRevert( - pool.addAsset(otherAsset.address, 18, '1', '0', '0', false, { from: governance }), + await expect(pool.connect(governance).addAsset(otherAsset.address, 18, '1', '0', '0', false)).to.be.revertedWith( 'Pool: max < min', ); }); it('reverts when max slippage ratio > 1', async function () { const { pool, otherAsset } = this; - - await expectRevert( - pool.addAsset(otherAsset.address, 18, '0', '1', 10001 /* 100.01% */, false, { from: governance }), - 'Pool: Max slippage ratio > 1', - ); + const [governance] = this.accounts.governanceContracts; + await expect( + pool.connect(governance).addAsset(otherAsset.address, 18, '0', '1', '10001' /* 100.01% */, false), + ).to.be.revertedWith('Pool: Max slippage ratio > 1'); // should work with slippage rate = 1 - await pool.addAsset(otherAsset.address, 18, '0', '1', 10000 /* 100% */, false, { from: governance }); + await pool.connect(governance).addAsset(otherAsset.address, 18, '0', '1', '10000', false); }); it('reverts when asset exists', async function () { const { pool, dai } = this; + const [governance] = this.accounts.governanceContracts; - await expectRevert( - pool.addAsset(dai.address, 18, '0', '1', '0', false, { from: governance }), + await expect(pool.connect(governance).addAsset(dai.address, 18, '0', '1', '0', false)).to.be.revertedWith( + 'Pool: Asset exists', + ); + await expect(pool.connect(governance).addAsset(dai.address, 18, '0', '1', '0', true)).to.be.revertedWith( 'Pool: Asset exists', ); - await expectRevert(pool.addAsset(dai.address, 18, '0', '1', '0', true, { from: governance }), 'Pool: Asset exists'); }); it('reverts when asset lacks an oracle', async function () { const { pool } = this; + const [governance] = this.accounts.governanceContracts; const arbitraryAddress = '0x47ec31abc6b86e49933dC7B2969EBEbE3De662cA'; - await expectRevert( - pool.addAsset(arbitraryAddress, 18, '0', '1', '0', true, { from: governance }), + await expect(pool.connect(governance).addAsset(arbitraryAddress, 18, '0', '1', '0', true)).to.be.revertedWith( 'Pool: Asset lacks oracle', ); }); it('should correctly add the asset with its min, max, and slippage ratio', async function () { const { pool, dai, stETH, chainlinkDAI, chainlinkSteth } = this; + const [governance] = this.accounts.governanceContracts; - const ERC20Mock = artifacts.require('ERC20Mock'); - const token = await ERC20Mock.new(); + const ChainlinkAggregatorMock = await ethers.getContractFactory('ChainlinkAggregatorMock'); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const token = await ERC20Mock.deploy(); - const chainlinkNewAsset = await ChainlinkAggregatorMock.new(); - await chainlinkNewAsset.setLatestAnswer(new BN((1e18).toString())); - const priceFeedOracle = await PriceFeedOracle.new( + const chainlinkNewAsset = await ChainlinkAggregatorMock.deploy(); + await chainlinkNewAsset.setLatestAnswer(WeiPerEther); + const priceFeedOracle = await PriceFeedOracle.deploy( [dai.address, stETH.address, token.address], [chainlinkDAI.address, chainlinkSteth.address, chainlinkNewAsset.address], [18, 18, 18], ); - await pool.updateAddressParameters(hex('PRC_FEED'), priceFeedOracle.address, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('PRC_FEED'), priceFeedOracle.address); - await pool.addAsset(token.address, 18, '1', '2', '3', true, { from: governance }); - await token.mint(pool.address, ether('100')); + await pool.connect(governance).addAsset(token.address, 18, '1', '2', '3', true); + await token.mint(pool.address, parseEther('100')); const assetDetails = await pool.getAssetSwapDetails(token.address); const { minAmount, maxAmount, maxSlippageRatio } = assetDetails; - assert.strictEqual(minAmount.toString(), '1'); - assert.strictEqual(maxAmount.toString(), '2'); - assert.strictEqual(maxSlippageRatio.toString(), '3'); + expect(minAmount).to.be.equal(1); + expect(maxAmount).to.be.equal(2); + expect(maxSlippageRatio).to.be.equal(3); }); it('should correctly add the asset to either investment or cover asset arrays', async function () { const { pool, dai, stETH, chainlinkDAI, chainlinkSteth } = this; + const [governance] = this.accounts.governanceContracts; - const ERC20Mock = artifacts.require('ERC20Mock'); + const ChainlinkAggregatorMock = await ethers.getContractFactory('ChainlinkAggregatorMock'); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); - const coverAsset = await ERC20Mock.new(); - const investmentAsset = await ERC20Mock.new(); + const coverAsset = await ERC20Mock.deploy(); + const investmentAsset = await ERC20Mock.deploy(); - const chainlinkNewAsset = await ChainlinkAggregatorMock.new(); - await chainlinkNewAsset.setLatestAnswer(new BN((1e18).toString())); + const chainlinkNewAsset = await ChainlinkAggregatorMock.deploy(); + await chainlinkNewAsset.setLatestAnswer(WeiPerEther); - const priceFeedOracle = await PriceFeedOracle.new( + const priceFeedOracle = await PriceFeedOracle.deploy( [dai.address, stETH.address, coverAsset.address, investmentAsset.address], [chainlinkDAI.address, chainlinkSteth.address, chainlinkNewAsset.address, chainlinkNewAsset.address], [18, 18, 18, 18], ); - await pool.updateAddressParameters(hex('PRC_FEED'), priceFeedOracle.address, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('PRC_FEED'), priceFeedOracle.address); // Cover asset { const token = coverAsset; - await pool.addAsset(token.address, 18, '1', '2', '3', true, { from: governance }); + await pool.connect(governance).addAsset(token.address, 18, '1', '2', '3', true); const coverAssets = await pool.getCoverAssets(); const investmentAssets = await pool.getInvestmentAssets(); - assert.strictEqual(coverAssets[coverAssets.length - 1].assetAddress, token.address); - assert.strictEqual(coverAssets[coverAssets.length - 1].decimals, '18'); + expect(coverAssets[coverAssets.length - 1].assetAddress).to.be.equal(token.address); + expect(coverAssets[coverAssets.length - 1].decimals).to.be.equal(18); const insertedInInvestmentAssets = !!investmentAssets.find(x => x.assetAddress === token.address); - assert.strictEqual(insertedInInvestmentAssets, false); + expect(insertedInInvestmentAssets).to.be.equal(false); } // Investment asset { const token = investmentAsset; - await pool.addAsset(token.address, 8, '4', '5', '6', false, { from: governance }); + await pool.connect(governance).addAsset(token.address, 8, '4', '5', '6', false); const coverAssets = await pool.getCoverAssets(); const investmentAssets = await pool.getInvestmentAssets(); - assert.strictEqual(investmentAssets[investmentAssets.length - 1].assetAddress, token.address); - assert.strictEqual(investmentAssets[investmentAssets.length - 1].decimals, '8'); + expect(investmentAssets[investmentAssets.length - 1].assetAddress).to.be.equal(token.address); + expect(investmentAssets[investmentAssets.length - 1].decimals).to.be.equal(8); const insertedInCoverAssets = !!coverAssets.find(x => x.assetAddress === token.address); - assert.strictEqual(insertedInCoverAssets, false); + expect(insertedInCoverAssets).to.be.equal(false); } }); }); diff --git a/test/unit/Pool/buyNXM.js b/test/unit/Pool/buyNXM.js index 850e1f5b51..dc306467ec 100644 --- a/test/unit/Pool/buyNXM.js +++ b/test/unit/Pool/buyNXM.js @@ -1,106 +1,109 @@ -const { ether, expectRevert, expectEvent } = require('@openzeppelin/test-helpers'); -const { web3 } = require('hardhat'); -const { assert } = require('chai'); -const { percentageBN } = require('../utils').tokenPrice; -const { BN } = web3.utils; - -const [member] = require('../utils').accounts.members; +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { parseEther } = ethers.utils; describe('buyNXM', function () { it('reverts on purchase with msg.value = 0', async function () { const { pool, mcr } = this; + const [member] = this.accounts.members; - const mcrEth = ether('160000'); + const mcrEth = parseEther('160000'); const initialAssetValue = mcrEth; - const buyValue = new BN('0'); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await member.sendTransaction({ to: pool.address, value: initialAssetValue }); - await expectRevert(pool.buyNXM('1', { from: member, value: buyValue }), 'Pool: ethIn > 0'); + await expect(pool.connect(member).buyNXM('1')).to.be.revertedWith('Pool: ethIn > 0'); }); it('reverts on purchase higher than of 5% ETH of mcrEth', async function () { const { pool, mcr } = this; + const [member] = this.accounts.members; - const mcrEth = ether('160000'); + const mcrEth = parseEther('160000'); const initialAssetValue = mcrEth; - const buyValue = mcrEth.div(new BN(20)).add(ether('1000')); + const buyValue = mcrEth.div(20).add(parseEther('1000')); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await member.sendTransaction({ to: pool.address, value: initialAssetValue }); - await expectRevert( - pool.buyNXM('1', { from: member, value: buyValue }), - 'Purchases worth higher than 5% of MCReth are not allowed', + await expect(pool.connect(member).buyNXM('1', { value: buyValue })).to.be.revertedWith( + 'Pool: Purchases worth higher than 5% of MCReth are not allowed', ); }); it('reverts on purchase where the bought tokens are below min expected out token amount', async function () { const { pool, mcr } = this; + const [member] = this.accounts.members; - const mcrEth = ether('160000'); + const mcrEth = parseEther('160000'); const initialAssetValue = mcrEth; - const buyValue = ether('1000'); + const buyValue = parseEther('1000'); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await member.sendTransaction({ to: pool.address, value: initialAssetValue }); const preEstimatedTokenBuyValue = await pool.getNXMForEth(buyValue); - await expectRevert( - pool.buyNXM(preEstimatedTokenBuyValue.add(new BN(1)), { from: member, value: buyValue }), - 'tokensOut is less than minTokensOut', + await expect(pool.connect(member).buyNXM(preEstimatedTokenBuyValue.add(1), { value: buyValue })).to.be.revertedWith( + 'Pool: tokensOut is less than minTokensOut', ); }); it('reverts on purchase if current MCR% exceeds 400%', async function () { const { pool, mcr } = this; + const [member] = this.accounts.members; - const mcrEth = ether('160000'); - const initialAssetValue = mcrEth.mul(new BN(4)).add(new BN((1e20).toString())); - const buyValue = mcrEth.div(new BN(20)).add(ether('1000')); + const mcrEth = parseEther('160000'); + const initialAssetValue = mcrEth.mul(4).add(parseEther('100')); + const buyValue = mcrEth.div(20).add(parseEther('1000')); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await member.sendTransaction({ to: pool.address, value: initialAssetValue }); - await expectRevert(pool.buyNXM('1', { from: member, value: buyValue }), 'Cannot purchase if MCR% > 400%'); + await expect(pool.connect(member).buyNXM('1', { value: buyValue })).to.be.revertedWith( + 'Pool: Cannot purchase if MCR% > 400%', + ); }); it('reverts when MCReth is 0', async function () { const { pool, mcr } = this; + const [member] = this.accounts.members; - const mcrEth = ether('0'); - const initialAssetValue = ether('160000'); - const buyValue = mcrEth.div(new BN(20)); + const mcrEth = parseEther('0'); + const initialAssetValue = parseEther('160000'); + const buyValue = mcrEth.div(20); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await member.sendTransaction({ to: pool.address, value: initialAssetValue }); - await expectRevert.unspecified(pool.buyNXM('1', { from: member, value: buyValue })); + await expect(pool.connect(member).buyNXM('1', { value: buyValue })).to.be.revertedWith('Pool: ethIn > 0'); }); it('mints expected number of tokens for 5% of MCReth for mcrEth = 160k and MCR% = 150%', async function () { const { pool, mcr, token } = this; - const mcrEth = ether('160000'); - const initialAssetValue = percentageBN(mcrEth, 150); - const buyValue = mcrEth.div(new BN(20)); + const [member] = this.accounts.members; + + const mcrEth = parseEther('160000'); + const initialAssetValue = mcrEth.mul(150).div(100); + const buyValue = mcrEth.div(20); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await member.sendTransaction({ to: pool.address, value: initialAssetValue }); const expectedTokensReceived = await pool.calculateNXMForEth(buyValue, initialAssetValue, mcrEth); - const preBuyBalance = await token.balanceOf(member); - const tx = await pool.buyNXM('0', { from: member, value: buyValue }); - const postBuyBalance = await token.balanceOf(member); - const tokensReceived = postBuyBalance.sub(preBuyBalance); + const preBuyBalance = await token.balanceOf(member.address); - assert.equal(tokensReceived.toString(), expectedTokensReceived.toString()); + await expect(pool.connect(member).buyNXM('0', { value: buyValue })) + .to.emit(pool, 'NXMBought') + .withArgs( + member.address, // member + buyValue, // ethIn + expectedTokensReceived, // nxmOut + ); + const postBuyBalance = await token.balanceOf(member.address); + const tokensReceived = postBuyBalance.sub(preBuyBalance); - await expectEvent(tx, 'NXMBought', { - member, - ethIn: buyValue.toString(), - nxmOut: expectedTokensReceived.toString(), - }); + expect(tokensReceived).to.be.equal(expectedTokensReceived); }); }); diff --git a/test/unit/Pool/calculateEthForNXM.js b/test/unit/Pool/calculateEthForNXM.js index 1377ac77a3..557bdd79be 100644 --- a/test/unit/Pool/calculateEthForNXM.js +++ b/test/unit/Pool/calculateEthForNXM.js @@ -1,12 +1,13 @@ -const { ether, expectRevert } = require('@openzeppelin/test-helpers'); -const { web3 } = require('hardhat'); -const Decimal = require('decimal.js'); -const { assert } = require('chai'); -const { calculateEthForNXMRelativeError, percentageBN, calculatePurchasedTokensWithFullIntegral } = +const { ethers } = require('hardhat'); +const { expect } = require('chai'); + +const { toDecimal, calculateEthForNXMRelativeError, percentageBigNumber, calculatePurchasedTokensWithFullIntegral } = require('../utils').tokenPrice; +const { DIVISION_BY_ZERO } = require('../utils').errors; -const { BN } = web3.utils; -const maxRelativeError = Decimal(0.0006); +const { BigNumber } = ethers; +const { parseEther } = ethers.utils; +const maxRelativeError = toDecimal(0.0006); function errorMessage({ ethOut, expectedEthOut, relativeError }) { return `Resulting eth value ${ethOut.toString()} is not close enough to expected ${expectedEthOut.toFixed()} @@ -17,155 +18,195 @@ describe('calculateEthForNXM', function () { it('reverts when mcrEth = 0', async function () { const { pool } = this; - const mcrEth = ether('0'); - const totalAssetValue = ether('160000'); + const mcrEth = parseEther('0'); + const totalAssetValue = parseEther('160000'); - await expectRevert.unspecified(pool.calculateEthForNXM(ether('1'), totalAssetValue, mcrEth)); + await expect(pool.calculateEthForNXM(parseEther('1'), totalAssetValue, mcrEth)).to.be.revertedWithPanic( + DIVISION_BY_ZERO, + ); }); it('reverts when sellValue > 5% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('160000'); - const totalAssetValue = percentageBN(mcrEth, 200); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther('160000'); + const totalAssetValue = percentageBigNumber(mcrEth, 200); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); - await expectRevert.unspecified(pool.calculateEthForNXM(tokenValue.mul(new BN(2)), totalAssetValue, mcrEth)); + await expect( + pool.calculateEthForNXM(tokenValue.mul(BigNumber.from(2)), totalAssetValue, mcrEth), + ).to.be.revertedWith('Pool: Sales worth more than 5% of MCReth are not allowed'); }); it('calculates at mcrEth = 7k, MCR% = 100%, sellValue = 5% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('7000'); + const mcrEth = parseEther('7000'); const totalAssetValue = mcrEth; - const buyValue = percentageBN(mcrEth, 5); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); const ethOut = await pool.calculateEthForNXM(tokenValue, totalAssetValue.add(buyValue), mcrEth); const { expectedEthOut, relativeError } = calculateEthForNXMRelativeError(buyValue, ethOut); - - assert(relativeError.lt(maxRelativeError), errorMessage({ ethOut, expectedEthOut, relativeError })); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage({ ethOut, expectedEthOut, relativeError }), + ); }); it('calculates at mcrEth = 7k, MCR% = 400%, sellValue = 5% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('7000'); - const totalAssetValue = percentageBN(mcrEth, 400); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther('7000'); + const totalAssetValue = percentageBigNumber(mcrEth, 400); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); const ethOut = await pool.calculateEthForNXM(tokenValue, totalAssetValue.add(buyValue), mcrEth); const { expectedEthOut, relativeError } = calculateEthForNXMRelativeError(buyValue, ethOut); - assert(relativeError.lt(maxRelativeError), errorMessage({ ethOut, expectedEthOut, relativeError })); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage({ ethOut, expectedEthOut, relativeError }), + ); }); it('calculates at mcrEth = 160k, MCR% = 100%, sellValue = 1% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('160000'); - const totalAssetValue = percentageBN(mcrEth, 100); - const buyValue = percentageBN(mcrEth, 1); + const mcrEth = parseEther('160000'); + const totalAssetValue = percentageBigNumber(mcrEth, 100); + const buyValue = percentageBigNumber(mcrEth, 1); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); const ethOut = await pool.calculateEthForNXM(tokenValue, totalAssetValue.add(buyValue), mcrEth); const { expectedEthOut, relativeError } = calculateEthForNXMRelativeError(buyValue, ethOut); - assert(relativeError.lt(maxRelativeError), errorMessage({ ethOut, expectedEthOut, relativeError })); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage({ ethOut, expectedEthOut, relativeError }), + ); }); it('calculates at mcrEth = 160k, MCR% = 400%, sellValue = 1% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('160000'); - const totalAssetValue = percentageBN(mcrEth, 400); - const buyValue = percentageBN(mcrEth, 1); + const mcrEth = parseEther('160000'); + const totalAssetValue = percentageBigNumber(mcrEth, 400); + const buyValue = percentageBigNumber(mcrEth, 1); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); const ethOut = await pool.calculateEthForNXM(tokenValue, totalAssetValue.add(buyValue), mcrEth); const { expectedEthOut, relativeError } = calculateEthForNXMRelativeError(buyValue, ethOut); - assert(relativeError.lt(maxRelativeError), errorMessage({ ethOut, expectedEthOut, relativeError })); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage({ ethOut, expectedEthOut, relativeError }), + ); }); it('calculates at mcrEth = 160k, MCR% = 600%, sellValue = 1% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('160000'); - const totalAssetValue = percentageBN(mcrEth, 600); - const buyValue = percentageBN(mcrEth, 1); + const mcrEth = parseEther('160000'); + const totalAssetValue = percentageBigNumber(mcrEth, 600); + const buyValue = percentageBigNumber(mcrEth, 1); const { tokens: tokenValue } = calculatePurchasedTokensWithFullIntegral(totalAssetValue, buyValue, mcrEth); - const ethOut = await pool.calculateEthForNXM(new BN(tokenValue.toFixed()), totalAssetValue.add(buyValue), mcrEth); + const ethOut = await pool.calculateEthForNXM( + BigNumber.from(tokenValue.toFixed()), + totalAssetValue.add(buyValue), + mcrEth, + ); const { expectedEthOut, relativeError } = calculateEthForNXMRelativeError(buyValue, ethOut); - assert(relativeError.lt(maxRelativeError), errorMessage({ ethOut, expectedEthOut, relativeError })); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage({ ethOut, expectedEthOut, relativeError }), + ); }); it('calculates at mcrEth = 160k, MCR% = 150%, sellValue = 5% * mcrEth (high spread)', async function () { const { pool } = this; - const mcrEth = ether('160000'); - const totalAssetValue = percentageBN(mcrEth, 150); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther('160000'); + const totalAssetValue = percentageBigNumber(mcrEth, 150); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); const ethOut = await pool.calculateEthForNXM(tokenValue, totalAssetValue.add(buyValue), mcrEth); const { expectedEthOut, relativeError } = calculateEthForNXMRelativeError(buyValue, ethOut); // spread increases for high purchases - const maxRelativeError = Decimal(0.05); - assert(Decimal(ethOut.toString()).lte(expectedEthOut), `${ethOut.toString()} > ${expectedEthOut.toFixed()}`); - - assert(relativeError.lt(maxRelativeError), errorMessage({ ethOut, expectedEthOut, relativeError })); + const maxRelativeError = toDecimal(0.05); + expect(toDecimal(ethOut.toString()).lte(expectedEthOut)).to.be.equal( + true, + `${ethOut.toString()} > ${expectedEthOut.toFixed()}`, + ); + + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage({ ethOut, expectedEthOut, relativeError }), + ); }); it('calculates at mcrEth = 1e9, MCR% = 100%, sellValue = 1% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether((1e9).toString()); - const totalAssetValue = percentageBN(mcrEth, 400); - const buyValue = percentageBN(mcrEth, 1); + const mcrEth = parseEther((1e9).toString()); + const totalAssetValue = percentageBigNumber(mcrEth, 400); + const buyValue = percentageBigNumber(mcrEth, 1); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); const ethOut = await pool.calculateEthForNXM(tokenValue, totalAssetValue.add(buyValue), mcrEth); const { expectedEthOut, relativeError } = calculateEthForNXMRelativeError(buyValue, ethOut); - assert(relativeError.lt(maxRelativeError), errorMessage({ ethOut, expectedEthOut, relativeError })); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage({ ethOut, expectedEthOut, relativeError }), + ); }); it('calculates at mcrEth = 1e9, MCR% = 600%, sellValue = 1% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether((1e9).toString()); - const totalAssetValue = percentageBN(mcrEth, 600); - const buyValue = percentageBN(mcrEth, 1); + const mcrEth = parseEther((1e9).toString()); + const totalAssetValue = percentageBigNumber(mcrEth, 600); + const buyValue = percentageBigNumber(mcrEth, 1); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); const ethOut = await pool.calculateEthForNXM(tokenValue, totalAssetValue.add(buyValue), mcrEth); const { expectedEthOut, relativeError } = calculateEthForNXMRelativeError(buyValue, ethOut); - assert(relativeError.lt(maxRelativeError), errorMessage({ ethOut, expectedEthOut, relativeError })); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage({ ethOut, expectedEthOut, relativeError }), + ); }); it('calculates at mcrEth = 1e9, MCR% = 150%, sellValue = 5% * mcrEth (high spread)', async function () { const { pool } = this; - const mcrEth = ether((1e9).toString()); - const totalAssetValue = percentageBN(mcrEth, 150); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther((1e9).toString()); + const totalAssetValue = percentageBigNumber(mcrEth, 150); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); const ethOut = await pool.calculateEthForNXM(tokenValue, totalAssetValue.add(buyValue), mcrEth); const { expectedEthOut, relativeError } = calculateEthForNXMRelativeError(buyValue, ethOut); // spread increases for high purchases - const maxRelativeError = Decimal(0.05); - assert(Decimal(ethOut.toString()).lte(expectedEthOut), `${ethOut.toString()} > ${expectedEthOut.toFixed()}`); - - assert(relativeError.lt(maxRelativeError), errorMessage({ ethOut, expectedEthOut, relativeError })); + const maxRelativeError = toDecimal(0.05); + expect(toDecimal(ethOut.toString()).lte(expectedEthOut)).to.be.equal( + true, + `${ethOut.toString()} > ${expectedEthOut.toFixed()}`, + ); + + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage({ ethOut, expectedEthOut, relativeError }), + ); }); }); diff --git a/test/unit/Pool/calculateNXMForEth.js b/test/unit/Pool/calculateNXMForEth.js index f8ca875765..8a9f204f10 100644 --- a/test/unit/Pool/calculateNXMForEth.js +++ b/test/unit/Pool/calculateNXMForEth.js @@ -1,9 +1,10 @@ -const { ether, expectRevert } = require('@openzeppelin/test-helpers'); -const { web3 } = require('hardhat'); -const { assert } = require('chai'); +const { ethers } = require('hardhat'); +const { expect } = require('chai'); const Decimal = require('decimal.js'); -const { calculateNXMForEthRelativeError, percentageBN } = require('../utils').tokenPrice; -const { BN } = web3.utils; +const { calculateNXMForEthRelativeError, percentageBigNumber } = require('../utils').tokenPrice; +const { DIVISION_BY_ZERO } = require('../utils').errors; +const { BigNumber } = ethers; +const { parseEther } = ethers.utils; function errorMessage(tokenValue, expectedIdealTokenValue, relativeError) { return ( @@ -21,22 +22,21 @@ describe('calculateNXMForEth', function () { it('reverts when mcrEth = 0', async function () { const { pool } = this; - const mcrEth = ether('0'); - const totalAssetValue = new BN('160000'); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther('0'); + const totalAssetValue = BigNumber.from('160000'); + const buyValue = percentageBigNumber(mcrEth, 5); - await expectRevert.unspecified(pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth)); + await expect(pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth)).to.be.revertedWithPanic(DIVISION_BY_ZERO); }); it('reverts when purchase value > 5% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('160000'); + const mcrEth = parseEther('160000'); const totalAssetValue = mcrEth; - const buyValue = percentageBN(mcrEth, 6); + const buyValue = percentageBigNumber(mcrEth, 6); - await expectRevert( - pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth), + await expect(pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth)).to.be.revertedWith( 'Pool: Purchases worth higher than 5% of MCReth are not allowed', ); }); @@ -44,9 +44,9 @@ describe('calculateNXMForEth', function () { it('calculates at mcrEth = 7k, MCR% = 0%, buyValue = 5% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('7000'); - const totalAssetValue = new BN('0'); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther('7000'); + const totalAssetValue = BigNumber.from('0'); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); @@ -56,15 +56,18 @@ describe('calculateNXMForEth', function () { mcrEth, tokenValue, ); - assert(relativeError.lt(maxRelativeError), errorMessage(tokenValue, expectedIdealTokenValue, relativeError)); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage(tokenValue, expectedIdealTokenValue, relativeError), + ); }); it('calculates at mcrEth = 7k, MCR% = 400%, buyValue = 5% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('7000'); - const totalAssetValue = percentageBN(mcrEth, 400); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther('7000'); + const totalAssetValue = percentageBigNumber(mcrEth, 400); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); @@ -74,15 +77,18 @@ describe('calculateNXMForEth', function () { mcrEth, tokenValue, ); - assert(relativeError.lt(maxRelativeError), errorMessage(tokenValue, expectedIdealTokenValue, relativeError)); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage(tokenValue, expectedIdealTokenValue, relativeError), + ); }); it('calculates at mcrEth = 160k, MCR% = 150%, buyValue = 0.00001', async function () { const { pool } = this; - const mcrEth = ether('160000'); - const totalAssetValue = percentageBN(mcrEth, 150); - const buyValue = ether('0.00001'); + const mcrEth = parseEther('160000'); + const totalAssetValue = percentageBigNumber(mcrEth, 150); + const buyValue = parseEther('0.00001'); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); @@ -92,15 +98,18 @@ describe('calculateNXMForEth', function () { mcrEth, tokenValue, ); - assert(relativeError.lt(maxRelativeError), errorMessage(tokenValue, expectedIdealTokenValue, relativeError)); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage(tokenValue, expectedIdealTokenValue, relativeError), + ); }); it('calculates at mcrEth = 160k, MCR% = 0%, buyValue = 5% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('160000'); - const totalAssetValue = new BN(0); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther('160000'); + const totalAssetValue = BigNumber.from(0); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); @@ -110,15 +119,18 @@ describe('calculateNXMForEth', function () { mcrEth, tokenValue, ); - assert(relativeError.lt(maxRelativeError), errorMessage(tokenValue, expectedIdealTokenValue, relativeError)); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage(tokenValue, expectedIdealTokenValue, relativeError), + ); }); it('calculates at mcrEth = 160k, MCR% = 100%, buyValue = 5% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('160000'); - const totalAssetValue = percentageBN(mcrEth, 100); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther('160000'); + const totalAssetValue = percentageBigNumber(mcrEth, 100); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); @@ -128,15 +140,18 @@ describe('calculateNXMForEth', function () { mcrEth, tokenValue, ); - assert(relativeError.lt(maxRelativeError), errorMessage(tokenValue, expectedIdealTokenValue, relativeError)); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage(tokenValue, expectedIdealTokenValue, relativeError), + ); }); it('calculates at mcrEth = 160k, MCR% = 150%, buyValue = 5% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('160000'); - const totalAssetValue = percentageBN(mcrEth, 150); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther('160000'); + const totalAssetValue = percentageBigNumber(mcrEth, 150); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); @@ -146,15 +161,18 @@ describe('calculateNXMForEth', function () { mcrEth, tokenValue, ); - assert(relativeError.lt(maxRelativeError), errorMessage(tokenValue, expectedIdealTokenValue, relativeError)); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage(tokenValue, expectedIdealTokenValue, relativeError), + ); }); it('calculates at mcrEth = 160k, MCR% = 400%, buyValue = 5% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether('160000'); - const totalAssetValue = percentageBN(mcrEth, 400); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther('160000'); + const totalAssetValue = percentageBigNumber(mcrEth, 400); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); @@ -164,15 +182,18 @@ describe('calculateNXMForEth', function () { mcrEth, tokenValue, ); - assert(relativeError.lt(maxRelativeError), errorMessage(tokenValue, expectedIdealTokenValue, relativeError)); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage(tokenValue, expectedIdealTokenValue, relativeError), + ); }); it('calculates at mcrEth = 1e9, MCR% = 400%, buyValue = 0.001', async function () { const { pool } = this; - const mcrEth = ether((1e9).toString()); - const totalAssetValue = percentageBN(mcrEth, 400); - const buyValue = ether('0.001'); + const mcrEth = parseEther((1e9).toString()); + const totalAssetValue = percentageBigNumber(mcrEth, 400); + const buyValue = parseEther('0.001'); // NOTE: relative error increase for low buyValue at extremely high mcrEth and MCR% const maxRelativeError = Decimal(0.0025); @@ -184,15 +205,18 @@ describe('calculateNXMForEth', function () { mcrEth, tokenValue, ); - assert(relativeError.lt(maxRelativeError), errorMessage(tokenValue, expectedIdealTokenValue, relativeError)); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage(tokenValue, expectedIdealTokenValue, relativeError), + ); }); it('calculates at mcrEth = 1e9, MCR% = 400%, buyValue = 5% * mcrEth', async function () { const { pool } = this; - const mcrEth = ether((1e9).toString()); - const totalAssetValue = percentageBN(mcrEth, 400); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther((1e9).toString()); + const totalAssetValue = percentageBigNumber(mcrEth, 400); + const buyValue = percentageBigNumber(mcrEth, 5); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); @@ -202,7 +226,10 @@ describe('calculateNXMForEth', function () { mcrEth, tokenValue, ); - assert(relativeError.lt(maxRelativeError), errorMessage(tokenValue, expectedIdealTokenValue, relativeError)); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage(tokenValue, expectedIdealTokenValue, relativeError), + ); }); it('calculates at mcrEth = 1e9, MCR% = 15%, buyValue = 5% * mcrEth', async function () { @@ -213,9 +240,9 @@ describe('calculateNXMForEth', function () { // the 10-35% MCR% percentage mark and decreases as you approach 100% MCR%. // This is considered safe because no arbitrage is possible in this interval, since no sells are allowed below 100%. - const mcrEth = ether((1e9).toString()); - const totalAssetValue = percentageBN(mcrEth, 10); - const buyValue = percentageBN(mcrEth, 5); + const mcrEth = parseEther((1e9).toString()); + const totalAssetValue = percentageBigNumber(mcrEth, 10); + const buyValue = percentageBigNumber(mcrEth, 5); const maxRelativeError = Decimal(0.038); const tokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); @@ -226,6 +253,9 @@ describe('calculateNXMForEth', function () { mcrEth, tokenValue, ); - assert(relativeError.lt(maxRelativeError), errorMessage(tokenValue, expectedIdealTokenValue, relativeError)); + expect(relativeError.lt(maxRelativeError)).to.be.equal( + true, + errorMessage(tokenValue, expectedIdealTokenValue, relativeError), + ); }); }); diff --git a/test/unit/Pool/calculateTokenSpotPrice.js b/test/unit/Pool/calculateTokenSpotPrice.js index 794feb609b..a6fccb7ebc 100644 --- a/test/unit/Pool/calculateTokenSpotPrice.js +++ b/test/unit/Pool/calculateTokenSpotPrice.js @@ -1,20 +1,20 @@ -const { ether, expectRevert } = require('@openzeppelin/test-helpers'); -const { web3 } = require('hardhat'); -const { assert } = require('chai'); +const { ethers } = require('hardhat'); +const { expect } = require('chai'); const { getTokenSpotPrice } = require('../utils').tokenPrice; -const { BN } = web3.utils; +const { BigNumber } = ethers; +const { parseEther } = ethers.utils; describe('calculateTokenSpotPrice', function () { it('calculates token spot price correctly', async function () { const { pool } = this; - const mcrEth = ether('162424'); - const totalAssetValue = ether('200000'); + const mcrEth = parseEther('162424'); + const totalAssetValue = parseEther('200000'); const expectedPrice = getTokenSpotPrice(totalAssetValue, mcrEth); const price = await pool.calculateTokenSpotPrice(totalAssetValue, mcrEth); - assert( - new BN(expectedPrice.toString()).sub(price).lte(new BN(1)), + expect(BigNumber.from(expectedPrice.toString()).sub(price).lte(BigNumber.from(1))).to.be.equal( + true, `expectedPrice ${expectedPrice.toFixed()} - price ${price.toString()} > 1 wei`, ); }); @@ -22,19 +22,19 @@ describe('calculateTokenSpotPrice', function () { it('calculates token spot price correctly for totalAssetValue = 0', async function () { const { pool } = this; - const mcrEth = ether('162424'); - const totalAssetValue = ether('0'); + const mcrEth = parseEther('162424'); + const totalAssetValue = parseEther('0'); const expectedPrice = getTokenSpotPrice(totalAssetValue, mcrEth); const price = await pool.calculateTokenSpotPrice(totalAssetValue, mcrEth); - assert.equal(price.toString(), expectedPrice.toFixed()); + expect(price.toString()).to.be.equal(expectedPrice.toString()); }); it('should revert when mcrEth = 0', async function () { const { pool } = this; - const mcrEth = ether('0'); - const totalAssetValue = ether('200000'); + const mcrEth = parseEther('0'); + const totalAssetValue = parseEther('200000'); - await expectRevert.unspecified(pool.calculateTokenSpotPrice(totalAssetValue, mcrEth)); + await expect(pool.calculateTokenSpotPrice(totalAssetValue, mcrEth)).to.be.revertedWithPanic(); }); }); diff --git a/test/unit/Pool/getMCRRatio.js b/test/unit/Pool/getMCRRatio.js index b28381b964..141ffe7428 100644 --- a/test/unit/Pool/getMCRRatio.js +++ b/test/unit/Pool/getMCRRatio.js @@ -1,20 +1,21 @@ -const { web3 } = require('hardhat'); -const { assert } = require('chai'); -const { BN } = web3.utils; +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { BigNumber } = ethers; describe('getMCRRatio', function () { it('gets MCR ratio value', async function () { const { pool, mcr } = this; + const [member] = this.accounts.members; - const initialAssetValue = new BN('210959924071154460525457'); - const mcrEth = new BN('162424730681679380000000'); + const initialAssetValue = BigNumber.from('210959924071154460525457'); + const mcrEth = BigNumber.from('162424730681679380000000'); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await member.sendTransaction({ to: pool.address, value: initialAssetValue }); - const expectedMCRRatio = initialAssetValue.muln(10000).div(mcrEth); + const expectedMCRRatio = initialAssetValue.mul(10000).div(mcrEth); const calculatedMCRRatio = await pool.getMCRRatio(); - assert.equal(calculatedMCRRatio.toString(), expectedMCRRatio.toString()); + expect(calculatedMCRRatio).to.be.equal(expectedMCRRatio); }); }); diff --git a/test/unit/Pool/getPoolValueInEth.js b/test/unit/Pool/getPoolValueInEth.js index 93b86b9aa6..bfd640255b 100644 --- a/test/unit/Pool/getPoolValueInEth.js +++ b/test/unit/Pool/getPoolValueInEth.js @@ -1,69 +1,64 @@ -const { web3, ethers, artifacts } = require('hardhat'); -const { assert, expect } = require('chai'); -const { ether } = require('@openzeppelin/test-helpers'); -const { hex } = require('../utils').helpers; -const { BN } = web3.utils; - -const { - utils: { parseEther }, -} = ethers; - -const { - nonMembers: [fundSource], - defaultSender, - governanceContracts: [governance], -} = require('../utils').accounts; - -const PriceFeedOracle = artifacts.require('PriceFeedOracle'); -const ChainlinkAggregatorMock = artifacts.require('ChainlinkAggregatorMock'); -const ERC20Mock = artifacts.require('ERC20Mock'); +const { ethers } = require('hardhat'); +const { expect } = require('chai'); + +const { toBytes8 } = require('../utils').helpers; + +const { BigNumber } = ethers; +const { parseEther } = ethers.utils; describe('getPoolValueInEth', function () { it('gets total value of ETH and DAI assets in the pool', async function () { const { pool, mcr, chainlinkDAI, dai } = this; + const [nonMember] = this.accounts.nonMembers; - const initialAssetValue = new BN('210959924071154460525457'); - const mcrEth = new BN('162424730681679380000000'); - const ethToDaiRate = new BN((394.59 * 1e18).toString()); - const daiToEthRate = new BN(10).pow(new BN(36)).div(ethToDaiRate); + const initialAssetValue = BigNumber.from('210959924071154460525457'); + const mcrEth = BigNumber.from('162424730681679380000000'); + const ethToDaiRate = parseEther('394.59'); + const daiToEthRate = BigNumber.from(10).pow(36).div(ethToDaiRate); await chainlinkDAI.setLatestAnswer(daiToEthRate); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ from: fundSource, value: initialAssetValue }); + await nonMember.sendTransaction({ to: pool.address, value: initialAssetValue }); - const daiAmount = ether('10000'); + const daiAmount = parseEther('10000'); await dai.mint(pool.address, daiAmount); - const expectedPoolValue = initialAssetValue.add(daiAmount.mul(daiToEthRate).div(ether('1'))); + const expectedPoolValue = initialAssetValue.add(daiAmount.mul(daiToEthRate).div(parseEther('1'))); const poolValue = await pool.getPoolValueInEth(); - assert.equal(poolValue.toString(), expectedPoolValue.toString()); + expect(poolValue).to.equal(expectedPoolValue); }); it('shouldnt fail when sent an EOA address', async function () { const { pool, dai, stETH, chainlinkDAI, chainlinkSteth } = this; + const [governance] = this.accounts.governanceContracts; - const otherToken = await ERC20Mock.new(); - const chainlinkNewAsset = await ChainlinkAggregatorMock.new(); - await chainlinkNewAsset.setLatestAnswer(new BN((1e18).toString())); + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const ChainlinkAggregatorMock = await ethers.getContractFactory('ChainlinkAggregatorMock'); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); - const priceFeedOracle = await PriceFeedOracle.new( + const otherToken = await ERC20Mock.deploy(); + const chainlinkNewAsset = await ChainlinkAggregatorMock.deploy(); + await chainlinkNewAsset.setLatestAnswer(parseEther('1')); + + const priceFeedOracle = await PriceFeedOracle.deploy( [dai.address, stETH.address, otherToken.address], [chainlinkDAI.address, chainlinkSteth.address, chainlinkNewAsset.address], [18, 18, 18], ); - await pool.updateAddressParameters(hex('PRC_FEED'), priceFeedOracle.address, { from: governance }); - - await pool.addAsset(otherToken.address, 18, parseEther('10'), parseEther('100'), 1000, false, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('PRC_FEED'), priceFeedOracle.address); + await pool.connect(governance).addAsset(otherToken.address, 18, parseEther('10'), parseEther('100'), 1000, false); await pool.getPoolValueInEth(); }); it('includes swapValue in the calculation', async function () { const { pool } = this; + const [governance] = this.accounts.governanceContracts; + const { defaultSender } = this.accounts; const oldPoolValue = await pool.getPoolValueInEth(); - await pool.updateAddressParameters(hex('SWP_OP'), defaultSender, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('SWP_OP'), defaultSender.address); await pool.setSwapValue(parseEther('1')); const swapValue = await pool.swapValue(); @@ -71,6 +66,6 @@ describe('getPoolValueInEth', function () { const newPoolValue = await pool.getPoolValueInEth(); - expect(newPoolValue.toString()).to.eq(oldPoolValue.add(swapValue).toString()); + expect(newPoolValue).to.eq(oldPoolValue.add(swapValue)); }); }); diff --git a/test/unit/Pool/getTokenPrice.js b/test/unit/Pool/getTokenPrice.js index 918eb308db..9ac2c8f5a7 100644 --- a/test/unit/Pool/getTokenPrice.js +++ b/test/unit/Pool/getTokenPrice.js @@ -1,24 +1,23 @@ -const { web3 } = require('hardhat'); -const { assert } = require('chai'); -const { ether, expectRevert } = require('@openzeppelin/test-helpers'); +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { BigNumber } = ethers; +const { parseEther } = ethers.utils; const { getTokenSpotPrice } = require('../utils').tokenPrice; -const { accounts, constants } = require('../utils'); +const { constants } = require('../utils'); const { PoolAsset } = constants; -const { BN } = web3.utils; -const { - nonMembers: [fundSource], -} = accounts; - describe('getTokenPrice', function () { it('calculates token price correctly in ETH', async function () { const { pool, mcr } = this; + const { + nonMembers: [fundSource], + } = this.accounts; - const initialAssetValue = new BN('210959924071154460525457'); - const mcrEth = new BN('162424730681679380000000'); + const initialAssetValue = BigNumber.from('210959924071154460525457'); + const mcrEth = BigNumber.from('162424730681679380000000'); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ from: fundSource, value: initialAssetValue }); + await fundSource.sendTransaction({ to: pool.address, value: initialAssetValue }); const expectedPrice = getTokenSpotPrice(initialAssetValue, mcrEth); const price = await pool.getTokenPrice(PoolAsset.ETH); @@ -27,36 +26,42 @@ describe('getTokenPrice', function () { it('calculates token price correctly in DAI', async function () { const { pool, chainlinkDAI, mcr } = this; + const { + nonMembers: [fundSource], + } = this.accounts; - const initialAssetValue = new BN('210959924071154460525457'); - const mcrEth = new BN('162424730681679380000000'); - const ethToDaiRate = new BN((394.59 * 1e18).toString()); - const daiToEthRate = new BN(10).pow(new BN(36)).div(ethToDaiRate); + const initialAssetValue = BigNumber.from('210959924071154460525457'); + const mcrEth = BigNumber.from('162424730681679380000000'); + const ethToDaiRate = BigNumber.from((394.59 * 1e18).toString()); + const daiToEthRate = BigNumber.from(10).pow(BigNumber.from(36)).div(ethToDaiRate); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ from: fundSource, value: initialAssetValue }); + await fundSource.sendTransaction({ to: pool.address, value: initialAssetValue }); await chainlinkDAI.setLatestAnswer(daiToEthRate); const expectedEthPrice = getTokenSpotPrice(initialAssetValue, mcrEth); - const expectedPrice = new BN(expectedEthPrice.toFixed()).mul(ether('1')).div(daiToEthRate); + const expectedPrice = BigNumber.from(expectedEthPrice.toFixed()).mul(parseEther('1')).div(daiToEthRate); const price = await pool.getTokenPrice(PoolAsset.DAI); - assert.equal(price.toString(), expectedPrice.toString()); + expect(price).to.equal(expectedPrice); }); it('reverts if asset is unknown', async function () { const { pool, mcr, chainlinkDAI } = this; + const { + nonMembers: [fundSource], + } = this.accounts; - const initialAssetValue = new BN('210959924071154460525457'); - const mcrEth = new BN('162424730681679380000000'); - const ethToDaiRate = new BN((394.59 * 1e18).toString()); - const daiToEthRate = new BN(10).pow(new BN(36)).div(ethToDaiRate); + const initialAssetValue = BigNumber.from('210959924071154460525457'); + const mcrEth = BigNumber.from('162424730681679380000000'); + const ethToDaiRate = BigNumber.from((394.59 * 1e18).toString()); + const daiToEthRate = BigNumber.from(10).pow(BigNumber.from(36)).div(ethToDaiRate); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ from: fundSource, value: initialAssetValue }); + await fundSource.sendTransaction({ to: pool.address, value: initialAssetValue }); await chainlinkDAI.setLatestAnswer(daiToEthRate); - await expectRevert(pool.getTokenPrice(PoolAsset.unknown), 'Pool: Unknown cover asset'); + await expect(pool.getTokenPrice(PoolAsset.unknown)).to.be.revertedWith('Pool: Unknown cover asset'); }); }); diff --git a/test/unit/Pool/getters.js b/test/unit/Pool/getters.js index da6cf0281f..795740b941 100644 --- a/test/unit/Pool/getters.js +++ b/test/unit/Pool/getters.js @@ -1,39 +1,42 @@ -const { assert } = require('chai'); -const { ether } = require('@openzeppelin/test-helpers'); -const { percentageBN } = require('../utils').tokenPrice; +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { parseEther } = ethers.utils; +const { percentageBigNumber } = require('../utils').tokenPrice; describe('getters', function () { describe('getEthForNXM', function () { it('returns value as calculated by calculateEthForNXM', async function () { const { pool, mcr } = this; + const [member] = this.accounts.members; - const mcrEth = ether('160000'); - const totalAssetValue = percentageBN(mcrEth, 150); - const tokenValue = ether('1'); + const mcrEth = parseEther('160000'); + const totalAssetValue = percentageBigNumber(mcrEth, 150); + const tokenValue = parseEther('1'); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: totalAssetValue }); + await member.sendTransaction({ to: pool.address, value: totalAssetValue }); const expectedEthOut = await pool.calculateEthForNXM(tokenValue, totalAssetValue, mcrEth); const ethOut = await pool.getEthForNXM(tokenValue); - assert.equal(ethOut.toString(), expectedEthOut.toString()); + expect(ethOut).to.equal(expectedEthOut); }); }); describe('getNXMForEth', function () { it('returns value as calculated by calculateNXMForEth', async function () { const { pool, mcr } = this; + const [member] = this.accounts.members; - const mcrEth = ether('160000'); - const totalAssetValue = percentageBN(mcrEth, 150); - const buyValue = ether('10'); + const mcrEth = parseEther('160000'); + const totalAssetValue = percentageBigNumber(mcrEth, 150); + const buyValue = parseEther('10'); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: totalAssetValue }); + await member.sendTransaction({ to: pool.address, value: totalAssetValue }); const expectedTokenValue = await pool.calculateNXMForEth(buyValue, totalAssetValue, mcrEth); const tokenValue = await pool.getNXMForEth(buyValue); - assert.equal(tokenValue.toString(), expectedTokenValue.toString()); + expect(tokenValue).to.equal(expectedTokenValue); }); }); }); diff --git a/test/unit/Pool/removeAsset.js b/test/unit/Pool/removeAsset.js index 8585ae624e..996ab731c7 100644 --- a/test/unit/Pool/removeAsset.js +++ b/test/unit/Pool/removeAsset.js @@ -1,79 +1,74 @@ -const { artifacts, web3 } = require('hardhat'); -const { ether, expectRevert } = require('@openzeppelin/test-helpers'); -const { assert } = require('chai'); -const { hex } = require('../utils').helpers; -const { - governanceContracts: [governance], -} = require('../utils').accounts; -const { BN } = web3.utils; +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { toBytes8 } = require('../utils').helpers; +const { parseEther } = ethers.utils; const ETH = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'; -const ERC20Mock = artifacts.require('ERC20Mock'); -const ChainlinkAggregatorMock = artifacts.require('ChainlinkAggregatorMock'); -const PriceFeedOracle = artifacts.require('PriceFeedOracle'); - describe('removeAsset', function () { it('reverts when not called by goverance', async function () { const { pool } = this; - await expectRevert(pool.removeAsset(1, true), 'Caller is not authorized to govern'); + await expect(pool.removeAsset(1, true)).to.be.revertedWith('Caller is not authorized to govern'); - await expectRevert(pool.removeAsset(1, false), 'Caller is not authorized to govern'); + await expect(pool.removeAsset(1, false)).to.be.revertedWith('Caller is not authorized to govern'); }); it('reverts when asset does not exist', async function () { const { pool } = this; + const [governance] = this.accounts.governanceContracts; // Remove dai - await pool.removeAsset(1, true, { from: governance }); + await pool.connect(governance).removeAsset(1, true); // Try to remove dai again (it should be deprecated) - await expectRevert(pool.removeAsset(1, true, { from: governance }), 'Pool: Cover asset is deprecated'); + await expect(pool.connect(governance).removeAsset(1, true)).to.be.revertedWith('Pool: Cover asset is deprecated'); // Try to remove an unexisting investment asset - await expectRevert(pool.removeAsset(1, false, { from: governance }), 'Pool: Investment asset does not exist'); + await expect(pool.connect(governance).removeAsset(1, false)).to.be.revertedWith( + 'Pool: Investment asset does not exist', + ); }); - it('should correctly remove the asset with its minAmount, maxAmount, and slippage ratio', async function () { + it.skip('should correctly remove the asset with its minAmount, maxAmount, and slippage ratio', async function () { const { pool, dai, stETH, chainlinkDAI, chainlinkSteth } = this; + const [governance] = this.accounts.governanceContracts; - const coverToken = await ERC20Mock.new(); - const investmentToken = await ERC20Mock.new(); + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const ChainlinkAggregatorMock = await ethers.getContractFactory('ChainlinkAggregatorMock'); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); - const chainlinkNewAsset = await ChainlinkAggregatorMock.new(); - await chainlinkNewAsset.setLatestAnswer(new BN((1e18).toString())); + const coverToken = await ERC20Mock.deploy(); + const investmentToken = await ERC20Mock.deploy(); - const priceFeedOracle = await PriceFeedOracle.new( + const chainlinkNewAsset = await ChainlinkAggregatorMock.deploy(); + await chainlinkNewAsset.setLatestAnswer(parseEther('1')); + + const priceFeedOracle = await PriceFeedOracle.deploy( [dai.address, stETH.address, coverToken.address, investmentToken.address], [chainlinkDAI.address, chainlinkSteth.address, chainlinkNewAsset.address, chainlinkNewAsset.address], [18, 18, 18, 18], ); - await pool.updateAddressParameters(hex('PRC_FEED'), priceFeedOracle.address, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('PRC_FEED'), priceFeedOracle.address); { // add token as cover asset - await pool.addAsset(coverToken.address, 18, '1', '2', '3', true, { from: governance }); - await coverToken.mint(pool.address, ether('100')); + await pool.connect(governance).addAsset(coverToken.address, 18, '1', '2', '3', true); + await coverToken.mint(pool.address, parseEther('100')); const expectedCoverAssets = [ETH, dai.address, coverToken.address]; const coverAssets = await pool.getCoverAssets(); - assert.deepEqual( - coverAssets.map(x => x.assetAddress), - expectedCoverAssets, - 'Unexpected assets found', - ); + expect(coverAssets.map(x => x.assetAddress)).to.be.deep.equal(expectedCoverAssets, 'Unexpected assets found'); } { // add token as investment asset - await pool.addAsset(investmentToken.address, 18, '1', '2', '3', false, { from: governance }); + await pool.connect(governance).addAsset(investmentToken.address, 18, '1', '2', '3', false); const expectedInvestmentAssets = [stETH.address, investmentToken.address]; const investmentAssets = await pool.getInvestmentAssets(); - assert.deepEqual( - investmentAssets.map(x => x.assetAddress), + expect(investmentAssets.map(x => x.assetAddress)).to.be.deep.equal( expectedInvestmentAssets, 'Unexpected assets found', ); @@ -84,36 +79,31 @@ describe('removeAsset', function () { { const deprecatedCoverAssetsBitmap = await pool.deprecatedCoverAssetsBitmap(); - assert.equal(deprecatedCoverAssetsBitmap.toNumber(), 0); + expect(deprecatedCoverAssetsBitmap).to.be.equal(0, 'Unexpected deprecated cover assets bitmap'); } - await pool.removeAsset(1, true, { from: governance }); + await pool.connect(governance).removeAsset(1, true); const assetDetails = await pool.getAssetSwapDetails(dai.address); const { minAmount, maxAmount, maxSlippageRatio, lastSwapTime } = assetDetails; - assert.strictEqual(minAmount.toString(), '0'); - assert.strictEqual(maxAmount.toString(), '0'); - assert.strictEqual(maxSlippageRatio.toString(), '0'); - assert.strictEqual(lastSwapTime.toString(), '0'); + expect(minAmount).to.be.equal(0); + expect(maxAmount).to.be.equal(0); + expect(maxSlippageRatio).to.be.equal(0); + expect(lastSwapTime).to.be.equal(0); const expectedCoverAssets = [ETH, dai.address, coverToken.address]; const coverAssets = await pool.getCoverAssets(); - assert.deepEqual( - coverAssets.map(x => x.assetAddress), - expectedCoverAssets, - 'Unexpected assets found', - ); + expect(coverAssets.map(x => x.assetAddress)).to.be.deep.equal(expectedCoverAssets, 'Unexpected assets found'); { const deprecatedCoverAssetsBitmap = await pool.deprecatedCoverAssetsBitmap(); - assert.equal(deprecatedCoverAssetsBitmap.toNumber(), 0b10); + expect(deprecatedCoverAssetsBitmap).to.be.equal(0b10, 'Unexpected deprecated cover assets bitmap'); } const expectedInvestmentAssets = [stETH.address, investmentToken.address]; const investmentAssets = await pool.getInvestmentAssets(); - assert.deepEqual( - investmentAssets.map(x => x.assetAddress), + expect(investmentAssets.map(x => x.assetAddress)).to.be.deep.equal( expectedInvestmentAssets, 'Unexpected assets found', ); @@ -124,28 +114,27 @@ describe('removeAsset', function () { const assetDetails = await pool.getAssetSwapDetails(coverToken.address); const { minAmount, maxAmount, maxSlippageRatio, lastSwapTime } = assetDetails; - assert.strictEqual(minAmount.toString(), '1'); - assert.strictEqual(maxAmount.toString(), '2'); - assert.strictEqual(maxSlippageRatio.toString(), '3'); - assert.strictEqual(lastSwapTime.toString(), '0'); + expect(minAmount).to.be.equal(1); + expect(maxAmount).to.be.equal(2); + expect(maxSlippageRatio).to.be.equal(3); + expect(lastSwapTime).to.be.equal(0); } { // remove investment token - await pool.removeAsset(1, false, { from: governance }); + await pool.connect(governance).removeAsset(1, false); const assetDetails = await pool.getAssetSwapDetails(investmentToken.address); const { minAmount, maxAmount, maxSlippageRatio, lastSwapTime } = assetDetails; - assert.strictEqual(minAmount.toString(), '0'); - assert.strictEqual(maxAmount.toString(), '0'); - assert.strictEqual(maxSlippageRatio.toString(), '0'); - assert.strictEqual(lastSwapTime.toString(), '0'); + expect(minAmount).to.be.equal(0); + expect(maxAmount).to.be.equal(0); + expect(maxSlippageRatio).to.be.equal(0); + expect(lastSwapTime).to.be.equal(0); const expectedInvestmentAssets = [stETH.address]; const investmentAssets = await pool.getInvestmentAssets(); - assert.deepEqual( - investmentAssets.map(x => x.assetAddress), + expect(investmentAssets.map(x => x.assetAddress)).to.be.deep.equal( expectedInvestmentAssets, 'Unexpected assets found', ); @@ -156,15 +145,15 @@ describe('removeAsset', function () { const assetDetails = await pool.getAssetSwapDetails(stETH.address); const { minAmount, maxAmount, maxSlippageRatio, lastSwapTime } = assetDetails; - assert.strictEqual(minAmount.toString(), ether('24360').toString()); - assert.strictEqual(maxAmount.toString(), ether('32500').toString()); - assert.strictEqual(maxSlippageRatio.toString(), '0'); - assert.strictEqual(lastSwapTime.toString(), '1633425218'); + expect(minAmount).to.be.equal(parseEther('24360')); + expect(maxAmount).to.be.equal(parseEther('32500')); + expect(maxSlippageRatio).to.be.equal(0); + // this value is currently hardcoded in the Pool's constructor + expect(lastSwapTime).to.be.equal(1633425218); const expectedInvestmentAssets = [stETH.address]; const investmentAssets = await pool.getInvestmentAssets(); - assert.deepEqual( - investmentAssets.map(x => x.assetAddress), + expect(investmentAssets.map(x => x.assetAddress)).to.be.deep.equal( expectedInvestmentAssets, 'Unexpected assets found', ); diff --git a/test/unit/Pool/sellNXM.js b/test/unit/Pool/sellNXM.js index 4ac3043054..1d216b7540 100644 --- a/test/unit/Pool/sellNXM.js +++ b/test/unit/Pool/sellNXM.js @@ -1,145 +1,160 @@ -const { ether, expectRevert, expectEvent } = require('@openzeppelin/test-helpers'); -const { web3 } = require('hardhat'); -const { assert } = require('chai'); -const { BN } = web3.utils; +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { BigNumber } = ethers; +const { parseEther } = ethers.utils; const { Role } = require('../utils').constants; const { setNextBlockBaseFee } = require('../utils').evm; -const { percentageBN } = require('../utils').tokenPrice; -const [memberOne] = require('../utils').accounts.members; - -const P1MockMember = artifacts.require('P1MockMember'); +const { percentageBigNumber } = require('../utils').tokenPrice; describe('sellNXM', function () { it('reverts on sell that decreases the MCR% below 100%', async function () { const { pool, mcr, token } = this; + const { + members: [memberOne], + nonMembers: [fundSource], + } = this.accounts; - const mcrEth = ether('160000'); + const mcrEth = parseEther('160000'); const initialAssetValue = mcrEth; await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await fundSource.sendTransaction({ to: pool.address, value: initialAssetValue }); - const tokenAmountToSell = ether('1000'); - await token.mint(memberOne, tokenAmountToSell); + const tokenAmountToSell = parseEther('1000'); + await token.mint(memberOne.address, tokenAmountToSell); - await expectRevert(pool.sellNXM(tokenAmountToSell, '0', { from: memberOne }), 'MCR% cannot fall below 100%'); + await expect(pool.connect(memberOne).sellNXM(tokenAmountToSell, '0')).to.be.revertedWith( + 'Pool: MCR% cannot fall below 100%', + ); }); it('reverts on sell worth more than 5% of MCReth', async function () { const { pool, mcr, token } = this; + const { + members: [memberOne], + nonMembers: [fundSource], + } = this.accounts; - const mcrEth = ether('160000'); + const mcrEth = parseEther('160000'); const initialAssetValue = mcrEth; await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await fundSource.sendTransaction({ to: pool.address, value: initialAssetValue }); - const buyValue = percentageBN(mcrEth, 5); - await pool.buyNXM('1', { from: memberOne, value: buyValue }); - await pool.buyNXM('1', { from: memberOne, value: buyValue }); + const buyValue = percentageBigNumber(mcrEth, 5); + await pool.connect(memberOne).buyNXM('1', { value: buyValue }); + await pool.connect(memberOne).buyNXM('1', { value: buyValue }); - const entireBalance = await token.balanceOf(memberOne); - await expectRevert( - pool.sellNXM(entireBalance, '0', { from: memberOne }), - 'Sales worth more than 5% of MCReth are not allowed', + const entireBalance = await token.balanceOf(memberOne.address); + await expect(pool.connect(memberOne).sellNXM(entireBalance, '0')).to.be.revertedWith( + 'Pool: Sales worth more than 5% of MCReth are not allowed', ); }); it('reverts on sell that exceeds member balance', async function () { const { pool, mcr, token } = this; + const { + members: [memberOne], + nonMembers: [fundSource], + } = this.accounts; - const mcrEth = ether('160000'); + const mcrEth = parseEther('160000'); const initialAssetValue = mcrEth; await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await fundSource.sendTransaction({ to: pool.address, value: initialAssetValue }); - const buyValue = percentageBN(mcrEth, 5); - await pool.buyNXM('1', { from: memberOne, value: buyValue }); + const buyValue = percentageBigNumber(mcrEth, 5); + await pool.connect(memberOne).buyNXM('1', { value: buyValue }); - const entireBalance = await token.balanceOf(memberOne); - await expectRevert(pool.sellNXM(entireBalance.addn(1), '0', { from: memberOne }), 'Not enough balance'); + const entireBalance = await token.balanceOf(memberOne.address); + await expect(pool.connect(memberOne).sellNXM(entireBalance.add(1), '0')).to.be.revertedWith( + 'Pool: Not enough balance', + ); }); it('reverts on sell from member that is a contract whose fallback function reverts', async function () { const { pool, mcr, token, tokenController, memberRoles } = this; + const { + nonMembers: [fundSource], + } = this.accounts; + const P1MockMember = await ethers.getContractFactory('P1MockMember'); - const mcrEth = ether('160000'); - const initialAssetValue = percentageBN(mcrEth, 150); + const mcrEth = parseEther('160000'); + const initialAssetValue = percentageBigNumber(mcrEth, 150); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await fundSource.sendTransaction({ to: pool.address, value: initialAssetValue }); - const contractMember = await P1MockMember.new(pool.address, token.address, tokenController.address); + const contractMember = await P1MockMember.deploy(pool.address, token.address, tokenController.address); await memberRoles.setRole(contractMember.address, Role.Member); - const tokensToSell = ether('1'); + const tokensToSell = parseEther('1'); await token.mint(contractMember.address, tokensToSell); - await expectRevert(contractMember.sellNXM(tokensToSell), 'Pool: Sell transfer failed'); + await expect(contractMember.sellNXM(tokensToSell)).to.be.revertedWith('Pool: Sell transfer failed'); }); it('reverts on sell from member when ethOut < minEthOut', async function () { const { pool, mcr, token, tokenController } = this; + const { + members: [member], + nonMembers: [fundSource], + } = this.accounts; - const mcrEth = ether('160000'); - const initialAssetValue = percentageBN(mcrEth, 150); + const mcrEth = parseEther('160000'); + const initialAssetValue = percentageBigNumber(mcrEth, 150); await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await fundSource.sendTransaction({ to: pool.address, value: initialAssetValue }); - const member = memberOne; - - const tokensToSell = ether('1'); - await token.mint(member, tokensToSell); + const tokensToSell = parseEther('1'); + await token.mint(member.address, tokensToSell); const expectedEthValue = await pool.getEthForNXM(tokensToSell); - await token.approve(tokenController.address, tokensToSell, { - from: member, - }); - await expectRevert( - pool.sellNXM(tokensToSell, expectedEthValue.add(new BN(1)), { from: member }), - 'Pool: ethOut < minEthOut', - ); + await token.connect(member).approve(tokenController.address, tokensToSell); + await expect( + pool.connect(member).sellNXM(tokensToSell, expectedEthValue.add(BigNumber.from(1))), + ).to.be.revertedWith('Pool: ethOut < minEthOut'); }); it('burns tokens from member in exchange for ETH worth 1% of mcrEth', async function () { const { pool, mcr, token, tokenController } = this; + const { + members: [member], + nonMembers: [fundSource], + } = this.accounts; - const mcrEth = ether('160000'); + const mcrEth = parseEther('160000'); const initialAssetValue = mcrEth; await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await fundSource.sendTransaction({ to: pool.address, value: initialAssetValue }); - const member = memberOne; - - const buyValue = percentageBN(mcrEth, 1); - await pool.buyNXM('1', { from: member, value: buyValue }); - const tokensToSell = await token.balanceOf(member); + const buyValue = percentageBigNumber(mcrEth, 1); + await pool.connect(member).buyNXM('1', { value: buyValue }); + const tokensToSell = await token.balanceOf(member.address); const expectedEthValue = await pool.getEthForNXM(tokensToSell); - await token.approve(tokenController.address, tokensToSell, { from: member }); - const balancePreSell = await web3.eth.getBalance(member); - const nxmBalancePreSell = await token.balanceOf(member); + await token.connect(member).approve(tokenController.address, tokensToSell); + const balancePreSell = await ethers.provider.getBalance(member.address); + const nxmBalancePreSell = await token.balanceOf(member.address); await setNextBlockBaseFee('0'); - const sellTx = await pool.sellNXM(tokensToSell, expectedEthValue, { from: member, gasPrice: 0 }); - const nxmBalancePostSell = await token.balanceOf(member); - const balancePostSell = await web3.eth.getBalance(member); - const nxmBalanceDecrease = nxmBalancePreSell.sub(nxmBalancePostSell); - assert(nxmBalanceDecrease.toString(), tokensToSell.toString()); + await expect(pool.connect(member).sellNXM(tokensToSell, expectedEthValue, { gasPrice: 0 })) + .to.emit(pool, 'NXMSold') + .withArgs(member.address, tokensToSell, expectedEthValue); - const ethOut = new BN(balancePostSell).sub(new BN(balancePreSell)); - assert(ethOut.toString(), expectedEthValue.toString()); + const nxmBalancePostSell = await token.balanceOf(member.address); + const balancePostSell = await ethers.provider.getBalance(member.address); + + const nxmBalanceDecrease = nxmBalancePreSell.sub(nxmBalancePostSell); + expect(nxmBalanceDecrease).to.equal(tokensToSell); - await expectEvent(sellTx, 'NXMSold', { - member, - nxmIn: tokensToSell.toString(), - ethOut: expectedEthValue.toString(), - }); + const ethOut = BigNumber.from(balancePostSell).sub(BigNumber.from(balancePreSell)); + expect(ethOut).to.equal(expectedEthValue); }); }); diff --git a/test/unit/Pool/sellNXMTokens.js b/test/unit/Pool/sellNXMTokens.js index e5c9dc2d78..6f33d3e178 100644 --- a/test/unit/Pool/sellNXMTokens.js +++ b/test/unit/Pool/sellNXMTokens.js @@ -1,48 +1,47 @@ -const { ether, expectEvent } = require('@openzeppelin/test-helpers'); -const { web3 } = require('hardhat'); -const { assert } = require('chai'); -const { BN } = web3.utils; +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { BigNumber } = ethers; +const { parseEther } = ethers.utils; const { setNextBlockBaseFee } = require('../utils').evm; -const { percentageBN } = require('../utils').tokenPrice; -const [memberOne] = require('../utils').accounts.members; +const { percentageBigNumber } = require('../utils').tokenPrice; describe('sellNXMTokens', function () { it('burns tokens from member in exchange for ETH worth 1% of mcrEth', async function () { const { pool, mcr, token, tokenController } = this; + const { + members: [member], + nonMembers: [fundSource], + } = this.accounts; - const mcrEth = ether('160000'); + const mcrEth = parseEther('160000'); const initialAssetValue = mcrEth; await mcr.setMCR(mcrEth); - await pool.sendTransaction({ value: initialAssetValue }); + await fundSource.sendTransaction({ value: initialAssetValue, to: pool.address }); - const member = memberOne; - - const buyValue = percentageBN(mcrEth, 1); - await pool.buyNXM('1', { from: member, value: buyValue }); - const tokensToSell = await token.balanceOf(member); + const buyValue = percentageBigNumber(mcrEth, 1); + await pool.connect(member).buyNXM('1', { value: buyValue }); + const tokensToSell = await token.balanceOf(member.address); const expectedEthValue = await pool.getEthForNXM(tokensToSell); - await token.approve(tokenController.address, tokensToSell, { from: member }); - const balancePreSell = await web3.eth.getBalance(member); - const nxmBalancePreSell = await token.balanceOf(member); + await token.connect(member).approve(tokenController.address, tokensToSell); + const balancePreSell = await ethers.provider.getBalance(member.address); + const nxmBalancePreSell = await token.balanceOf(member.address); await setNextBlockBaseFee('0'); - const sellTx = await pool.sellNXMTokens(tokensToSell, { from: member, gasPrice: 0 }); - const nxmBalancePostSell = await token.balanceOf(member); - const balancePostSell = await web3.eth.getBalance(member); - const nxmBalanceDecrease = nxmBalancePreSell.sub(nxmBalancePostSell); - assert(nxmBalanceDecrease.toString(), tokensToSell.toString()); + await expect(pool.connect(member).sellNXMTokens(tokensToSell, { gasPrice: 0 })) + .to.emit(pool, 'NXMSold') + .withArgs(member.address, tokensToSell, expectedEthValue); - const ethOut = new BN(balancePostSell).sub(new BN(balancePreSell)); - assert(ethOut.toString(), expectedEthValue.toString()); + const nxmBalancePostSell = await token.balanceOf(member.address); + const balancePostSell = await ethers.provider.getBalance(member.address); + + const nxmBalanceDecrease = nxmBalancePreSell.sub(nxmBalancePostSell); + expect(nxmBalanceDecrease).to.equal(tokensToSell); - await expectEvent(sellTx, 'NXMSold', { - member, - nxmIn: tokensToSell.toString(), - ethOut: expectedEthValue.toString(), - }); + const ethOut = BigNumber.from(balancePostSell).sub(BigNumber.from(balancePreSell)); + expect(ethOut).to.equal(expectedEthValue); }); }); diff --git a/test/unit/Pool/sendPayout.js b/test/unit/Pool/sendPayout.js index 5b95bda7e3..17ae54d093 100644 --- a/test/unit/Pool/sendPayout.js +++ b/test/unit/Pool/sendPayout.js @@ -1,26 +1,24 @@ -const { ether } = require('@openzeppelin/test-helpers'); -const { web3 } = require('hardhat'); -const { toBN } = web3.utils; -const { assert } = require('chai'); +const { ethers } = require('hardhat'); +const { parseEther } = ethers.utils; +const { expect } = require('chai'); const { PoolAsset } = require('../../../lib/constants'); -const { - internalContracts: [internal], - generalPurpose: [destination], -} = require('../utils').accounts; - describe('sendPayout', function () { it('transfers ERC20 payout to destination', async function () { const { pool, dai } = this; + const { + internalContracts: [internal], + generalPurpose: [destination], + } = this.accounts; - const tokenAmount = ether('100000'); + const tokenAmount = parseEther('100000'); await dai.mint(pool.address, tokenAmount); - const amountToTransfer = tokenAmount.divn(2); + const amountToTransfer = tokenAmount.div(2); - await pool.sendPayout(PoolAsset.DAI, destination, amountToTransfer, { from: internal }); - const destinationBalance = await dai.balanceOf(destination); - assert.equal(destinationBalance.toString(), amountToTransfer.toString()); + await pool.connect(internal).sendPayout(PoolAsset.DAI, destination.address, amountToTransfer); + const destinationBalance = await dai.balanceOf(destination.address); + expect(destinationBalance).to.be.equal(amountToTransfer); const poolBalance = await dai.balanceOf(pool.address); assert.equal(poolBalance.toString(), tokenAmount.sub(amountToTransfer).toString()); @@ -28,18 +26,22 @@ describe('sendPayout', function () { it('transfers ETH payout to destination', async function () { const { pool } = this; + const { + internalContracts: [internal], + nonMembers: [destination, fundSource], + } = this.accounts; - const ethAmount = ether('10000'); - await pool.sendTransaction({ value: ethAmount }); + const ethAmount = parseEther('10000'); + await fundSource.sendTransaction({ to: pool.address, value: ethAmount }); - const amountToTransfer = ethAmount.divn(2); + const amountToTransfer = ethAmount.div(2); - const destinationBalancePrePayout = toBN(await web3.eth.getBalance(destination)); - await pool.sendPayout(PoolAsset.ETH, destination, amountToTransfer, { from: internal }); - const destinationBalance = toBN(await web3.eth.getBalance(destination)); - assert.equal(destinationBalance.sub(destinationBalancePrePayout).toString(), amountToTransfer.toString()); + const destinationBalancePrePayout = await ethers.provider.getBalance(destination.address); + await pool.connect(internal).sendPayout(PoolAsset.ETH, destination.address, amountToTransfer); + const destinationBalance = await ethers.provider.getBalance(destination.address); + expect(destinationBalance.sub(destinationBalancePrePayout)).to.be.equal(amountToTransfer); - const poolBalance = toBN(await web3.eth.getBalance(pool.address)); - assert.equal(poolBalance.toString(), ethAmount.sub(amountToTransfer).toString()); + const poolBalance = await ethers.provider.getBalance(pool.address); + expect(poolBalance).to.be.equal(ethAmount.sub(amountToTransfer)); }); }); diff --git a/test/unit/Pool/setSwapDetailsLastSwapTime.js b/test/unit/Pool/setSwapDetailsLastSwapTime.js index 2bf9e20a15..c7a37d0b3c 100644 --- a/test/unit/Pool/setSwapDetailsLastSwapTime.js +++ b/test/unit/Pool/setSwapDetailsLastSwapTime.js @@ -1,73 +1,71 @@ -const { ether } = require('@openzeppelin/test-helpers'); -const { expectRevert } = require('@openzeppelin/test-helpers'); -const { assert } = require('chai'); -const { web3, artifacts } = require('hardhat'); - -const { - governanceContracts: [governance], - generalPurpose: [arbitraryCaller], - defaultSender, -} = require('../utils').accounts; -const { hex } = require('../utils').helpers; -const { BN } = web3.utils; - -const PriceFeedOracle = artifacts.require('PriceFeedOracle'); -const ChainlinkAggregatorMock = artifacts.require('ChainlinkAggregatorMock'); -const ERC20Mock = artifacts.require('ERC20Mock'); +const { expect } = require('chai'); +const { ethers } = require('hardhat'); +const { BigNumber } = ethers; +const { parseEther } = ethers.utils; + +const { toBytes8 } = require('../utils').helpers; describe('setSwapDetailsLastSwapTime', function () { before(async function () { const { pool, dai, stETH, chainlinkDAI, chainlinkSteth } = this; + const [governance] = this.accounts.governanceContracts; + + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const ChainlinkAggregatorMock = await ethers.getContractFactory('ChainlinkAggregatorMock'); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); - const otherToken = await ERC20Mock.new(); + const otherToken = await ERC20Mock.deploy(); - const chainlinkNewAsset = await ChainlinkAggregatorMock.new(); - await chainlinkNewAsset.setLatestAnswer(new BN((1e18).toString())); + const chainlinkNewAsset = await ChainlinkAggregatorMock.deploy(); + await chainlinkNewAsset.setLatestAnswer(BigNumber.from((1e18).toString())); - const priceFeedOracle = await PriceFeedOracle.new( + const priceFeedOracle = await PriceFeedOracle.deploy( [dai.address, stETH.address, otherToken.address], [chainlinkDAI.address, chainlinkSteth.address, chainlinkNewAsset.address], [18, 18, 18], ); - await pool.updateAddressParameters(hex('PRC_FEED'), priceFeedOracle.address, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('PRC_FEED'), priceFeedOracle.address); this.otherToken = otherToken; }); it('set last swap time for asset', async function () { const { pool, otherToken } = this; + const { + governanceContracts: [governance], + members: [member], + } = this.accounts; - const tokenAmount = ether('100000'); - await pool.addAsset(otherToken.address, 18, '0', '0', 100, true, { - from: governance, - }); + const tokenAmount = parseEther('100000'); + await pool.connect(governance).addAsset(otherToken.address, 18, '0', '0', 100, true); await otherToken.mint(pool.address, tokenAmount); - const lastSwapTime = '11512651'; + const lastSwapTime = 11512651; - await pool.updateAddressParameters(hex('SWP_OP'), defaultSender, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('SWP_OP'), member.address); - await pool.setSwapDetailsLastSwapTime(otherToken.address, lastSwapTime); + await pool.connect(member).setSwapDetailsLastSwapTime(otherToken.address, lastSwapTime); const swapDetails = await pool.swapDetails(otherToken.address); - assert.equal(swapDetails.lastSwapTime.toString(), lastSwapTime); + expect(swapDetails.lastSwapTime).to.equal(lastSwapTime); }); it('revers if not called by swap operator', async function () { const { pool, otherToken } = this; + const { + governanceContracts: [governance], + members: [arbitraryCaller], + } = this.accounts; - const tokenAmount = ether('100000'); - await pool.addAsset(otherToken.address, 18, '0', '0', 100, true, { - from: governance, - }); + const tokenAmount = parseEther('100000'); + await pool.connect(governance).addAsset(otherToken.address, 18, '0', '0', 100, true); await otherToken.mint(pool.address, tokenAmount); const lastSwapTime = '11512651'; - await expectRevert( - pool.setSwapDetailsLastSwapTime(otherToken.address, lastSwapTime, { from: arbitraryCaller }), - 'Pool: Not swapOperator', - ); + await expect( + pool.connect(arbitraryCaller).setSwapDetailsLastSwapTime(otherToken.address, lastSwapTime), + ).to.be.revertedWith('Pool: Not swapOperator'); }); }); diff --git a/test/unit/Pool/setSwapValue.js b/test/unit/Pool/setSwapValue.js index 6d763d0089..56b233e91c 100644 --- a/test/unit/Pool/setSwapValue.js +++ b/test/unit/Pool/setSwapValue.js @@ -1,37 +1,38 @@ -const { web3 } = require('hardhat'); +const { ethers } = require('hardhat'); const { expect } = require('chai'); -const { BN } = web3.utils; -const { expectRevert } = require('@openzeppelin/test-helpers'); - -const { hex } = require('../utils').helpers; - -const { - governanceContracts: [governance], - defaultSender, -} = require('../utils').accounts; +const { BigNumber } = ethers; +const { toBytes8 } = require('../utils').helpers; describe('setSwapValue', function () { it('is only callabe by swap operator', async function () { const { pool } = this; + const { + governanceContracts: [governance], + nonMembers: [swapOperator], + } = this.accounts; // Not calling from swap operator reverts - await expectRevert(pool.setSwapValue(new BN('123')), 'Pool: Not swapOperator'); + await expect(pool.setSwapValue(BigNumber.from('123'))).to.be.revertedWith('Pool: Not swapOperator'); - // Set current signer as swap operator - await pool.updateAddressParameters(hex('SWP_OP'), defaultSender, { from: governance }); + // Set swap operator + await pool.connect(governance).updateAddressParameters(toBytes8('SWP_OP'), swapOperator.address); // Call should succeed - await pool.setSwapValue(new BN('123')); + await pool.connect(swapOperator).setSwapValue(BigNumber.from('123')); }); it('sets the swapValue value', async function () { const { pool } = this; - expect((await pool.swapValue()).toString()).to.eq('0'); + const { + governanceContracts: [governance], + nonMembers: [swapOperator], + } = this.accounts; - // Set current signer as swap operator and set swap value - await pool.updateAddressParameters(hex('SWP_OP'), defaultSender, { from: governance }); - await pool.setSwapValue(new BN('123')); + expect(await pool.swapValue()).to.eq(0); + // Set swap operator and set swap value + await pool.connect(governance).updateAddressParameters(toBytes8('SWP_OP'), swapOperator.address); + await pool.connect(swapOperator).setSwapValue(123); - expect((await pool.swapValue()).toString()).to.eq('123'); + expect(await pool.swapValue()).to.eq(123); }); }); diff --git a/test/unit/Pool/setup.js b/test/unit/Pool/setup.js index 013d2ae6b5..5268cfa806 100644 --- a/test/unit/Pool/setup.js +++ b/test/unit/Pool/setup.js @@ -1,70 +1,72 @@ -const { artifacts, web3 } = require('hardhat'); -const { ether } = require('@openzeppelin/test-helpers'); +const { ethers } = require('hardhat'); +const { BigNumber } = ethers; +const { parseEther } = ethers.utils; +const { WeiPerEther } = ethers.constants; const { Role } = require('../utils').constants; -const accounts = require('../utils').accounts; -const { hex } = require('../utils').helpers; - -const { BN } = web3.utils; +const { getAccounts } = require('../../utils/accounts'); +const { toBytes2 } = require('../utils').helpers; async function setup() { - const MasterMock = artifacts.require('MasterMock'); - const TokenController = artifacts.require('TokenControllerMock'); - const TokenMock = artifacts.require('NXMTokenMock'); - const Pool = artifacts.require('Pool'); - const MCR = artifacts.require('P1MockMCR'); - const ERC20Mock = artifacts.require('ERC20Mock'); - const ERC20BlacklistableMock = artifacts.require('ERC20BlacklistableMock'); - const PriceFeedOracle = artifacts.require('PriceFeedOracle'); - const ChainlinkAggregatorMock = artifacts.require('ChainlinkAggregatorMock'); - const P1MockSwapOperator = artifacts.require('P1MockSwapOperator'); - const MemberRolesMock = await artifacts.require('MemberRolesMock'); - - const master = await MasterMock.new(); - const dai = await ERC20Mock.new(); - const stETH = await ERC20BlacklistableMock.new(); - const otherAsset = await ERC20Mock.new(); - const memberRoles = await MemberRolesMock.new(); - - const ethToDaiRate = new BN((394.59 * 1e18).toString()); - const daiToEthRate = new BN(10).pow(new BN(36)).div(ethToDaiRate); - - const chainlinkDAI = await ChainlinkAggregatorMock.new(); + // rewrite above artifact imports using ethers.js + const MasterMock = await ethers.getContractFactory('MasterMock'); + const TokenController = await ethers.getContractFactory('TokenControllerMock'); + const TokenMock = await ethers.getContractFactory('NXMTokenMock'); + const Pool = await ethers.getContractFactory('Pool'); + const MCR = await ethers.getContractFactory('P1MockMCR'); + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const ERC20BlacklistableMock = await ethers.getContractFactory('ERC20BlacklistableMock'); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); + const ChainlinkAggregatorMock = await ethers.getContractFactory('ChainlinkAggregatorMock'); + const P1MockSwapOperator = await ethers.getContractFactory('P1MockSwapOperator'); + const MemberRolesMock = await ethers.getContractFactory('MemberRolesMock'); + + const master = await MasterMock.deploy(); + const dai = await ERC20Mock.deploy(); + const stETH = await ERC20BlacklistableMock.deploy(); + const otherAsset = await ERC20Mock.deploy(); + const memberRoles = await MemberRolesMock.deploy(); + + const ethToDaiRate = parseEther('394.59'); + const daiToEthRate = BigNumber.from(10).pow(36).div(ethToDaiRate); + + const chainlinkDAI = await ChainlinkAggregatorMock.deploy(); await chainlinkDAI.setLatestAnswer(daiToEthRate); - const chainlinkSteth = await ChainlinkAggregatorMock.new(); - await chainlinkSteth.setLatestAnswer(new BN((1e18).toString())); - const chainlinkNewAsset = await ChainlinkAggregatorMock.new(); - await chainlinkNewAsset.setLatestAnswer(new BN((1e18).toString())); + const chainlinkSteth = await ChainlinkAggregatorMock.deploy(); + await chainlinkSteth.setLatestAnswer(WeiPerEther); + const chainlinkNewAsset = await ChainlinkAggregatorMock.deploy(); + await chainlinkNewAsset.setLatestAnswer(WeiPerEther); - const priceFeedOracle = await PriceFeedOracle.new( + const priceFeedOracle = await PriceFeedOracle.deploy( [dai.address, stETH.address, otherAsset.address], [chainlinkDAI.address, chainlinkSteth.address, chainlinkNewAsset.address], [18, 18, 18], ); - const swapOperator = await P1MockSwapOperator.new(); + const swapOperator = await P1MockSwapOperator.deploy(); + const accounts = await getAccounts(); - const pool = await Pool.new( - accounts.defaultSender, // master: it is changed a few lines below + const pool = await Pool.deploy( + accounts.defaultSender.address, // master: it is changed a few lines below priceFeedOracle.address, swapOperator.address, // we do not test swaps here dai.address, stETH.address, ); - await master.setLatestAddress(hex('P1'), pool.address); + await master.setLatestAddress(toBytes2('P1'), pool.address); - const token = await TokenMock.new(); - const mcr = await MCR.new(); - const tokenController = await TokenController.new(); - await token.mint(accounts.defaultSender, ether('10000')); + const token = await TokenMock.deploy(); + const mcr = await MCR.deploy(); + const tokenController = await TokenController.deploy(); + await token.mint(accounts.defaultSender.address, parseEther('10000')); // set contract addresses await master.setTokenAddress(token.address); - await master.setLatestAddress(hex('P1'), pool.address); - await master.setLatestAddress(hex('MC'), mcr.address); - await master.setLatestAddress(hex('TC'), tokenController.address); - await master.setLatestAddress(hex('MR'), memberRoles.address); + await master.setLatestAddress(toBytes2('P1'), pool.address); + await master.setLatestAddress(toBytes2('MC'), mcr.address); + await master.setLatestAddress(toBytes2('TC'), tokenController.address); + await master.setLatestAddress(toBytes2('MR'), memberRoles.address); const contractsToUpdate = [mcr, pool, tokenController]; @@ -77,27 +79,28 @@ async function setup() { await master.enrollInternal(pool.address); for (const member of accounts.members) { - await master.enrollMember(member, Role.Member); - await memberRoles.setRole(member, Role.Member); + await master.enrollMember(member.address, Role.Member); + await memberRoles.setRole(member.address, Role.Member); } for (const advisoryBoardMember of accounts.advisoryBoardMembers) { - await master.enrollMember(advisoryBoardMember, Role.AdvisoryBoard); - await memberRoles.setRole(advisoryBoardMember, Role.AdvisoryBoard); + await master.enrollMember(advisoryBoardMember.address, Role.AdvisoryBoard); + await memberRoles.setRole(advisoryBoardMember.address, Role.AdvisoryBoard); } for (const internalContract of accounts.internalContracts) { - await master.enrollInternal(internalContract); + await master.enrollInternal(internalContract.address); } // there is only one in reality, but it doesn't matter for (const governanceContract of accounts.governanceContracts) { - await master.enrollGovernance(governanceContract); + await master.enrollGovernance(governanceContract.address); } // initialize token await token.setOperator(tokenController.address); + this.accounts = accounts; this.master = master; this.token = token; this.pool = pool; @@ -108,6 +111,7 @@ async function setup() { this.chainlinkDAI = chainlinkDAI; this.chainlinkSteth = chainlinkSteth; this.swapOperator = swapOperator; + this.priceFeedOracle = priceFeedOracle; this.stETH = stETH; this.otherAsset = otherAsset; } diff --git a/test/unit/Pool/transferAsset.js b/test/unit/Pool/transferAsset.js index d48a0df62d..eced7826b5 100644 --- a/test/unit/Pool/transferAsset.js +++ b/test/unit/Pool/transferAsset.js @@ -1,114 +1,129 @@ -const { ether } = require('@openzeppelin/test-helpers'); -const { expectRevert } = require('@openzeppelin/test-helpers'); -const { web3, artifacts } = require('hardhat'); -const { assert } = require('chai'); -const { BN } = web3.utils; -const { hex } = require('../utils').helpers; -const { - governanceContracts: [governance], - generalPurpose: [destination, arbitraryCaller], -} = require('../utils').accounts; - -const ERC20Mock = artifacts.require('ERC20Mock'); +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { BigNumber } = ethers; +const { parseEther } = ethers.utils; +const { toBytes8 } = require('../utils').helpers; describe('transferAsset', function () { before(async function () { const { pool, dai, stETH, chainlinkDAI, chainlinkSteth } = this; + const { + governanceContracts: [governance], + } = this.accounts; - const ChainlinkAggregatorMock = artifacts.require('ChainlinkAggregatorMock'); - const PriceFeedOracle = artifacts.require('PriceFeedOracle'); + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const ChainlinkAggregatorMock = await ethers.getContractFactory('ChainlinkAggregatorMock'); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); - const otherToken = await ERC20Mock.new(); - const chainlinkNewAsset = await ChainlinkAggregatorMock.new(); - await chainlinkNewAsset.setLatestAnswer(new BN((1e18).toString())); + const otherToken = await ERC20Mock.deploy(); + const chainlinkNewAsset = await ChainlinkAggregatorMock.deploy(); + await chainlinkNewAsset.setLatestAnswer(BigNumber.from((1e18).toString())); - const priceFeedOracle = await PriceFeedOracle.new( + const priceFeedOracle = await PriceFeedOracle.deploy( [dai.address, stETH.address, otherToken.address], [chainlinkDAI.address, chainlinkSteth.address, chainlinkNewAsset.address], [18, 18, 18], ); - await pool.updateAddressParameters(hex('PRC_FEED'), priceFeedOracle.address, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('PRC_FEED'), priceFeedOracle.address); this.otherToken = otherToken; }); it('transfers added ERC20 asset to destination', async function () { const { pool, otherToken } = this; + const { + governanceContracts: [governance], + nonMembers: [destination], + } = this.accounts; - const tokenAmount = ether('100000'); - await pool.addAsset(otherToken.address, 18, '0', '0', 100 /* 1% */, true, { - from: governance, - }); + const tokenAmount = parseEther('100000'); + await pool.connect(governance).addAsset(otherToken.address, 18, '0', '0', 100 /* 1% */, true); await otherToken.mint(pool.address, tokenAmount); - const amountToTransfer = tokenAmount.divn(2); + const amountToTransfer = tokenAmount.div(2); - await pool.transferAsset(otherToken.address, destination, amountToTransfer, { from: governance }); - const destinationBalance = await otherToken.balanceOf(destination); - assert.equal(destinationBalance.toString(), amountToTransfer.toString()); + await pool.connect(governance).transferAsset(otherToken.address, destination.address, amountToTransfer); + const destinationBalance = await otherToken.balanceOf(destination.address); + expect(destinationBalance).to.eq(amountToTransfer); const poolBalance = await otherToken.balanceOf(pool.address); - assert.equal(poolBalance.toString(), tokenAmount.sub(amountToTransfer).toString()); + expect(poolBalance).to.eq(tokenAmount.sub(amountToTransfer)); }); it('transfers arbitrary ERC20 asset in the Pool to destination', async function () { const { pool } = this; - - const tokenAmount = ether('100000'); - const otherToken = await ERC20Mock.new(); + const { + governanceContracts: [governance], + nonMembers: [destination], + } = this.accounts; + + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const tokenAmount = parseEther('100000'); + const otherToken = await ERC20Mock.deploy(); await otherToken.mint(pool.address, tokenAmount); - const amountToTransfer = tokenAmount.divn(2); + const amountToTransfer = tokenAmount.div(2); - await pool.transferAsset(otherToken.address, destination, amountToTransfer, { from: governance }); - const destinationBalance = await otherToken.balanceOf(destination); - assert.equal(destinationBalance.toString(), amountToTransfer.toString()); + await pool.connect(governance).transferAsset(otherToken.address, destination.address, amountToTransfer); + const destinationBalance = await otherToken.balanceOf(destination.address); + expect(destinationBalance).to.eq(amountToTransfer); const poolBalance = await otherToken.balanceOf(pool.address); - assert.equal(poolBalance.toString(), tokenAmount.sub(amountToTransfer).toString()); + expect(poolBalance).to.eq(tokenAmount.sub(amountToTransfer)); }); it('transfers entire balance of arbitrary ERC20 asset in the Pool if amount < balance', async function () { const { pool } = this; + const { + governanceContracts: [governance], + nonMembers: [destination], + } = this.accounts; - const tokenAmount = ether('100000'); - const otherToken = await ERC20Mock.new(); + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const tokenAmount = parseEther('100000'); + const otherToken = await ERC20Mock.deploy(); await otherToken.mint(pool.address, tokenAmount); - const amountToTransfer = tokenAmount.addn(1); + const amountToTransfer = tokenAmount.add(1); - await pool.transferAsset(otherToken.address, destination, amountToTransfer, { from: governance }); + await pool.connect(governance).transferAsset(otherToken.address, destination.address, amountToTransfer); - const destinationBalance = await otherToken.balanceOf(destination); - assert.equal(destinationBalance.toString(), tokenAmount.toString()); + const destinationBalance = await otherToken.balanceOf(destination.address); + expect(destinationBalance).to.eq(tokenAmount); const poolBalance = await otherToken.balanceOf(pool.address); - assert.equal(poolBalance.toString(), '0'); + expect(poolBalance).to.eq(0); }); it('reverts on asset transfer if asset maxAmount > 0', async function () { const { pool, otherToken } = this; + const { + governanceContracts: [governance], + nonMembers: [destination], + } = this.accounts; - const tokenAmount = ether('100000'); - await pool.addAsset(otherToken.address, 18, '0', '1', 100 /* 1% */, true, { - from: governance, - }); + const tokenAmount = parseEther('100000'); + await pool.connect(governance).addAsset(otherToken.address, 18, '0', '1', 100 /* 1% */, true); await otherToken.mint(pool.address, tokenAmount); - await expectRevert( - pool.transferAsset(otherToken.address, destination, tokenAmount, { from: governance }), - 'Pool: Max not zero', - ); + await expect( + pool.connect(governance).transferAsset(otherToken.address, destination.address, tokenAmount), + ).to.be.revertedWith('Pool: Max not zero'); }); it('reverts on asset transfer if caller is not authorized to govern', async function () { const { pool } = this; - - const tokenAmount = ether('100000'); - const otherToken = await ERC20Mock.new(); + const { + governanceContracts: [governance], + nonMembers: [destination], + } = this.accounts; + + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const tokenAmount = parseEther('100000'); + const otherToken = await ERC20Mock.deploy(); await otherToken.mint(pool.address, tokenAmount); - await expectRevert( - pool.transferAsset(otherToken.address, destination, tokenAmount, { from: arbitraryCaller }), + await expect( + pool.connect(governance).transferAsset(otherToken.address, destination.address, tokenAmount), 'Caller is not authorized to govern', ); }); diff --git a/test/unit/Pool/transferAssetToSwapOperator.js b/test/unit/Pool/transferAssetToSwapOperator.js index 86240f7a25..7840a021f3 100644 --- a/test/unit/Pool/transferAssetToSwapOperator.js +++ b/test/unit/Pool/transferAssetToSwapOperator.js @@ -1,75 +1,75 @@ -const { ether } = require('@openzeppelin/test-helpers'); -const { expectRevert } = require('@openzeppelin/test-helpers'); -const { assert } = require('chai'); -const { web3, artifacts } = require('hardhat'); - -const { - governanceContracts: [governance], - generalPurpose: [arbitraryCaller], -} = require('../utils').accounts; -const { hex } = require('../utils').helpers; -const { BN } = web3.utils; - -const PriceFeedOracle = artifacts.require('PriceFeedOracle'); -const ChainlinkAggregatorMock = artifacts.require('ChainlinkAggregatorMock'); -const ERC20Mock = artifacts.require('ERC20Mock'); +const { expect } = require('chai'); +const { ethers } = require('hardhat'); +const { BigNumber } = ethers; +const { parseEther } = ethers.utils; +const { toBytes8 } = require('../utils').helpers; describe('transferAssetToSwapOperator', function () { before(async function () { const { pool, dai, stETH, chainlinkDAI, chainlinkSteth } = this; + const { + governanceContracts: [governance], + } = this.accounts; - const otherToken = await ERC20Mock.new(); + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const ChainlinkAggregatorMock = await ethers.getContractFactory('ChainlinkAggregatorMock'); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); - const chainlinkNewAsset = await ChainlinkAggregatorMock.new(); - await chainlinkNewAsset.setLatestAnswer(new BN((1e18).toString())); + const otherToken = await ERC20Mock.deploy(); - const priceFeedOracle = await PriceFeedOracle.new( + const chainlinkNewAsset = await ChainlinkAggregatorMock.deploy(); + await chainlinkNewAsset.setLatestAnswer(BigNumber.from((1e18).toString())); + + const priceFeedOracle = await PriceFeedOracle.deploy( [dai.address, stETH.address, otherToken.address], [chainlinkDAI.address, chainlinkSteth.address, chainlinkNewAsset.address], [18, 18, 18], ); - await pool.updateAddressParameters(hex('PRC_FEED'), priceFeedOracle.address, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('PRC_FEED'), priceFeedOracle.address); this.otherToken = otherToken; }); it('transfers added ERC20 asset to swap operator', async function () { const { pool, otherToken } = this; + const { + governanceContracts: [governance], + nonMembers: [arbitraryCaller], + } = this.accounts; - const tokenAmount = ether('100000'); - await pool.addAsset(otherToken.address, 18, '0', '0', 100 /* 1% */, true, { - from: governance, - }); + const tokenAmount = parseEther('100000'); + await pool.connect(governance).addAsset(otherToken.address, 18, '0', '0', 100 /* 1% */, true); await otherToken.mint(pool.address, tokenAmount); - const amountToTransfer = tokenAmount.divn(2); + const amountToTransfer = tokenAmount.div(2); const tempSwapOperator = arbitraryCaller; - await pool.updateAddressParameters(hex('SWP_OP'), tempSwapOperator, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('SWP_OP'), tempSwapOperator.address); - await pool.transferAssetToSwapOperator(otherToken.address, amountToTransfer, { from: tempSwapOperator }); - const destinationBalance = await otherToken.balanceOf(tempSwapOperator); - assert.equal(destinationBalance.toString(), amountToTransfer.toString()); + await pool.connect(tempSwapOperator).transferAssetToSwapOperator(otherToken.address, amountToTransfer); + const destinationBalance = await otherToken.balanceOf(tempSwapOperator.address); + expect(destinationBalance).to.eq(amountToTransfer); const poolBalance = await otherToken.balanceOf(pool.address); - assert.equal(poolBalance.toString(), tokenAmount.sub(amountToTransfer).toString()); + expect(poolBalance).to.eq(tokenAmount.sub(amountToTransfer)); }); it('revers if not called by swap operator', async function () { const { pool, otherToken } = this; + const { + governanceContracts: [governance], + nonMembers: [arbitraryCaller], + } = this.accounts; - const tokenAmount = ether('100000'); - await pool.addAsset(otherToken.address, 18, '0', '0', 100 /* 1% */, true, { - from: governance, - }); + const tokenAmount = parseEther('100000'); + await pool.connect(governance).addAsset(otherToken.address, 18, '0', '0', 100 /* 1% */, true); await otherToken.mint(pool.address, tokenAmount); - const amountToTransfer = tokenAmount.divn(2); + const amountToTransfer = tokenAmount.div(2); - await expectRevert( - pool.transferAssetToSwapOperator(otherToken.address, amountToTransfer, { from: arbitraryCaller }), - 'Pool: Not swapOperator', - ); + await expect( + pool.connect(arbitraryCaller).transferAssetToSwapOperator(otherToken.address, amountToTransfer), + ).to.be.revertedWith('Pool: Not swapOperator'); }); }); diff --git a/test/unit/Pool/updateParameters.js b/test/unit/Pool/updateParameters.js index 473bf230fd..e7c0252585 100644 --- a/test/unit/Pool/updateParameters.js +++ b/test/unit/Pool/updateParameters.js @@ -1,43 +1,44 @@ -const { assert } = require('chai'); -const { expectRevert } = require('@openzeppelin/test-helpers'); -const { artifacts } = require('hardhat'); +const { expect } = require('chai'); +const { ethers } = require('hardhat'); -const accounts = require('../utils').accounts; -const { hex } = require('../utils').helpers; +const { toBytes8 } = require('../utils').helpers; const { PoolUintParamType, PoolAddressParamType } = require('../utils').constants; -const PriceFeedOracle = artifacts.require('PriceFeedOracle'); - -const { - nonMembers: [nonMember], - members: [member], - advisoryBoardMembers: [advisoryBoardMember], - internalContracts: [internalContract], - governanceContracts: [governanceContract], - generalPurpose: [generalPurpose], -} = accounts; - describe('updateUintParameters', function () { it('should revert when called by non governance addresses', async function () { const { pool } = this; + const { + nonMembers: [nonMember], + members: [member], + advisoryBoardMembers: [advisoryBoardMember], + internalContracts: [internalContract], + } = this.accounts; const param = PoolUintParamType.minPoolEth; const nonGov = [nonMember, member, advisoryBoardMember, internalContract]; for (const address of nonGov) { - await expectRevert(pool.updateUintParameters(param, 0, { from: address }), 'Caller is not authorized to govern'); + await expect(pool.connect(address).updateUintParameters(param, 0)).to.be.revertedWith( + 'Caller is not authorized to govern', + ); } }); }); describe('updateAddressParameters', function () { it('should revert when called by non governance addresses', async function () { + const { + nonMembers: [nonMember], + members: [member], + advisoryBoardMembers: [advisoryBoardMember], + internalContracts: [internalContract], + generalPurpose: [generalPurpose], + } = this.accounts; const { pool } = this; const param = PoolAddressParamType.priceFeedOracle; const nonGov = [nonMember, member, advisoryBoardMember, internalContract]; for (const address of nonGov) { - await expectRevert( - pool.updateAddressParameters(param, generalPurpose, { from: address }), + await expect(pool.connect(address).updateAddressParameters(param, generalPurpose.address)).to.be.revertedWith( 'Caller is not authorized to govern', ); } @@ -45,57 +46,72 @@ describe('updateAddressParameters', function () { it('should revert when called with a PRC_FEED oracle parameter that lacks an investment asset', async function () { const { pool, dai, chainlinkDAI } = this; + const { + governanceContracts: [governanceContract], + } = this.accounts; - const priceFeedOracle = await PriceFeedOracle.new([dai.address], [chainlinkDAI.address], [18]); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); + const priceFeedOracle = await PriceFeedOracle.deploy([dai.address], [chainlinkDAI.address], [18]); - await expectRevert( - pool.updateAddressParameters(hex('PRC_FEED'), priceFeedOracle.address, { from: governanceContract }), - 'Pool: Oracle lacks asset', - ); + await expect( + pool.connect(governanceContract).updateAddressParameters(toBytes8('PRC_FEED'), priceFeedOracle.address), + ).to.be.revertedWith('Pool: Oracle lacks asset'); }); it('should revert when called with a PRC_FEED oracle parameter that lacks a cover asset', async function () { const { pool, chainlinkSteth, stETH } = this; + const { + governanceContracts: [governanceContract], + } = this.accounts; - const priceFeedOracle = await PriceFeedOracle.new([stETH.address], [chainlinkSteth.address], [18]); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); + const priceFeedOracle = await PriceFeedOracle.deploy([stETH.address], [chainlinkSteth.address], [18]); - await expectRevert( - pool.updateAddressParameters(hex('PRC_FEED'), priceFeedOracle.address, { from: governanceContract }), - 'Pool: Oracle lacks asset', - ); + await expect( + pool.connect(governanceContract).updateAddressParameters(toBytes8('PRC_FEED'), priceFeedOracle.address), + ).to.be.revertedWith('Pool: Oracle lacks asset'); }); it('should correctly update the address parameters', async function () { const { pool } = this; + const { + governanceContracts: [governanceContract], + generalPurpose: [generalPurpose], + } = this.accounts; const params = Object.keys(PoolAddressParamType).filter(param => param !== 'priceFeedOracle'); for (const paramName of params) { const before = await pool[paramName](); - assert.notStrictEqual(before.toString(), generalPurpose); + expect(before.toString()).to.not.equal(generalPurpose.address); const param = PoolAddressParamType[paramName]; - await pool.updateAddressParameters(param, generalPurpose, { from: governanceContract }); + await pool.connect(governanceContract).updateAddressParameters(param, generalPurpose.address); const actual = await pool[paramName](); - assert.strictEqual(actual.toString(), generalPurpose); + expect(actual.toString()).to.equal(generalPurpose.address); } }); it('should correctly update the PRC_FEED parameter', async function () { const { pool, dai, stETH, chainlinkDAI, chainlinkSteth } = this; + const { + governanceContracts: [governanceContract], + } = this.accounts; + + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); - const newPriceFeedOracle = await PriceFeedOracle.new( + const newPriceFeedOracle = await PriceFeedOracle.deploy( [dai.address, stETH.address], [chainlinkDAI.address, chainlinkSteth.address], [18, 18], ); - await pool.updateAddressParameters(PoolAddressParamType.priceFeedOracle, newPriceFeedOracle.address, { - from: governanceContract, - }); + await pool + .connect(governanceContract) + .updateAddressParameters(PoolAddressParamType.priceFeedOracle, newPriceFeedOracle.address); const storedAddress = await pool.priceFeedOracle(); - assert.equal(storedAddress, newPriceFeedOracle.address); + expect(storedAddress).to.equal(newPriceFeedOracle.address); }); }); diff --git a/test/unit/Pool/upgradeCapitalPool.js b/test/unit/Pool/upgradeCapitalPool.js index b9f830e5de..3de8c9ab82 100644 --- a/test/unit/Pool/upgradeCapitalPool.js +++ b/test/unit/Pool/upgradeCapitalPool.js @@ -1,53 +1,46 @@ -const { ether } = require('@openzeppelin/test-helpers'); -const { ZERO_ADDRESS } = require('@openzeppelin/test-helpers').constants; -const { web3, artifacts } = require('hardhat'); -const { assert } = require('chai'); -const { expectRevert } = require('@openzeppelin/test-helpers'); -const { hex } = require('../utils').helpers; - -const { - defaultSender, - governanceContracts: [governance], -} = require('../utils').accounts; -const { BN } = web3.utils; - -const PriceFeedOracle = artifacts.require('PriceFeedOracle'); -const ChainlinkAggregatorMock = artifacts.require('ChainlinkAggregatorMock'); -const Pool = artifacts.require('Pool'); -const ERC20Mock = artifacts.require('ERC20Mock'); -const ERC20NonRevertingMock = artifacts.require('ERC20NonRevertingMock'); +const { ethers } = require('hardhat'); +const { expect } = require('chai'); +const { toBytes8 } = require('../utils').helpers; + +const { parseEther } = ethers.utils; +const { AddressZero } = ethers.constants; describe('upgradeCapitalPool', function () { it('moves pool funds to new pool', async function () { const { pool, master, dai, stETH, chainlinkDAI, chainlinkSteth } = this; + const [governance] = this.accounts.governanceContracts; + const { defaultSender } = this.accounts; + + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const ChainlinkAggregatorMock = await ethers.getContractFactory('ChainlinkAggregatorMock'); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); + const Pool = await ethers.getContractFactory('Pool'); - const chainlinkNewAsset = await ChainlinkAggregatorMock.new(); - await chainlinkNewAsset.setLatestAnswer(new BN((1e18).toString())); + const chainlinkNewAsset = await ChainlinkAggregatorMock.deploy(); + await chainlinkNewAsset.setLatestAnswer(parseEther('1')); - const coverToken = await ERC20Mock.new(); - const priceFeedOracle = await PriceFeedOracle.new( + const coverToken = await ERC20Mock.deploy(); + const priceFeedOracle = await PriceFeedOracle.deploy( [dai.address, stETH.address, coverToken.address], [chainlinkDAI.address, chainlinkSteth.address, chainlinkNewAsset.address], [18, 18, 18], ); - await pool.updateAddressParameters(hex('PRC_FEED'), priceFeedOracle.address, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('PRC_FEED'), priceFeedOracle.address); - const ethAmount = ether('10000'); - const tokenAmount = ether('100000'); - await pool.sendTransaction({ value: ethAmount }); + const ethAmount = parseEther('10000'); + const tokenAmount = parseEther('100000'); + await governance.sendTransaction({ value: ethAmount, to: pool.address }); - await pool.addAsset(coverToken.address, 18, '0', '0', 100, true, { - from: governance, - }); + await pool.connect(governance).addAsset(coverToken.address, 18, '0', '0', 100, true); const tokens = [dai, stETH, coverToken]; for (const token of tokens) { await token.mint(pool.address, tokenAmount); } - const newPool = await Pool.new( - defaultSender, - ZERO_ADDRESS, - ZERO_ADDRESS, // we do not test swaps here + const newPool = await Pool.deploy( + defaultSender.address, + AddressZero, + AddressZero, // we do not test swaps here dai.address, stETH.address, ); @@ -57,67 +50,69 @@ describe('upgradeCapitalPool', function () { for (const token of tokens) { const oldPoolBalance = await token.balanceOf(pool.address); const newPoolBalance = await token.balanceOf(newPool.address); - assert.equal(oldPoolBalance.toString(), '0'); - assert.equal(newPoolBalance.toString(), tokenAmount.toString()); + expect(oldPoolBalance).to.equal(0); + expect(newPoolBalance).to.equal(tokenAmount); } - const oldPoolBalance = await web3.eth.getBalance(pool.address); - const newPoolBalance = await web3.eth.getBalance(newPool.address); - assert.equal(oldPoolBalance.toString(), '0'); - assert.equal(newPoolBalance.toString(), ethAmount.toString()); + const oldPoolBalance = await ethers.provider.getBalance(pool.address); + const newPoolBalance = await ethers.provider.getBalance(newPool.address); + expect(oldPoolBalance).to.equal(0); + expect(newPoolBalance).to.equal(ethAmount); }); it('abandons marked assets on pool upgrade', async function () { const { pool, master, dai, stETH, chainlinkDAI, chainlinkSteth } = this; + const [governance] = this.accounts.governanceContracts; + const { defaultSender } = this.accounts; - const ethAmount = ether('10000'); - const tokenAmount = ether('100000'); - await pool.sendTransaction({ value: ethAmount }); + const ethAmount = parseEther('10000'); + const tokenAmount = parseEther('100000'); + await governance.sendTransaction({ value: ethAmount, to: pool.address }); - const coverToken = await ERC20Mock.new(); - const nonRevertingERC20 = await ERC20NonRevertingMock.new(); + const ChainlinkAggregatorMock = await ethers.getContractFactory('ChainlinkAggregatorMock'); + const ERC20Mock = await ethers.getContractFactory('ERC20Mock'); + const ERC20NonRevertingMock = await ethers.getContractFactory('ERC20NonRevertingMock'); + const PriceFeedOracle = await ethers.getContractFactory('PriceFeedOracle'); + const Pool = await ethers.getContractFactory('Pool'); - const chainlinkNewAsset = await ChainlinkAggregatorMock.new(); - await chainlinkNewAsset.setLatestAnswer(new BN((1e18).toString())); + const coverToken = await ERC20Mock.deploy(); + const nonRevertingERC20 = await ERC20NonRevertingMock.deploy(); - const priceFeedOracle = await PriceFeedOracle.new( + const chainlinkNewAsset = await ChainlinkAggregatorMock.deploy(); + await chainlinkNewAsset.setLatestAnswer(parseEther('1')); + + const priceFeedOracle = await PriceFeedOracle.deploy( [dai.address, stETH.address, coverToken.address, nonRevertingERC20.address], [chainlinkDAI.address, chainlinkSteth.address, chainlinkNewAsset.address, chainlinkNewAsset.address], [18, 18, 18, 18], ); - await pool.updateAddressParameters(hex('PRC_FEED'), priceFeedOracle.address, { from: governance }); + await pool.connect(governance).updateAddressParameters(toBytes8('PRC_FEED'), priceFeedOracle.address); - await pool.addAsset(coverToken.address, 18, '0', '0', 100, true, { - from: governance, - }); + await pool.connect(governance).addAsset(coverToken.address, 18, '0', '0', 100, true); - await pool.addAsset(nonRevertingERC20.address, 18, '0', '0', 100, true, { - from: governance, - }); + await pool.connect(governance).addAsset(nonRevertingERC20.address, 18, '0', '0', 100, true); const tokens = [dai, stETH, coverToken]; for (const token of tokens) { await token.mint(pool.address, tokenAmount); } - const newPool = await Pool.new( - defaultSender, - ZERO_ADDRESS, - ZERO_ADDRESS, // we do not test swaps here + const newPool = await Pool.deploy( + defaultSender.address, + AddressZero, + AddressZero, // we do not test swaps here dai.address, stETH.address, ); await stETH.blacklistSender(pool.address); - await expectRevert(master.upgradeCapitalPool(pool.address, newPool.address), 'ERC20Mock: sender is blacklisted'); + await expect(master.upgradeCapitalPool(pool.address, newPool.address)).to.be.revertedWith( + 'ERC20Mock: sender is blacklisted', + ); - await pool.setAssetsToAbandon([nonRevertingERC20.address], true, { - from: governance, - }); - await pool.setAssetsToAbandon([stETH.address], true, { - from: governance, - }); + await pool.connect(governance).setAssetsToAbandon([nonRevertingERC20.address], true); + await pool.connect(governance).setAssetsToAbandon([stETH.address], true); await master.upgradeCapitalPool(pool.address, newPool.address); @@ -126,17 +121,17 @@ describe('upgradeCapitalPool', function () { const newPoolBalance = await token.balanceOf(newPool.address); if (token.address === stETH.address) { // stETH is blacklisted and abandoned - assert.equal(oldPoolBalance.toString(), tokenAmount.toString()); - assert.equal(newPoolBalance.toString(), '0'); + expect(oldPoolBalance).to.be.equal(tokenAmount); + expect(newPoolBalance).to.be.equal(0); } else { - assert.equal(oldPoolBalance.toString(), '0'); - assert.equal(newPoolBalance.toString(), tokenAmount.toString()); + expect(oldPoolBalance).to.be.equal(0); + expect(newPoolBalance).to.be.equal(tokenAmount); } } - const oldPoolBalance = await web3.eth.getBalance(pool.address); - const newPoolBalance = await web3.eth.getBalance(newPool.address); - assert.equal(oldPoolBalance.toString(), '0'); - assert.equal(newPoolBalance.toString(), ethAmount.toString()); + const oldPoolBalance = await ethers.provider.getBalance(pool.address); + const newPoolBalance = await ethers.provider.getBalance(newPool.address); + expect(oldPoolBalance).to.be.equal(0); + expect(newPoolBalance).to.be.equal(ethAmount); }); }); diff --git a/test/unit/StakingPool/depositTo.js b/test/unit/StakingPool/depositTo.js index c5df2acc4c..22a3d8e4de 100644 --- a/test/unit/StakingPool/depositTo.js +++ b/test/unit/StakingPool/depositTo.js @@ -480,7 +480,7 @@ describe('depositTo', function () { const { firstActiveTrancheId, maxTranche } = await getTranches(daysToSeconds(0), DEFAULT_GRACE_PERIOD); - const tranches = Array(maxTranche - firstActiveTrancheId + 1) + const tranches = Array(maxTranche - firstActiveTrancheId) .fill(0) .map((e, i) => firstActiveTrancheId + i); diff --git a/test/utils/token-price.js b/test/utils/token-price.js index fcfac240b5..31701334d4 100644 --- a/test/utils/token-price.js +++ b/test/utils/token-price.js @@ -148,6 +148,11 @@ function percentageBN(x, percentage) { return x.muln(percentage).divn(100); } +// Uses ethers.BigNumber +function percentageBigNumber(x, percentage) { + return x.mul(percentage).div(100); +} + function toDecimal(x) { return new Decimal(x.toString()); } @@ -163,5 +168,6 @@ module.exports = { calculateNXMForEthRelativeError, calculateEthForNXMRelativeError, percentageBN, + percentageBigNumber, toDecimal, };