From bacfc48a8fde07613d836426d4248a36aae316c0 Mon Sep 17 00:00:00 2001 From: Hui Min HE Date: Mon, 31 Aug 2020 12:47:49 +0800 Subject: [PATCH 1/5] Move fixtures into helpers --- test/helpers/fixtures.js | 123 +++++++++++++++++++++++++++++++++++ test/testInterestProvider.js | 58 +++-------------- test/testUSR.js | 107 +++++------------------------- 3 files changed, 150 insertions(+), 138 deletions(-) create mode 100644 test/helpers/fixtures.js diff --git a/test/helpers/fixtures.js b/test/helpers/fixtures.js new file mode 100644 index 0000000..538a5b4 --- /dev/null +++ b/test/helpers/fixtures.js @@ -0,0 +1,123 @@ +const {loadFixture} = require("ethereum-waffle"); +const BN = ethers.BigNumber; + +const USDxV2deploy = require("../../USDx_1.0/test/helpers/USDxV2deploy.js"); + +// USDx Contracts use web3 and truffle +async function deployUSDxContracts() { + accounts = await web3.eth.getAccounts(); + let collaterals = new Array("PAX", "TUSD", "USDC"); + var weights = new Array(1, 1, 8); + return await USDxV2deploy.contractsDeploy(accounts, collaterals, weights); +} + +async function initialize(usr, usdx, interestProvider) { + const [owner, ...accounts] = await ethers.getSigners(); + + // There are many initialize due to inheritance, use the full typed signature + //console.log(usr.functions); + await usr.functions["initialize(address,address)"]( + usdx.address, + interestProvider.address + ); + + // Allocate some USDx + for (const account of accounts) { + await usdx.transfer(account._address, ethers.utils.parseEther("10000")); + await usdx + .connect(account) + .approve(usr.address, ethers.constants.MaxUint256); + } +} + +async function fixtureInterestProvider([wallet, other], provider) { + const [owner, ...accounts] = await ethers.getSigners(); + + const usdxContracts = await deployUSDxContracts(); + + const Funds = await ethers.getContractFactory("Funds"); + const funds = await Funds.deploy(); + await funds.deployed(); + + const InterestProvider = await ethers.getContractFactory("InterestProvider"); + const interestProvider = await InterestProvider.deploy( + usdxContracts.usdxToken.address, + usdxContracts.store.address, + usdxContracts.poolV2.address, + funds.address + ); + await interestProvider.deployed(); + + await funds.setAuthority(usdxContracts.guard.address); + await usdxContracts.guard.permitx( + interestProvider.address, + usdxContracts.poolV2.address + ); + await usdxContracts.guard.permitx(interestProvider.address, funds.address); + + return {usdxContracts, funds, interestProvider, owner, accounts}; +} + +async function fixtureUSRWithMockInterestProvider([wallet, other], provider) { + const [owner, ...accounts] = await ethers.getSigners(); + + const USDx = await ethers.getContractFactory("USDx"); + const usdx = await USDx.deploy(); + await usdx.deployed(); + + // console.log("USDx address:", usdx.address); + + const MockInterestProvider = await ethers.getContractFactory( + "MockInterestProvider" + ); + + // let accounts[0] to act as funds + let funds = accounts[0]; + // console.log("funds address:", funds._address); + + const interestProvider = await MockInterestProvider.deploy( + usdx.address, + funds._address + ); + await interestProvider.deployed(); + + // console.log("interestProvider address:", interestProvider.address); + + await usdx + .connect(funds) + .approve(interestProvider.address, ethers.constants.MaxUint256); + + const initialInterest = ethers.utils.parseEther("500"); + await usdx.transfer(funds._address, initialInterest); + expect(await usdx.balanceOf(funds._address)).to.equal(initialInterest); + + const USR = await ethers.getContractFactory("USR"); + const usr = await USR.deploy(); + await usr.deployed(); + + await initialize(usr, usdx, interestProvider); + + return {usdx, usr, interestProvider, funds}; +} + +async function fixtureUSRWithInterestProvider([wallet, other], provider) { + const [owner, ...accounts] = await ethers.getSigners(); + + const {usdxContracts, funds, interestProvider} = await loadFixture( + fixtureInterestProvider + ); + + const USR = await ethers.getContractFactory("USR"); + const usr = await USR.deploy(); + await usr.deployed(); + + await initialize(usdx, usr, interestProvider); + + return {usdx, usr, interestProvider}; +} + +module.exports = { + fixtureInterestProvider, + fixtureUSRWithInterestProvider, + fixtureUSRWithMockInterestProvider, +}; diff --git a/test/testInterestProvider.js b/test/testInterestProvider.js index d58260f..1c3a9fd 100644 --- a/test/testInterestProvider.js +++ b/test/testInterestProvider.js @@ -2,18 +2,9 @@ const {expect} = require("chai"); const {loadFixture} = require("ethereum-waffle"); const BN = ethers.BigNumber; -const USDxV2deploy = require("../USDx_1.0/test/helpers/USDxV2deploy.js"); - +const {fixtureInterestProvider} = require("./helpers/fixtures.js"); const Collaterals = artifacts.require("Collaterals_t.sol"); -// USDx Contracts use web3 and truffle -async function deployUSDxContracts() { - accounts = await web3.eth.getAccounts(); - let collaterals = new Array("PAX", "TUSD", "USDC"); - var weights = new Array(1, 1, 8); - return await USDxV2deploy.contractsDeploy(accounts, collaterals, weights); -} - async function printInterestDetails(details, contracts) { console.log("Interest Details:"); for (const i in details[0]) { @@ -30,37 +21,6 @@ async function printInterestDetails(details, contracts) { } } -async function fixtureDeployed([wallet, other], provider) { - const usdxContracts = await deployUSDxContracts(); - - //console.log(usdxContracts); - - const [owner, ...accounts] = await ethers.getSigners(); - - const Funds = await ethers.getContractFactory("Funds"); - const funds = await Funds.deploy(); - await funds.deployed(); - - const InterestProvider = await ethers.getContractFactory("InterestProvider"); - const interestProvider = await InterestProvider.deploy( - usdxContracts.usdxToken.address, - usdxContracts.store.address, - usdxContracts.poolV2.address, - funds.address - ); - await interestProvider.deployed(); - - await funds.setAuthority(usdxContracts.guard.address); - - await usdxContracts.guard.permitx( - interestProvider.address, - usdxContracts.poolV2.address - ); - await usdxContracts.guard.permitx(interestProvider.address, funds.address); - - return {usdxContracts, funds, interestProvider, owner, accounts}; -} - describe("InterestProvider", function () { let owner, accounts; @@ -70,11 +30,11 @@ describe("InterestProvider", function () { describe("deployment()", function () { it("Should be able to deploy basic contracts", async function () { - const {usdx, usr} = await loadFixture(fixtureDeployed); + const {usdx, usr} = await loadFixture(fixtureInterestProvider); }); it("Should be able to get 0 as initial interest amount", async function () { - const {interestProvider} = await loadFixture(fixtureDeployed); + const {interestProvider} = await loadFixture(fixtureInterestProvider); let interest = await interestProvider.callStatic.getInterestAmount(); @@ -83,7 +43,7 @@ describe("InterestProvider", function () { it("Should be able to get 0 as initial interest details", async function () { const {usdxContracts, interestProvider} = await loadFixture( - fixtureDeployed + fixtureInterestProvider ); let interestDetails = await interestProvider.callStatic.getInterestDetails(); @@ -92,14 +52,14 @@ describe("InterestProvider", function () { }); it("Should not be able to withdraw any interest", async function () { - const {interestProvider} = await loadFixture(fixtureDeployed); + const {interestProvider} = await loadFixture(fixtureInterestProvider); await expect(interestProvider.withdrawInterest(1)).to.be.reverted; }); }); describe("Mock some interest", function () { before(async function () { - const {usdxContracts, funds} = await loadFixture(fixtureDeployed); + const {usdxContracts, funds} = await loadFixture(fixtureInterestProvider); let amount = ethers.utils.parseEther("10000"); await usdxContracts.protocol.oneClickMinting(0, amount); @@ -128,7 +88,7 @@ describe("InterestProvider", function () { }); it("getInterestAmount()", async function () { - const {interestProvider} = await loadFixture(fixtureDeployed); + const {interestProvider} = await loadFixture(fixtureInterestProvider); let interest = await interestProvider.callStatic.getInterestAmount(); @@ -137,7 +97,7 @@ describe("InterestProvider", function () { it("getInterestDetails()", async function () { const {usdxContracts, interestProvider} = await loadFixture( - fixtureDeployed + fixtureInterestProvider ); let interestDetails = await interestProvider.callStatic.getInterestDetails(); @@ -147,7 +107,7 @@ describe("InterestProvider", function () { it("withdrawInterest()", async function () { const {usdxContracts, interestProvider, owner} = await loadFixture( - fixtureDeployed + fixtureInterestProvider ); let interest = await interestProvider.callStatic.getInterestAmount(); diff --git a/test/testUSR.js b/test/testUSR.js index 28097b5..4a31cca 100644 --- a/test/testUSR.js +++ b/test/testUSR.js @@ -2,83 +2,12 @@ const {expect} = require("chai"); const {loadFixture} = require("ethereum-waffle"); const USRTruffle = artifacts.require("USR"); +const {fixtureUSRWithMockInterestProvider} = require("./helpers/fixtures.js"); + const BASE = ethers.utils.parseEther("1"); const MINT_SELECTOR = "0x40c10f19"; const REDEEM_SELECTOR = "0x1e9a6950"; -async function fixtureDeployed([wallet, other], provider) { - const [owner, ...accounts] = await ethers.getSigners(); - - const USDx = await ethers.getContractFactory("USDx"); - const usdx = await USDx.deploy(); - await usdx.deployed(); - - // console.log("USDx address:", usdx.address); - - const MockInterestProvider = await ethers.getContractFactory( - "MockInterestProvider" - ); - - // let accounts[0] to act as funds - let funds = accounts[0]; - // console.log("funds address:", funds._address); - - const interestProvider = await MockInterestProvider.deploy( - usdx.address, - funds._address - ); - await interestProvider.deployed(); - - // console.log("interestProvider address:", interestProvider.address); - - await usdx - .connect(funds) - .approve(interestProvider.address, ethers.constants.MaxUint256); - - const initialInterest = ethers.utils.parseEther("500"); - await usdx.transfer(funds._address, initialInterest); - expect(await usdx.balanceOf(funds._address)).to.equal(initialInterest); - - const USR = await ethers.getContractFactory("USR"); - const usr = await USR.deploy(); - await usr.deployed(); - - // const usrTruffle = await USRTruffle.at(usr.address); - // console.log(usrTruffle.methods); - - // await usrTruffle.methods["initialize(address,address)"]( - // usdx.address, - // interestProvider.address - // ); - - return {usdx, usr, interestProvider, funds}; -} - -async function fixtureInitialized([wallet, other], provider) { - const [owner, ...accounts] = await ethers.getSigners(); - - const {usdx, usr, interestProvider, funds} = await loadFixture( - fixtureDeployed - ); - - // There are many initialize due to inheritance, use the full typed signature - //console.log(usr.functions); - await usr.functions["initialize(address,address)"]( - usdx.address, - interestProvider.address - ); - - // Allocate some USDx - for (const account of accounts) { - await usdx.transfer(account._address, ethers.utils.parseEther("10000")); - await usdx - .connect(account) - .approve(usr.address, ethers.constants.MaxUint256); - } - - return {usdx, usr, interestProvider, funds}; -} - describe("USR", function () { let owner, accounts; @@ -88,13 +17,13 @@ describe("USR", function () { describe("Initializable", async function () { it("Should be able to initialize", async function () { - const {usr} = await loadFixture(fixtureInitialized); + const {usr} = await loadFixture(fixtureUSRWithMockInterestProvider); expect(await usr.name()).to.equal("USR"); }); it("Should not be able to initialize again", async function () { const {usr, usdx, interestProvider, funds} = await loadFixture( - fixtureInitialized + fixtureUSRWithMockInterestProvider ); await expect( @@ -144,7 +73,7 @@ describe("USR", function () { describe("ERC20Pausable", function () { it("Should be able to pause", async function () { - const {usr} = await loadFixture(fixtureInitialized); + const {usr} = await loadFixture(fixtureUSRWithMockInterestProvider); let account = accounts[1]; @@ -182,7 +111,7 @@ describe("USR", function () { }); it("Should be able to unpause ", async function () { - const {usr} = await loadFixture(fixtureInitialized); + const {usr} = await loadFixture(fixtureUSRWithMockInterestProvider); let account = accounts[1]; await expect(usr.unpause()) @@ -218,7 +147,7 @@ describe("USR", function () { describe("Chargeable", function () { it("Should be able to update fee recipient", async function () { const {usdx, usr, interestProvider} = await loadFixture( - fixtureInitialized + fixtureUSRWithMockInterestProvider ); let recipient = accounts[accounts.length - 1]._address; @@ -228,7 +157,7 @@ describe("USR", function () { it("Should be able to charge some fee when mint", async function () { const {usdx, usr, interestProvider} = await loadFixture( - fixtureInitialized + fixtureUSRWithMockInterestProvider ); let fee = ethers.utils.parseEther("0.05"); @@ -290,7 +219,7 @@ describe("USR", function () { it("Should be able to charge some fee when redeem", async function () { const {usdx, usr, interestProvider} = await loadFixture( - fixtureInitialized + fixtureUSRWithMockInterestProvider ); let fee = ethers.utils.parseEther("0.05"); @@ -357,7 +286,7 @@ describe("USR", function () { it("Should be able to charge some fee when redeemUnderlying", async function () { const {usdx, usr, interestProvider} = await loadFixture( - fixtureInitialized + fixtureUSRWithMockInterestProvider ); let account = accounts[1]; @@ -425,7 +354,7 @@ describe("USR", function () { }); it("Should be able to update fee to zero", async function () { - const {usr} = await loadFixture(fixtureInitialized); + const {usr} = await loadFixture(fixtureUSRWithMockInterestProvider); await usr.updateOriginationFee(REDEEM_SELECTOR, 0); await usr.updateOriginationFee(MINT_SELECTOR, 0); }); @@ -433,7 +362,7 @@ describe("USR", function () { describe("ERC20Exchangeable", function () { it("Initial exchange rate should be 1.0", async function () { - const {usr} = await loadFixture(fixtureInitialized); + const {usr} = await loadFixture(fixtureUSRWithMockInterestProvider); //console.log(ethers.utils.formatEther(await usr.totalSupply())); @@ -444,7 +373,7 @@ describe("USR", function () { it("Should be able to update exchange rate", async function () { const {usdx, usr, interestProvider} = await loadFixture( - fixtureInitialized + fixtureUSRWithMockInterestProvider ); expect(await usr.callStatic.exchangeRate()).to.equal( @@ -470,7 +399,7 @@ describe("USR", function () { it("Should be able to get underlying balance", async function () { const {usdx, usr, interestProvider} = await loadFixture( - fixtureInitialized + fixtureUSRWithMockInterestProvider ); let account = accounts[1]; @@ -521,7 +450,7 @@ describe("USR", function () { describe("Mint/Redeem/RedeemUnderlying", function () { it("Should not be able to mint < 0 when totalSupply is 0", async function () { const {usdx, usr, interestProvider} = await loadFixture( - fixtureInitialized + fixtureUSRWithMockInterestProvider ); let account = accounts[1]; @@ -533,7 +462,7 @@ describe("USR", function () { it("Should be able to mint with mock profit provider", async function () { const {usdx, usr, interestProvider} = await loadFixture( - fixtureInitialized + fixtureUSRWithMockInterestProvider ); let account = accounts[1]; @@ -593,7 +522,7 @@ describe("USR", function () { it("Should be able to redeem with mock profit provider", async function () { const {usdx, usr, interestProvider} = await loadFixture( - fixtureInitialized + fixtureUSRWithMockInterestProvider ); let account = accounts[1]; @@ -648,7 +577,7 @@ describe("USR", function () { it("Should be able to redeemUnderlying with mock profit provider", async function () { const {usdx, usr, interestProvider} = await loadFixture( - fixtureInitialized + fixtureUSRWithMockInterestProvider ); let account = accounts[1]; From dafff29210eff242202b8d93e067c6f41ca3aae9 Mon Sep 17 00:00:00 2001 From: Hui Min HE Date: Mon, 31 Aug 2020 18:51:23 +0800 Subject: [PATCH 2/5] Add test cases for USR with real interest provider --- test/helpers/fixtures.js | 48 ++++-- test/testUSR.js | 328 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 361 insertions(+), 15 deletions(-) diff --git a/test/helpers/fixtures.js b/test/helpers/fixtures.js index 538a5b4..7d2f93c 100644 --- a/test/helpers/fixtures.js +++ b/test/helpers/fixtures.js @@ -11,8 +11,8 @@ async function deployUSDxContracts() { return await USDxV2deploy.contractsDeploy(accounts, collaterals, weights); } -async function initialize(usr, usdx, interestProvider) { - const [owner, ...accounts] = await ethers.getSigners(); +async function initialize(usr, usdx, protocol, interestProvider) { + const accounts = await web3.eth.getAccounts(); // There are many initialize due to inheritance, use the full typed signature //console.log(usr.functions); @@ -21,12 +21,14 @@ async function initialize(usr, usdx, interestProvider) { interestProvider.address ); - // Allocate some USDx + // Mint some USDx + const amount = ethers.utils.parseEther("10000"); for (const account of accounts) { - await usdx.transfer(account._address, ethers.utils.parseEther("10000")); - await usdx - .connect(account) - .approve(usr.address, ethers.constants.MaxUint256); + // USDx contracts are truffle contracts + await protocol.oneClickMinting(0, amount, {from: account}); + await usdx.approve(usr.address, ethers.constants.MaxUint256, { + from: account, + }); } } @@ -95,7 +97,19 @@ async function fixtureUSRWithMockInterestProvider([wallet, other], provider) { const usr = await USR.deploy(); await usr.deployed(); - await initialize(usr, usdx, interestProvider); + await usr.functions["initialize(address,address)"]( + usdx.address, + interestProvider.address + ); + + // Transfer some USDx + const amount = ethers.utils.parseEther("10000"); + for (const account of accounts) { + await usdx.transfer(account._address, amount); + await usdx + .connect(account) + .approve(usr.address, ethers.constants.MaxUint256); + } return {usdx, usr, interestProvider, funds}; } @@ -111,9 +125,23 @@ async function fixtureUSRWithInterestProvider([wallet, other], provider) { const usr = await USR.deploy(); await usr.deployed(); - await initialize(usdx, usr, interestProvider); + await initialize( + usr, + usdxContracts.usdxToken, + usdxContracts.protocol, + interestProvider + ); + + // Provide some interest + await usdxContracts.usdxToken.transfer( + funds.address, + ethers.utils.parseEther("10000") + ); + + await interestProvider.setAuthority(usdxContracts.guard.address); + await usdxContracts.guard.permitx(usr.address, interestProvider.address); - return {usdx, usr, interestProvider}; + return {usdxContracts, usr, interestProvider}; } module.exports = { diff --git a/test/testUSR.js b/test/testUSR.js index 4a31cca..506dd5e 100644 --- a/test/testUSR.js +++ b/test/testUSR.js @@ -1,14 +1,22 @@ const {expect} = require("chai"); +const BN = ethers.BigNumber; const {loadFixture} = require("ethereum-waffle"); const USRTruffle = artifacts.require("USR"); -const {fixtureUSRWithMockInterestProvider} = require("./helpers/fixtures.js"); +const { + fixtureUSRWithMockInterestProvider, + fixtureUSRWithInterestProvider, +} = require("./helpers/fixtures.js"); const BASE = ethers.utils.parseEther("1"); const MINT_SELECTOR = "0x40c10f19"; const REDEEM_SELECTOR = "0x1e9a6950"; -describe("USR", function () { +function unifyBN(num) { + return BN.from(num.toString()); +} + +describe("USR with Mock Interest Provider", function () { let owner, accounts; before(async () => { @@ -460,7 +468,7 @@ describe("USR", function () { ).to.be.revertedWith("The first mint amount is too small"); }); - it("Should be able to mint with mock profit provider", async function () { + it("Should be able to mint", async function () { const {usdx, usr, interestProvider} = await loadFixture( fixtureUSRWithMockInterestProvider ); @@ -520,7 +528,7 @@ describe("USR", function () { ); }); - it("Should be able to redeem with mock profit provider", async function () { + it("Should be able to redeem", async function () { const {usdx, usr, interestProvider} = await loadFixture( fixtureUSRWithMockInterestProvider ); @@ -575,7 +583,7 @@ describe("USR", function () { ); }); - it("Should be able to redeemUnderlying with mock profit provider", async function () { + it("Should be able to redeemUnderlying", async function () { const {usdx, usr, interestProvider} = await loadFixture( fixtureUSRWithMockInterestProvider ); @@ -633,3 +641,313 @@ describe("USR", function () { }); }); }); + +describe("USR with Real Interest Provider", function () { + let owner, accounts; + + before(async () => { + [owner, ...accounts] = await ethers.getSigners(); + }); + + describe("ERC20Exchangeable", function () { + it("Initial exchange rate should be 1.0", async function () { + const {usr} = await loadFixture(fixtureUSRWithInterestProvider); + + //console.log(ethers.utils.formatEther(await usr.totalSupply())); + + expect(await usr.callStatic.exchangeRate()).to.equal( + ethers.utils.parseEther("1.0") + ); + }); + + it("Should be able to update exchange rate", async function () { + const {usdxContracts, usr} = await loadFixture( + fixtureUSRWithInterestProvider + ); + + const usdx = usdxContracts.usdxToken; + + expect(await usr.callStatic.exchangeRate()).to.equal( + ethers.utils.parseEther("1.0") + ); + + let account = accounts[1]; + + let amount = ethers.utils.parseEther("1000"); + await usr.connect(account).mint(account._address, amount); + + // Mock some profit + for (srcToken of usdxContracts.srcTokens) { + let dTokenAddr = await usdxContracts.dTokenController.getDToken( + srcToken.address + ); + + let decimals = await srcToken.decimals(); + let amount = BN.from(500).mul(BN.from(10).pow(decimals)); + + await srcToken.transfer(dTokenAddr, amount); + } + + // expect(await usr.callStatic.exchangeRate()).to.equal( + // ethers.utils.parseEther("1.5") + // ); + + // await usr + // .connect(account) + // .redeem(account._address, await usr.balanceOf(account._address)); + }); + + it("Should be able to get underlying balance", async function () { + const {usdxContracts, usr, interestProvider} = await loadFixture( + fixtureUSRWithInterestProvider + ); + + const usdx = usdxContracts.usdxToken; + + let account = accounts[1]; + + let exchangeRate = await usr.callStatic.exchangeRate(); + // console.log( + // "Exchange Rate:", + // ethers.utils.formatEther(await usr.callStatic.exchangeRate()) + // ); + + let balancesBefore = { + usrUnderlying: await usr.callStatic.balanceOfUnderlying( + account._address + ), + usdx: unifyBN(await usdx.balanceOf(account._address)), + }; + + await usr + .connect(account) + .mint(account._address, ethers.utils.parseEther("500")); + + let balancesAfter = { + usrUnderlying: await usr.callStatic.balanceOfUnderlying( + account._address + ), + usdx: unifyBN(await usdx.balanceOf(account._address)), + }; + + let changed = { + usrUnderlying: balancesAfter.usrUnderlying.sub( + balancesBefore.usrUnderlying + ), + usdx: balancesAfter.usdx.sub(balancesBefore.usdx), + }; + + // usrUnderlying = usdx + // There could be some loss of underlying due to the precision + let loss = changed.usdx.abs().sub(changed.usrUnderlying.abs()); + expect(loss.mul(BASE)).to.lte(exchangeRate); + + //console.log(balancesAfter.usrUnderlying.toString()); + + // Restore the original state + await usr + .connect(account) + .redeemUnderlying(account._address, balancesAfter.usrUnderlying); + }); + }); + + describe("Mint/Redeem/RedeemUnderlying", function () { + it("Should not be able to mint < 0 when totalSupply is 0", async function () { + const {usdxContracts, usr, interestProvider} = await loadFixture( + fixtureUSRWithInterestProvider + ); + + const usdx = usdxContracts.usdxToken; + + let account = accounts[1]; + let amount = ethers.utils.parseEther("0.85"); + await expect( + usr.connect(account).mint(account._address, amount) + ).to.be.revertedWith("The first mint amount is too small"); + }); + + it("Should be able to mint", async function () { + const {usdxContracts, usr, interestProvider} = await loadFixture( + fixtureUSRWithInterestProvider + ); + + const usdx = usdxContracts.usdxToken; + + let account = accounts[1]; + + let exchangeRate = await usr.callStatic.exchangeRate(); + // console.log( + // "Exchange Rate:", + // ethers.utils.formatEther(await usr.callStatic.exchangeRate()) + // ); + + let balancesBefore = { + usr: await usr.balanceOf(account._address), + usdx: unifyBN(await usdx.balanceOf(account._address)), + }; + + await usr + .connect(account) + .mint(account._address, ethers.utils.parseEther("500")); + + // Mock some profit + for (srcToken of usdxContracts.srcTokens) { + let dTokenAddr = await usdxContracts.dTokenController.getDToken( + srcToken.address + ); + + let decimals = await srcToken.decimals(); + let amount = BN.from(500).mul(BN.from(10).pow(decimals)); + + await srcToken.transfer(dTokenAddr, amount); + } + + // console.log( + // "Account has", + // ethers.utils.formatEther(balancesBefore.usr), + // "USR", + // ethers.utils.formatEther(balancesBefore.usdx), + // "USDx" + // ); + + let balancesAfter = { + usr: await usr.balanceOf(account._address), + usdx: unifyBN(await usdx.balanceOf(account._address)), + }; + + // console.log( + // "Account has", + // ethers.utils.formatEther(balancesAfter.usr), + // "USR", + // ethers.utils.formatEther(balancesAfter.usdx), + // "USDx" + // ); + + let changed = { + usr: balancesAfter.usr.sub(balancesBefore.usr), + usdx: balancesAfter.usdx.sub(balancesBefore.usdx), + }; + + // usr = usdx * BASE/exchangeRate + expect(changed.usdx.mul(BASE).div(exchangeRate).abs()).to.equal( + changed.usr.abs() + ); + }); + + it("Should be able to redeem", async function () { + const {usdxContracts, usr, interestProvider} = await loadFixture( + fixtureUSRWithInterestProvider + ); + + const usdx = usdxContracts.usdxToken; + + let account = accounts[1]; + + let amount = ethers.utils.parseEther("500"); + await usr.connect(account).mint(account._address, amount); + + let exchangeRate = await usr.callStatic.exchangeRate(); + // console.log( + // "Exchange Rate:", + // ethers.utils.formatEther(await usr.callStatic.exchangeRate()) + // ); + + let balancesBefore = { + usr: await usr.balanceOf(account._address), + usdx: unifyBN(await usdx.balanceOf(account._address)), + }; + + // console.log( + // "Account has", + // ethers.utils.formatEther(balancesBefore.usr), + // "USR", + // ethers.utils.formatEther(balancesBefore.usdx), + // "USDx" + // ); + + await usr.connect(account).redeem(account._address, balancesBefore.usr); + + let balancesAfter = { + usr: await usr.balanceOf(account._address), + usdx: unifyBN(await usdx.balanceOf(account._address)), + }; + + // console.log( + // "Account has", + // ethers.utils.formatEther(balancesAfter.usr), + // "USR", + // ethers.utils.formatEther(balancesAfter.usdx), + // "USDx" + // ); + + let changed = { + usr: balancesAfter.usr.sub(balancesBefore.usr), + usdx: balancesAfter.usdx.sub(balancesBefore.usdx), + }; + + // usdx = usr * exchangeRate/BASE + expect(changed.usr.mul(exchangeRate).div(BASE).abs()).to.equal( + changed.usdx.abs() + ); + }); + + it("Should be able to redeemUnderlying", async function () { + const {usdxContracts, usr, interestProvider} = await loadFixture( + fixtureUSRWithInterestProvider + ); + + const usdx = usdxContracts.usdxToken; + + let account = accounts[1]; + let amount = ethers.utils.parseEther("500"); + + await usr.connect(account).mint(account._address, amount); + + let exchangeRate = await usr.callStatic.exchangeRate(); + // console.log( + // "Exchange Rate:", + // ethers.utils.formatEther(await usr.callStatic.exchangeRate()) + // ); + + let balancesBefore = { + usr: await usr.balanceOf(account._address), + usdx: unifyBN(await usdx.balanceOf(account._address)), + }; + + // console.log( + // "Account has", + // ethers.utils.formatEther(balancesBefore.usr), + // "USR", + // ethers.utils.formatEther(balancesBefore.usdx), + // "USDx" + // ); + + await usr.connect(account).redeemUnderlying(account._address, amount); + + let balancesAfter = { + usr: await usr.balanceOf(account._address), + usdx: unifyBN(await usdx.balanceOf(account._address)), + }; + + // console.log( + // "Account has", + // ethers.utils.formatEther(balancesAfter.usr), + // "USR", + // ethers.utils.formatEther(balancesAfter.usdx), + // "USDx" + // ); + + let changed = { + usr: balancesAfter.usr.sub(balancesBefore.usr), + usdx: balancesAfter.usdx.sub(balancesBefore.usdx), + }; + + // usdx = usr * exchangeRate/BASE + expect(changed.usr.mul(exchangeRate).div(BASE).abs()).to.equal( + changed.usdx.abs() + ); + + expect(changed.usdx.abs()).to.equal(amount); + }); + }); +}); From a3ef752c4fbae033c6247b8ed1f76816033ba0d5 Mon Sep 17 00:00:00 2001 From: Hui Min HE Date: Wed, 2 Sep 2020 16:44:46 +0800 Subject: [PATCH 3/5] Add coverage support --- .solcover.js | 82 +++++++++++++++++++++++++++++++++++++++++++++++ buidler.config.js | 1 + package.json | 1 + 3 files changed, 84 insertions(+) create mode 100644 .solcover.js diff --git a/.solcover.js b/.solcover.js new file mode 100644 index 0000000..cef326e --- /dev/null +++ b/.solcover.js @@ -0,0 +1,82 @@ +var fs = require("fs"); +const bre = require("@nomiclabs/buidler"); + +async function copyUSDxArtifacts() { + const USDxArtifacts = [ + "Utils", + "ReentrancyGuard", + "DSValue", + "DSThing", + "DSNote", + "DSMath", + "DSGuardEvents", + "DSGuard", + "DSAuthority", + "DSAuthEvents", + "DSAuth", + "UpgradeabilityProxy", + "Proxy", + "DFProxy", + "AdminUpgradeabilityProxy", + "AddressUtils", + "DFUpgrader", + "IERC20Token", + "IERC20", + "IDSWrappedToken", + "IDSToken", + "ERC20SafeTransfer", + "DSWrappedToken", + "ERC20Events", + "ERC20", + "DSTokenBase", + "DSToken", + "DSStop", + "SafeMath", + "Collaterals_t", + "IDTokenController", + "IDToken", + "IDFStore", + "IDFPoolV2", + "IDFPool", + "IDFFunds", + "IDFCollateral", + "DFStore", + "DFPoolV2", + "DFPoolV1", + "DFPool", + "DFFunds", + "DFCollateral", + "iMedianizer", + "UniswapV2Library", + "Oracle", + "PriceFeed", + "Medianizer", + "DTokenController", + "DToken", + "Migrations", + "IDFProtocol", + "IDFEngine", + "DFSetting", + "DFProtocolView", + "DFProtocol", + "DFEngineV2", + "DFEngine", + ]; + + USDxArtifacts.forEach((file) => { + fs.copyFileSync( + "./artifacts/" + file + ".json", + "./build/" + file + ".json" + ); + }); +} + +module.exports = { + onCompileComplete: copyUSDxArtifacts, + skipFiles: ["library", "interface", "mock", "Migrations.sol", "USRProxy.sol"], + + mocha: { + grep: "(Skipped in coverage)", // We have some cases need to be skipped + invert: true, // Run the grep's inverse set. + }, +}; diff --git a/buidler.config.js b/buidler.config.js index 4f50a57..29d1319 100644 --- a/buidler.config.js +++ b/buidler.config.js @@ -1,6 +1,7 @@ usePlugin("@nomiclabs/buidler-waffle"); usePlugin("@nomiclabs/buidler-truffle5"); usePlugin("buidler-gas-reporter"); +usePlugin("solidity-coverage"); // This is a sample Buidler task. To learn how to create your own go to // https://buidler.dev/guides/create-task.html diff --git a/package.json b/package.json index 3a2b2e5..7eef6d4 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "ethers": "^5.0.8", "prettier": "^2.0.5", "prettier-plugin-solidity": "^1.0.0-alpha.56", + "solidity-coverage": "^0.7.10", "truffle-hdwallet-provider": "^1.0.17", "web3": "^1.2.11" }, From 6acd4acd48aba16848e657550563417ab566c3dc Mon Sep 17 00:00:00 2001 From: Hui Min HE Date: Wed, 2 Sep 2020 17:54:54 +0800 Subject: [PATCH 4/5] Add test cases for better coverage --- USDx_1.0 | 2 +- contracts/USR.sol | 7 +- test/testInterestProvider.js | 50 ++++++++++++ test/testUSR.js | 142 +++++++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 4 deletions(-) diff --git a/USDx_1.0 b/USDx_1.0 index 357c54b..7137bbf 160000 --- a/USDx_1.0 +++ b/USDx_1.0 @@ -1 +1 @@ -Subproject commit 357c54bc76cee43631ba1f385b040b30a94c1f78 +Subproject commit 7137bbfd709de7292846eb95e9eef8c1b0d44312 diff --git a/contracts/USR.sol b/contracts/USR.sol index 37b3f68..15fa862 100644 --- a/contracts/USR.sol +++ b/contracts/USR.sol @@ -170,7 +170,7 @@ contract ERC20Exchangeable is contract USR is Initializable, DSAuth, ERC20Exchangeable { using SafeERC20 for IERC20; - IInterestProvider interestProvider; + IInterestProvider public interestProvider; event NewInterestProvider( address oldInterestProvider, @@ -201,8 +201,9 @@ contract USR is Initializable, DSAuth, ERC20Exchangeable { address _oldInterestProvider = address(interestProvider); require( - _interestProvider != _oldInterestProvider, - "updateInterestProvider: same profit provider address." + _interestProvider != address(0) && + _interestProvider != _oldInterestProvider, + "updateInterestProvider: interest provider can be not set to 0 or the current one." ); interestProvider = IInterestProvider(_interestProvider); diff --git a/test/testInterestProvider.js b/test/testInterestProvider.js index 1c3a9fd..ee98ece 100644 --- a/test/testInterestProvider.js +++ b/test/testInterestProvider.js @@ -144,4 +144,54 @@ describe("InterestProvider", function () { expect(balanceAfter.sub(balanceBefore)).to.equal(amount); }); }); + + describe("setPool() & setFunds()", function () { + it("setPool()", async function () { + const {usdxContracts, interestProvider} = await loadFixture( + fixtureInterestProvider + ); + + await expect( + interestProvider.setPool(usdxContracts.poolV2.address) + ).to.be.revertedWith( + "setPool: dfPool can be not set to 0 or the current one." + ); + + await expect( + interestProvider.setPool(ethers.constants.AddressZero) + ).to.be.revertedWith( + "setPool: dfPool can be not set to 0 or the current one." + ); + + await interestProvider.setPool(interestProvider.address); + expect(await interestProvider.dfPool()).to.equal( + interestProvider.address + ); + + // Restore back + await interestProvider.setPool(usdxContracts.poolV2.address); + }); + + it("setFunds()", async function () { + const {interestProvider, funds} = await loadFixture( + fixtureInterestProvider + ); + + await expect( + interestProvider.setFunds(ethers.constants.AddressZero) + ).to.be.revertedWith( + "setFunds: funds can be not set to 0 or the current one." + ); + + await expect(interestProvider.setFunds(funds.address)).to.be.revertedWith( + "setFunds: funds can be not set to 0 or the current one." + ); + + await interestProvider.setFunds(interestProvider.address); + expect(await interestProvider.funds()).to.equal(interestProvider.address); + + // Restore back + await interestProvider.setFunds(funds.address); + }); + }); }); diff --git a/test/testUSR.js b/test/testUSR.js index 506dd5e..4a2f7d9 100644 --- a/test/testUSR.js +++ b/test/testUSR.js @@ -583,6 +583,64 @@ describe("USR with Mock Interest Provider", function () { ); }); + it("Should be able to redeem from another account", async function () { + const {usdx, usr, interestProvider} = await loadFixture( + fixtureUSRWithMockInterestProvider + ); + + let account = accounts[1]; + let from = accounts[2]; + + let amount = ethers.utils.parseEther("500"); + + await usr.connect(from).mint(from._address, amount); + await usr.connect(from).approve(account._address, amount); + + let exchangeRate = await usr.callStatic.exchangeRate(); + // console.log( + // "Exchange Rate:", + // ethers.utils.formatEther(await usr.callStatic.exchangeRate()) + // ); + + let balancesBefore = { + usr: await usr.balanceOf(from._address), + usdx: await usdx.balanceOf(account._address), + }; + + // console.log( + // "Account has", + // ethers.utils.formatEther(balancesBefore.usr), + // "USR", + // ethers.utils.formatEther(balancesBefore.usdx), + // "USDx" + // ); + + await usr.connect(account).redeem(from._address, balancesBefore.usr); + + let balancesAfter = { + usr: await usr.balanceOf(from._address), + usdx: await usdx.balanceOf(account._address), + }; + + // console.log( + // "Account has", + // ethers.utils.formatEther(balancesAfter.usr), + // "USR", + // ethers.utils.formatEther(balancesAfter.usdx), + // "USDx" + // ); + + let changed = { + usr: balancesAfter.usr.sub(balancesBefore.usr), + usdx: balancesAfter.usdx.sub(balancesBefore.usdx), + }; + + // usdx = usr * exchangeRate/BASE + expect(changed.usr.mul(exchangeRate).div(BASE).abs()).to.equal( + changed.usdx.abs() + ); + }); + it("Should be able to redeemUnderlying", async function () { const {usdx, usr, interestProvider} = await loadFixture( fixtureUSRWithMockInterestProvider @@ -639,6 +697,90 @@ describe("USR with Mock Interest Provider", function () { expect(changed.usdx.abs()).to.equal(amount); }); + + it("Should be able to redeemUnderlying from another account", async function () { + const {usdx, usr, interestProvider} = await loadFixture( + fixtureUSRWithMockInterestProvider + ); + + let account = accounts[1]; + let from = accounts[2]; + + let amount = ethers.utils.parseEther("500"); + + await usr.connect(from).mint(from._address, amount); + await usr.connect(from).approve(account._address, amount); + + let exchangeRate = await usr.callStatic.exchangeRate(); + // console.log( + // "Exchange Rate:", + // ethers.utils.formatEther(await usr.callStatic.exchangeRate()) + // ); + + let balancesBefore = { + usr: await usr.balanceOf(from._address), + usdx: await usdx.balanceOf(account._address), + }; + + // console.log( + // "Account has", + // ethers.utils.formatEther(balancesBefore.usr), + // "USR", + // ethers.utils.formatEther(balancesBefore.usdx), + // "USDx" + // ); + + await usr.connect(account).redeemUnderlying(from._address, amount); + + let balancesAfter = { + usr: await usr.balanceOf(from._address), + usdx: await usdx.balanceOf(account._address), + }; + + // console.log( + // "Account has", + // ethers.utils.formatEther(balancesAfter.usr), + // "USR", + // ethers.utils.formatEther(balancesAfter.usdx), + // "USDx" + // ); + + let changed = { + usr: balancesAfter.usr.sub(balancesBefore.usr), + usdx: balancesAfter.usdx.sub(balancesBefore.usdx), + }; + + // usdx = usr * exchangeRate/BASE + expect(changed.usr.mul(exchangeRate).div(BASE).abs()).to.equal( + changed.usdx.abs() + ); + + expect(changed.usdx.abs()).to.equal(amount); + }); + }); + + it("updateInterestProvider()", async function () { + const {usr, interestProvider} = await loadFixture( + fixtureUSRWithMockInterestProvider + ); + + await expect( + usr.updateInterestProvider(ethers.constants.AddressZero) + ).to.be.revertedWith( + "updateInterestProvider: interest provider can be not set to 0 or the current one." + ); + + await expect( + usr.updateInterestProvider(interestProvider.address) + ).to.be.revertedWith( + "updateInterestProvider: interest provider can be not set to 0 or the current one." + ); + + await usr.updateInterestProvider(usr.address); + expect(await usr.interestProvider()).to.equal(usr.address); + + // Restore back + await usr.updateInterestProvider(interestProvider.address); }); }); From 4380a48ac9b8404a5d15ba604c0bdde257b51011 Mon Sep 17 00:00:00 2001 From: Hui Min HE Date: Thu, 3 Sep 2020 16:57:44 +0800 Subject: [PATCH 5/5] Use fixture to avoid restore state in every test case --- README.md | 30 +++++++-- package.json | 1 + test/helpers/fixtures.js | 16 +++-- test/testInterestProvider.js | 4 +- test/testUSR.js | 118 +++++++++++++++-------------------- 5 files changed, 83 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index 7ea6a10..2e51cb6 100755 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ in an existing USR repo. ## Usage +### Build + Install buidler and plugins ``` @@ -37,12 +39,34 @@ Compile the USDx contracts for integration test: npx buidler compile --config buidler.config.usdx.js ``` +Run a local develop network with buidler EVM: + +``` +npx buidler node +``` + +Run a local node and a console: + +``` +npx buidler console +``` + +### Test + To run the tests: ``` npx buidler test ``` +To run test coverage: + +``` +npx buidler coverage --temp build +``` + +### Deploy + To deploy contracts, need to set basic config parameters in `.env`: ``` @@ -61,9 +85,3 @@ Deploy contracts at the testnet: Kovan. ``` truffle migrate --network kovan ``` - -Run a local develop network with buidler EVM: - -``` -npx buidler node -``` diff --git a/package.json b/package.json index 7eef6d4..55d0c56 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "", "scripts": { "test": "npx buidler test", + "coverage": "npx buidler coverage --temp build", "format": "prettier --write contracts test" }, "author": "", diff --git a/test/helpers/fixtures.js b/test/helpers/fixtures.js index 7d2f93c..da36663 100644 --- a/test/helpers/fixtures.js +++ b/test/helpers/fixtures.js @@ -1,8 +1,8 @@ -const {loadFixture} = require("ethereum-waffle"); -const BN = ethers.BigNumber; - +const {createFixtureLoader} = require("ethereum-waffle"); const USDxV2deploy = require("../../USDx_1.0/test/helpers/USDxV2deploy.js"); +const loadFixture = createFixtureLoader([], ethers.provider); + // USDx Contracts use web3 and truffle async function deployUSDxContracts() { accounts = await web3.eth.getAccounts(); @@ -74,7 +74,7 @@ async function fixtureUSRWithMockInterestProvider([wallet, other], provider) { ); // let accounts[0] to act as funds - let funds = accounts[0]; + const [funds, ...others] = accounts; // console.log("funds address:", funds._address); const interestProvider = await MockInterestProvider.deploy( @@ -89,10 +89,6 @@ async function fixtureUSRWithMockInterestProvider([wallet, other], provider) { .connect(funds) .approve(interestProvider.address, ethers.constants.MaxUint256); - const initialInterest = ethers.utils.parseEther("500"); - await usdx.transfer(funds._address, initialInterest); - expect(await usdx.balanceOf(funds._address)).to.equal(initialInterest); - const USR = await ethers.getContractFactory("USR"); const usr = await USR.deploy(); await usr.deployed(); @@ -104,7 +100,8 @@ async function fixtureUSRWithMockInterestProvider([wallet, other], provider) { // Transfer some USDx const amount = ethers.utils.parseEther("10000"); - for (const account of accounts) { + + for (const account of others) { await usdx.transfer(account._address, amount); await usdx .connect(account) @@ -145,6 +142,7 @@ async function fixtureUSRWithInterestProvider([wallet, other], provider) { } module.exports = { + loadFixture, fixtureInterestProvider, fixtureUSRWithInterestProvider, fixtureUSRWithMockInterestProvider, diff --git a/test/testInterestProvider.js b/test/testInterestProvider.js index ee98ece..4e5fca7 100644 --- a/test/testInterestProvider.js +++ b/test/testInterestProvider.js @@ -1,10 +1,10 @@ const {expect} = require("chai"); -const {loadFixture} = require("ethereum-waffle"); const BN = ethers.BigNumber; -const {fixtureInterestProvider} = require("./helpers/fixtures.js"); const Collaterals = artifacts.require("Collaterals_t.sol"); +const {loadFixture, fixtureInterestProvider} = require("./helpers/fixtures.js"); + async function printInterestDetails(details, contracts) { console.log("Interest Details:"); for (const i in details[0]) { diff --git a/test/testUSR.js b/test/testUSR.js index 4a2f7d9..ea930d6 100644 --- a/test/testUSR.js +++ b/test/testUSR.js @@ -1,9 +1,9 @@ const {expect} = require("chai"); const BN = ethers.BigNumber; -const {loadFixture} = require("ethereum-waffle"); const USRTruffle = artifacts.require("USR"); const { + loadFixture, fixtureUSRWithMockInterestProvider, fixtureUSRWithInterestProvider, } = require("./helpers/fixtures.js"); @@ -23,7 +23,7 @@ describe("USR with Mock Interest Provider", function () { [owner, ...accounts] = await ethers.getSigners(); }); - describe("Initializable", async function () { + describe("Initializable", function () { it("Should be able to initialize", async function () { const {usr} = await loadFixture(fixtureUSRWithMockInterestProvider); expect(await usr.name()).to.equal("USR"); @@ -122,13 +122,16 @@ describe("USR with Mock Interest Provider", function () { const {usr} = await loadFixture(fixtureUSRWithMockInterestProvider); let account = accounts[1]; + + await usr.pause(); + await expect(usr.unpause()) .to.emit(usr, "Unpaused") .withArgs(owner._address); await usr .connect(account) - .mint(account._address, ethers.utils.parseEther("100")); + .mint(account._address, ethers.utils.parseEther("500")); await usr .connect(account) @@ -145,10 +148,6 @@ describe("USR with Mock Interest Provider", function () { await usr .connect(account) .transfer(accounts[2]._address, ethers.utils.parseEther("100")); - - await usr - .connect(accounts[2]) - .transfer(account._address, ethers.utils.parseEther("100")); }); }); @@ -360,53 +359,37 @@ describe("USR with Mock Interest Provider", function () { expect(changed.usdx).to.equal(balancesBefore.usrUnderlying); }); - - it("Should be able to update fee to zero", async function () { - const {usr} = await loadFixture(fixtureUSRWithMockInterestProvider); - await usr.updateOriginationFee(REDEEM_SELECTOR, 0); - await usr.updateOriginationFee(MINT_SELECTOR, 0); - }); }); describe("ERC20Exchangeable", function () { it("Initial exchange rate should be 1.0", async function () { const {usr} = await loadFixture(fixtureUSRWithMockInterestProvider); - //console.log(ethers.utils.formatEther(await usr.totalSupply())); - expect(await usr.callStatic.exchangeRate()).to.equal( ethers.utils.parseEther("1.0") ); }); it("Should be able to update exchange rate", async function () { - const {usdx, usr, interestProvider} = await loadFixture( + const {usdx, usr, funds} = await loadFixture( fixtureUSRWithMockInterestProvider ); - expect(await usr.callStatic.exchangeRate()).to.equal( - ethers.utils.parseEther("1.0") - ); - let account = accounts[1]; let amount = ethers.utils.parseEther("1000"); await usr.connect(account).mint(account._address, amount); // Mock some profit by direct transfer - await usdx.transfer(usr.address, ethers.utils.parseEther("500")); + await usdx.transfer(funds._address, ethers.utils.parseEther("500")); expect(await usr.callStatic.exchangeRate()).to.equal( ethers.utils.parseEther("1.5") ); - - // await usr - // .connect(account) - // .redeem(account._address, await usr.balanceOf(account._address)); }); it("Should be able to get underlying balance", async function () { - const {usdx, usr, interestProvider} = await loadFixture( + const {usdx, usr, funds} = await loadFixture( fixtureUSRWithMockInterestProvider ); @@ -429,6 +412,9 @@ describe("USR with Mock Interest Provider", function () { .connect(account) .mint(account._address, ethers.utils.parseEther("500")); + // Mock some profit by direct transfer + await usdx.transfer(funds._address, ethers.utils.parseEther("500")); + let balancesAfter = { usrUnderlying: await usr.callStatic.balanceOfUnderlying( account._address @@ -447,11 +433,6 @@ describe("USR with Mock Interest Provider", function () { // There could be some loss of underlying due to the precision let loss = changed.usdx.abs().sub(changed.usrUnderlying.abs()); expect(loss.mul(BASE)).to.lte(exchangeRate); - - // Restore the original state - await usr - .connect(account) - .redeemUnderlying(account._address, balancesAfter.usrUnderlying); }); }); @@ -469,7 +450,7 @@ describe("USR with Mock Interest Provider", function () { }); it("Should be able to mint", async function () { - const {usdx, usr, interestProvider} = await loadFixture( + const {usdx, usr, funds} = await loadFixture( fixtureUSRWithMockInterestProvider ); @@ -490,12 +471,6 @@ describe("USR with Mock Interest Provider", function () { .connect(account) .mint(account._address, ethers.utils.parseEther("500")); - // Mock some profit - await usdx.transfer( - await interestProvider.funds(), - ethers.utils.parseEther("500") - ); - // console.log( // "Account has", // ethers.utils.formatEther(balancesBefore.usr), @@ -529,7 +504,7 @@ describe("USR with Mock Interest Provider", function () { }); it("Should be able to redeem", async function () { - const {usdx, usr, interestProvider} = await loadFixture( + const {usdx, usr, funds} = await loadFixture( fixtureUSRWithMockInterestProvider ); @@ -538,6 +513,9 @@ describe("USR with Mock Interest Provider", function () { let amount = ethers.utils.parseEther("500"); await usr.connect(account).mint(account._address, amount); + // Mock some profit by direct transfer + await usdx.transfer(funds._address, ethers.utils.parseEther("500")); + let exchangeRate = await usr.callStatic.exchangeRate(); // console.log( // "Exchange Rate:", @@ -584,7 +562,7 @@ describe("USR with Mock Interest Provider", function () { }); it("Should be able to redeem from another account", async function () { - const {usdx, usr, interestProvider} = await loadFixture( + const {usdx, usr, funds} = await loadFixture( fixtureUSRWithMockInterestProvider ); @@ -596,6 +574,9 @@ describe("USR with Mock Interest Provider", function () { await usr.connect(from).mint(from._address, amount); await usr.connect(from).approve(account._address, amount); + // Mock some profit by direct transfer + await usdx.transfer(funds._address, ethers.utils.parseEther("500")); + let exchangeRate = await usr.callStatic.exchangeRate(); // console.log( // "Exchange Rate:", @@ -642,7 +623,7 @@ describe("USR with Mock Interest Provider", function () { }); it("Should be able to redeemUnderlying", async function () { - const {usdx, usr, interestProvider} = await loadFixture( + const {usdx, usr, funds} = await loadFixture( fixtureUSRWithMockInterestProvider ); @@ -651,6 +632,9 @@ describe("USR with Mock Interest Provider", function () { await usr.connect(account).mint(account._address, amount); + // Mock some profit by direct transfer + await usdx.transfer(funds._address, ethers.utils.parseEther("500")); + let exchangeRate = await usr.callStatic.exchangeRate(); // console.log( // "Exchange Rate:", @@ -699,7 +683,7 @@ describe("USR with Mock Interest Provider", function () { }); it("Should be able to redeemUnderlying from another account", async function () { - const {usdx, usr, interestProvider} = await loadFixture( + const {usdx, usr, funds} = await loadFixture( fixtureUSRWithMockInterestProvider ); @@ -711,6 +695,9 @@ describe("USR with Mock Interest Provider", function () { await usr.connect(from).mint(from._address, amount); await usr.connect(from).approve(account._address, amount); + // Mock some profit by direct transfer + await usdx.transfer(funds._address, ethers.utils.parseEther("500")); + let exchangeRate = await usr.callStatic.exchangeRate(); // console.log( // "Exchange Rate:", @@ -759,28 +746,30 @@ describe("USR with Mock Interest Provider", function () { }); }); - it("updateInterestProvider()", async function () { - const {usr, interestProvider} = await loadFixture( - fixtureUSRWithMockInterestProvider - ); + describe("Interest Provider", function () { + it("updateInterestProvider()", async function () { + const {usr, interestProvider} = await loadFixture( + fixtureUSRWithMockInterestProvider + ); - await expect( - usr.updateInterestProvider(ethers.constants.AddressZero) - ).to.be.revertedWith( - "updateInterestProvider: interest provider can be not set to 0 or the current one." - ); + await expect( + usr.updateInterestProvider(ethers.constants.AddressZero) + ).to.be.revertedWith( + "updateInterestProvider: interest provider can be not set to 0 or the current one." + ); - await expect( - usr.updateInterestProvider(interestProvider.address) - ).to.be.revertedWith( - "updateInterestProvider: interest provider can be not set to 0 or the current one." - ); + await expect( + usr.updateInterestProvider(interestProvider.address) + ).to.be.revertedWith( + "updateInterestProvider: interest provider can be not set to 0 or the current one." + ); - await usr.updateInterestProvider(usr.address); - expect(await usr.interestProvider()).to.equal(usr.address); + await usr.updateInterestProvider(usr.address); + expect(await usr.interestProvider()).to.equal(usr.address); - // Restore back - await usr.updateInterestProvider(interestProvider.address); + // Restore back + await usr.updateInterestProvider(interestProvider.address); + }); }); }); @@ -833,10 +822,6 @@ describe("USR with Real Interest Provider", function () { // expect(await usr.callStatic.exchangeRate()).to.equal( // ethers.utils.parseEther("1.5") // ); - - // await usr - // .connect(account) - // .redeem(account._address, await usr.balanceOf(account._address)); }); it("Should be able to get underlying balance", async function () { @@ -885,11 +870,6 @@ describe("USR with Real Interest Provider", function () { expect(loss.mul(BASE)).to.lte(exchangeRate); //console.log(balancesAfter.usrUnderlying.toString()); - - // Restore the original state - await usr - .connect(account) - .redeemUnderlying(account._address, balancesAfter.usrUnderlying); }); });