From 65ab6e1db2daf58054bbeeef78ed60f128252f63 Mon Sep 17 00:00:00 2001 From: shmuel Date: Wed, 3 Nov 2021 09:28:30 +0200 Subject: [PATCH 1/7] liquidateLikeTiran --- test/BProtocol.js | 378 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 266 insertions(+), 112 deletions(-) diff --git a/test/BProtocol.js b/test/BProtocol.js index 95a0c69..c8130d8 100644 --- a/test/BProtocol.js +++ b/test/BProtocol.js @@ -687,15 +687,16 @@ describe("KashiPair Basic", function () { } } - describe.only("bamm", function () { - async function getBentoBoxBalance(thisObject, token, address) { - const share = await thisObject.bentoBox.balanceOf(token, address) - return await thisObject.bentoBox.toAmount(token, share, false) - } + async function getBentoBoxBalance(thisObject, token, address) { + const share = await thisObject.bentoBox.balanceOf(token, address) + return await thisObject.bentoBox.toAmount(token, share, false) + } - async function toAmount(thisObject, token, share) { - return await thisObject.bentoBox.toAmount(token, share, false) - } + async function toAmount(thisObject, token, share) { + return await thisObject.bentoBox.toAmount(token, share, false) + } + + describe("bamm", function () { it("deposit and withdraw only with mim", async function () { const bamm = this.BAMM @@ -1041,7 +1042,145 @@ describe("KashiPair Basic", function () { const roundingFactor = getBigNumber(1, 11); expect(deltaMimWithPermium.mul(price).div(getBigNumber(1,18)).div(roundingFactor)).to.be.equal(deltaCol.div(roundingFactor)) }) + }) + + describe("Liquidate", function () { + + it("should not allow open liquidate yet", async function () { + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), + ]) + + await expect( + this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) + ).to.be.revertedWith("KashiPair: all are solvent") + }) + it("should allow open liquidate", async function () { + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + cmd.do(this.oracle.set, "11000000000000000000000000000"), + cmd.updateExchangeRate(), + cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), + cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), + ]) + await this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) + }) + + it("should not allow liquidate for non b.protocol", async function () { + //await this.BkashiPair.setBProtocol(this.bob.address) + //console.log(this.BKashiPair) + + await this.pairHelper.contract.connect(this.alice).setBProtocolMock(this.alice.address) + + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + cmd.do(this.oracle.set, "11000000000000000000000000000"), + cmd.updateExchangeRate(), + cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), + cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), + ]) + await expect( + this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) + ).to.be.revertedWith("liquidate: not bprotocol") + }) + + it("should allow open liquidate with swapper", async function () { + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + cmd.do(this.oracle.set, "11000000000000000000000000000"), + cmd.updateExchangeRate(), + cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), + ]) + await expect( + this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.swapper.address, this.swapper.address, true) + ) + .to.emit(this.pairHelper.contract, "LogRemoveCollateral") + .to.emit(this.pairHelper.contract, "LogRepay") + }) + + it("should allow closed liquidate", async function () { + await this.pairHelper.run((cmd) => [ + // Bob adds 290 asset amount (145 shares) + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + // Alice adds 100 collateral amount (76 shares) + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + // Alice borrows 75 asset amount + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + // Change oracle to put Alice into insolvency + cmd.do(this.oracle.set, "11000000000000000000000000000"), + //cmd.do(this.a.transfer, this.sushiSwapPair.address, getBigNumber(500)), + //cmd.do(this.sushiSwapPair.sync), + cmd.updateExchangeRate(), + ]) + + // Bob liquidates Alice for 20 asset parts (approx 20 asset amount = 10 asset shares) + await this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.swapper.address, this.swapper.address, false) + }) + + it("should not allow closed liquidate with invalid swapper", async function () { + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(340, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + ]) + + await cmd.deploy( + "invalidSwapper", + "SushiSwapSwapper", + this.bentoBox.address, + this.factory.address, + await this.factory.pairCodeHash() + ) + await expect( + this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.invalidSwapper.address, this.invalidSwapper.address, false) + ).to.be.revertedWith("KashiPair: Invalid swapper") + }) + + }) + + + describe.only('liquidateLikeTiran', function () { + it("liquidateLikeTiran", async function () { const bamm = this.BAMM const price = getBigNumber(11, 27); @@ -1078,7 +1217,6 @@ describe("KashiPair Basic", function () { const pairMimBalBefore = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) const nullAddr = "0x0000000000000000000000000000000000000000" const rewardAddress = "0x0000000000000000000000000000000000000007" - const rewardBalanceBefore = await getBentoBoxBalance(this, this.b.address, rewardAddress) // liquidate await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); @@ -1108,6 +1246,77 @@ describe("KashiPair Basic", function () { expect(collateralInMim).to.be.equal(roundedRewardBalance) }) + it("when BAMM has sufficient funds liquidateLikeTiran should return tiran money", async function () { + const bamm = this.BAMM + const price = getBigNumber(11, 27); + + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + cmd.do(this.oracle.set, price.toString()), + cmd.updateExchangeRate(), + cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), + cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), + ]) + + await bamm.setParams(20, 0, 100) + + // deposit + const liquidationShare = await this.pairHelper.contract.userBorrowPart(this.alice.address) //getBigNumber(20, 18); + const liquidationAmount = (await toAmount(this, this.b.address, liquidationShare)).add(11) + + // making sure bamm has sufficient funds + const depositAmonut = liquidationAmount + await this.b.connect(this.bob).approve(this.bentoBox.address, depositAmonut); + await this.bentoBox.connect(this.bob).deposit(this.b.address, this.bob.address, this.bob.address, depositAmonut, 0) + await setMasterContractApproval(this.bentoBox, this.bob, this.bob, this.bobPrivateKey, bamm.address, true) + await bamm.connect(this.bob).deposit(depositAmonut, true); + + const bammMimBalBefore = await getBentoBoxBalance(this, this.b.address, bamm.address) + const bobMimBalBefore = await this.b.balanceOf(this.bob.address) + const bammColBalBefore = await getBentoBoxBalance(this, this.a.address, bamm.address) + const pairMimBalBefore = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) + const nullAddr = "0x0000000000000000000000000000000000000000" + const rewardAddress = "0x0000000000000000000000000000000000000007" + + // liquidate + await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); + await bamm.connect(this.bob).liquidateLikeTiran(liquidationAmount, [this.alice.address], [liquidationShare], rewardAddress, nullAddr, false) + const bammMimBalAfter = await getBentoBoxBalance(this, this.b.address, bamm.address) + const bammColBalAfter = await getBentoBoxBalance(this, this.a.address, bamm.address) + const pairMimBalAfter = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) + + const deltaMimBamm = bammMimBalBefore.sub(bammMimBalAfter) + const deltaMimPair = pairMimBalAfter.sub(pairMimBalBefore) + const bobMimBalAfter = await this.b.balanceOf(this.bob.address) + + const rewardBalance = await this.a.balanceOf(rewardAddress) + + // tirans funds sould be returned + expect(bobMimBalAfter).to.be.equal(bobMimBalBefore) + + // tirans collateral should not get any collateral reward + expect(rewardBalance).to.be.equal(0) + + // check bamm MIM makes sense + expect( + isEqualWithRoundingErrorFlexability(bammMimBalBefore.sub(deltaMimPair), bammMimBalAfter, 2) + ).to.be.true + + const roundingFactor = getBigNumber(1, 11); + const deltaMimWithPermium = deltaMimPair.mul(112).div(100) + const collateralInMim = deltaMimWithPermium.mul(price).div(getBigNumber(1,18)).div(roundingFactor) + const roundedBammCollBalance = bammColBalAfter.div(roundingFactor) + + expect(bammColBalBefore).to.be.equal(0) + // liquidated collateral should be in the BAMM + expect(collateralInMim).to.be.equal(roundedBammCollBalance) + }) + it("liquidateLikeTiran via bentoBox", async function () { const bamm = this.BAMM const price = getBigNumber(11, 27); @@ -1145,7 +1354,6 @@ describe("KashiPair Basic", function () { const pairMimBalBefore = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) const nullAddr = "0x0000000000000000000000000000000000000000" const rewardAddress = "0x0000000000000000000000000000000000000007" - const rewardBalanceBefore = await getBentoBoxBalance(this, this.b.address, rewardAddress) // liquidate await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); @@ -1155,7 +1363,6 @@ describe("KashiPair Basic", function () { const deltaMimBamm = bammMimBalBefore.sub(bammMimBalAfter) const deltaMimPair = pairMimBalAfter.sub(pairMimBalBefore) - const bobMimBalAfter = await this.b.balanceOf(this.bob.address) const bobMimBentoBalAfter = await getBentoBoxBalance(this, this.b.address, this.bob.address) const rewardBalance = await getBentoBoxBalance(this, this.a.address, rewardAddress) // check bamm MIM is the same @@ -1171,30 +1378,18 @@ describe("KashiPair Basic", function () { expect(collateralInMim).to.be.equal(roundedRewardBalance) }) - // liquidate normal test - TODO - }) - - describe.only("Liquidate", function () { + it("liquidateLikeTiran insufficent funds", async function () { + const bamm = this.BAMM + const price = getBigNumber(11, 27); - it("should not allow open liquidate yet", async function () { - await this.pairHelper.run((cmd) => [ - cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), - cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - cmd.approveCollateral(getBigNumber(100)), - cmd.depositCollateral(getBigNumber(100)), - cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), - cmd.accrue(), - cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), - ]) + // bob bento deposit setup + const depositAmonut = getBigNumber(1000, 0) + await this.b.connect(this.bob).approve(this.bentoBox.address, depositAmonut); + await this.bentoBox.connect(this.bob).deposit(this.b.address, this.bob.address, this.bob.address, depositAmonut, 0) + await setMasterContractApproval(this.bentoBox, this.bob, this.bob, this.bobPrivateKey, bamm.address, true) + await bamm.connect(this.bob).deposit(depositAmonut, true); - await expect( - this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) - ).to.be.revertedWith("KashiPair: all are solvent") - }) - it("should allow open liquidate", async function () { await this.pairHelper.run((cmd) => [ cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), @@ -1202,110 +1397,66 @@ describe("KashiPair Basic", function () { cmd.depositCollateral(getBigNumber(100)), cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), cmd.accrue(), - cmd.do(this.oracle.set, "11000000000000000000000000000"), + cmd.do(this.oracle.set, price.toString()), cmd.updateExchangeRate(), cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), ]) - await this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) - }) - - it("should not allow liquidate for non b.protocol", async function () { - //await this.BkashiPair.setBProtocol(this.bob.address) - //console.log(this.BKashiPair) - await this.pairHelper.contract.connect(this.alice).setBProtocolMock(this.alice.address) + await bamm.setParams(20, 0, 100) - await this.pairHelper.run((cmd) => [ - cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), - cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - cmd.approveCollateral(getBigNumber(100)), - cmd.depositCollateral(getBigNumber(100)), - cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), - cmd.accrue(), - cmd.do(this.oracle.set, "11000000000000000000000000000"), - cmd.updateExchangeRate(), - cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), - cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), - ]) - await expect( - this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) - ).to.be.revertedWith("liquidate: not bprotocol") - }) + // deposit + const liquidationShare = await this.pairHelper.contract.userBorrowPart(this.alice.address) //getBigNumber(20, 18); + const liquidationAmount = getBigNumber(1, 4)//(await toAmount(this, this.b.address, liquidationShare)).add(11) + const nullAddr = "0x0000000000000000000000000000000000000000" + const rewardAddress = "0x0000000000000000000000000000000000000007" - it("should allow open liquidate with swapper", async function () { - await this.pairHelper.run((cmd) => [ - cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), - cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - cmd.approveCollateral(getBigNumber(100)), - cmd.depositCollateral(getBigNumber(100)), - cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), - cmd.accrue(), - cmd.do(this.oracle.set, "11000000000000000000000000000"), - cmd.updateExchangeRate(), - cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), - ]) + await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); await expect( - this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.swapper.address, this.swapper.address, true) - ) - .to.emit(this.pairHelper.contract, "LogRemoveCollateral") - .to.emit(this.pairHelper.contract, "LogRepay") + bamm.connect(this.bob) + .liquidateLikeTiran(liquidationAmount, [this.alice.address], [liquidationShare], rewardAddress, nullAddr, false) + ).to.be.revertedWith('BoringMath: Underflow') }) - it("should allow closed liquidate", async function () { + it("liquidateLikeTiran tiran calims to provide all funds but provides half", async function () { + const bamm = this.BAMM + const price = getBigNumber(11, 27); + const halfTheLiquidationAmount = getBigNumber(7500000027, 0).div(2) + // bob bento deposit setup + const depositAmonut = halfTheLiquidationAmount + await this.b.connect(this.bob).approve(this.bentoBox.address, depositAmonut); + await this.bentoBox.connect(this.bob).deposit(this.b.address, this.bob.address, this.bob.address, depositAmonut, 0) + await setMasterContractApproval(this.bentoBox, this.bob, this.bob, this.bobPrivateKey, bamm.address, true) + await bamm.connect(this.bob).deposit(depositAmonut, true); + + await this.pairHelper.run((cmd) => [ - // Bob adds 290 asset amount (145 shares) cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - // Alice adds 100 collateral amount (76 shares) cmd.approveCollateral(getBigNumber(100)), cmd.depositCollateral(getBigNumber(100)), - // Alice borrows 75 asset amount cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), cmd.accrue(), - // Change oracle to put Alice into insolvency - cmd.do(this.oracle.set, "11000000000000000000000000000"), - //cmd.do(this.a.transfer, this.sushiSwapPair.address, getBigNumber(500)), - //cmd.do(this.sushiSwapPair.sync), + cmd.do(this.oracle.set, price.toString()), cmd.updateExchangeRate(), + cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), + cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), ]) - // Bob liquidates Alice for 20 asset parts (approx 20 asset amount = 10 asset shares) - await this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.swapper.address, this.swapper.address, false) - }) + await bamm.setParams(20, 0, 100) - it("should not allow closed liquidate with invalid swapper", async function () { - await this.pairHelper.run((cmd) => [ - cmd.as(this.bob).approveAsset(getBigNumber(340, 8)), - cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - cmd.approveCollateral(getBigNumber(100)), - cmd.depositCollateral(getBigNumber(100)), - cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), - cmd.accrue(), - ]) + // deposit + const liquidationShare = await this.pairHelper.contract.userBorrowPart(this.alice.address) //getBigNumber(20, 18); + const liquidationAmount = halfTheLiquidationAmount + const nullAddr = "0x0000000000000000000000000000000000000000" + const rewardAddress = "0x0000000000000000000000000000000000000007" - await cmd.deploy( - "invalidSwapper", - "SushiSwapSwapper", - this.bentoBox.address, - this.factory.address, - await this.factory.pairCodeHash() - ) + await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); await expect( - this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.invalidSwapper.address, this.invalidSwapper.address, false) - ).to.be.revertedWith("KashiPair: Invalid swapper") + bamm.connect(this.bob) + .liquidateLikeTiran(liquidationAmount, [this.alice.address], [liquidationShare], rewardAddress, nullAddr, false) + ).to.be.revertedWith('liquidateLikeTiran: insufficent extraMim') }) - }) describe("Withdraw Fees", function () { @@ -1338,6 +1489,9 @@ describe("KashiPair Basic", function () { await this.pairHelper.run((cmd) => [cmd.repay(part)]) await this.pairHelper.contract.withdrawFees() await expect(this.pairHelper.contract.withdrawFees()).to.emit(this.pairHelper.contract, "LogWithdrawFees") + + const bammMimDelta = bammMimBalAfter.sub(bammMimBalBefore) + const tiranMimDelta = tiranMimBalAfter.sub(tiranMimBalBefore) }) }) From 888beafdfd30929520ebbbfd28a96ce12dcb5b48 Mon Sep 17 00:00:00 2001 From: shmuel Date: Wed, 3 Nov 2021 10:42:17 +0200 Subject: [PATCH 2/7] remove liquidateLikeTiran describe block --- test/BProtocol.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test/BProtocol.js b/test/BProtocol.js index c8130d8..7fa520f 100644 --- a/test/BProtocol.js +++ b/test/BProtocol.js @@ -696,8 +696,7 @@ describe("KashiPair Basic", function () { return await thisObject.bentoBox.toAmount(token, share, false) } - describe("bamm", function () { - + describe.only("bamm", function () { it("deposit and withdraw only with mim", async function () { const bamm = this.BAMM const depositAmonut = getBigNumber(2, 18); @@ -1175,11 +1174,6 @@ describe("KashiPair Basic", function () { .liquidate([this.alice.address], [getBigNumber(20, 8)], this.invalidSwapper.address, this.invalidSwapper.address, false) ).to.be.revertedWith("KashiPair: Invalid swapper") }) - - }) - - - describe.only('liquidateLikeTiran', function () { it("liquidateLikeTiran", async function () { const bamm = this.BAMM From 3c702f68c0ee006971fb21a3d5bbd4ed9eff32bf Mon Sep 17 00:00:00 2001 From: shmuel Date: Wed, 3 Nov 2021 11:01:50 +0200 Subject: [PATCH 3/7] initial-state --- test/BProtocol.js | 374 ++++++++++++++-------------------------------- 1 file changed, 113 insertions(+), 261 deletions(-) diff --git a/test/BProtocol.js b/test/BProtocol.js index 7fa520f..4ca3a60 100644 --- a/test/BProtocol.js +++ b/test/BProtocol.js @@ -687,16 +687,16 @@ describe("KashiPair Basic", function () { } } - async function getBentoBoxBalance(thisObject, token, address) { - const share = await thisObject.bentoBox.balanceOf(token, address) - return await thisObject.bentoBox.toAmount(token, share, false) - } + describe.only("bamm", function () { + async function getBentoBoxBalance(thisObject, token, address) { + const share = await thisObject.bentoBox.balanceOf(token, address) + return await thisObject.bentoBox.toAmount(token, share, false) + } - async function toAmount(thisObject, token, share) { - return await thisObject.bentoBox.toAmount(token, share, false) - } + async function toAmount(thisObject, token, share) { + return await thisObject.bentoBox.toAmount(token, share, false) + } - describe.only("bamm", function () { it("deposit and withdraw only with mim", async function () { const bamm = this.BAMM const depositAmonut = getBigNumber(2, 18); @@ -1041,140 +1041,7 @@ describe("KashiPair Basic", function () { const roundingFactor = getBigNumber(1, 11); expect(deltaMimWithPermium.mul(price).div(getBigNumber(1,18)).div(roundingFactor)).to.be.equal(deltaCol.div(roundingFactor)) }) - }) - - describe("Liquidate", function () { - - it("should not allow open liquidate yet", async function () { - await this.pairHelper.run((cmd) => [ - cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), - cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - cmd.approveCollateral(getBigNumber(100)), - cmd.depositCollateral(getBigNumber(100)), - cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), - cmd.accrue(), - cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), - ]) - - await expect( - this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) - ).to.be.revertedWith("KashiPair: all are solvent") - }) - - it("should allow open liquidate", async function () { - await this.pairHelper.run((cmd) => [ - cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), - cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - cmd.approveCollateral(getBigNumber(100)), - cmd.depositCollateral(getBigNumber(100)), - cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), - cmd.accrue(), - cmd.do(this.oracle.set, "11000000000000000000000000000"), - cmd.updateExchangeRate(), - cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), - cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), - ]) - await this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) - }) - it("should not allow liquidate for non b.protocol", async function () { - //await this.BkashiPair.setBProtocol(this.bob.address) - //console.log(this.BKashiPair) - - await this.pairHelper.contract.connect(this.alice).setBProtocolMock(this.alice.address) - - await this.pairHelper.run((cmd) => [ - cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), - cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - cmd.approveCollateral(getBigNumber(100)), - cmd.depositCollateral(getBigNumber(100)), - cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), - cmd.accrue(), - cmd.do(this.oracle.set, "11000000000000000000000000000"), - cmd.updateExchangeRate(), - cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), - cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), - ]) - await expect( - this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) - ).to.be.revertedWith("liquidate: not bprotocol") - }) - - it("should allow open liquidate with swapper", async function () { - await this.pairHelper.run((cmd) => [ - cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), - cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - cmd.approveCollateral(getBigNumber(100)), - cmd.depositCollateral(getBigNumber(100)), - cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), - cmd.accrue(), - cmd.do(this.oracle.set, "11000000000000000000000000000"), - cmd.updateExchangeRate(), - cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), - ]) - await expect( - this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.swapper.address, this.swapper.address, true) - ) - .to.emit(this.pairHelper.contract, "LogRemoveCollateral") - .to.emit(this.pairHelper.contract, "LogRepay") - }) - - it("should allow closed liquidate", async function () { - await this.pairHelper.run((cmd) => [ - // Bob adds 290 asset amount (145 shares) - cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), - cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - // Alice adds 100 collateral amount (76 shares) - cmd.approveCollateral(getBigNumber(100)), - cmd.depositCollateral(getBigNumber(100)), - // Alice borrows 75 asset amount - cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), - cmd.accrue(), - // Change oracle to put Alice into insolvency - cmd.do(this.oracle.set, "11000000000000000000000000000"), - //cmd.do(this.a.transfer, this.sushiSwapPair.address, getBigNumber(500)), - //cmd.do(this.sushiSwapPair.sync), - cmd.updateExchangeRate(), - ]) - - // Bob liquidates Alice for 20 asset parts (approx 20 asset amount = 10 asset shares) - await this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.swapper.address, this.swapper.address, false) - }) - - it("should not allow closed liquidate with invalid swapper", async function () { - await this.pairHelper.run((cmd) => [ - cmd.as(this.bob).approveAsset(getBigNumber(340, 8)), - cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - cmd.approveCollateral(getBigNumber(100)), - cmd.depositCollateral(getBigNumber(100)), - cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), - cmd.accrue(), - ]) - - await cmd.deploy( - "invalidSwapper", - "SushiSwapSwapper", - this.bentoBox.address, - this.factory.address, - await this.factory.pairCodeHash() - ) - await expect( - this.pairHelper.contract - .connect(this.bob) - .liquidate([this.alice.address], [getBigNumber(20, 8)], this.invalidSwapper.address, this.invalidSwapper.address, false) - ).to.be.revertedWith("KashiPair: Invalid swapper") - }) - it("liquidateLikeTiran", async function () { const bamm = this.BAMM const price = getBigNumber(11, 27); @@ -1211,6 +1078,7 @@ describe("KashiPair Basic", function () { const pairMimBalBefore = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) const nullAddr = "0x0000000000000000000000000000000000000000" const rewardAddress = "0x0000000000000000000000000000000000000007" + const rewardBalanceBefore = await getBentoBoxBalance(this, this.b.address, rewardAddress) // liquidate await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); @@ -1240,77 +1108,6 @@ describe("KashiPair Basic", function () { expect(collateralInMim).to.be.equal(roundedRewardBalance) }) - it("when BAMM has sufficient funds liquidateLikeTiran should return tiran money", async function () { - const bamm = this.BAMM - const price = getBigNumber(11, 27); - - await this.pairHelper.run((cmd) => [ - cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), - cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), - cmd.approveCollateral(getBigNumber(100)), - cmd.depositCollateral(getBigNumber(100)), - cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), - cmd.accrue(), - cmd.do(this.oracle.set, price.toString()), - cmd.updateExchangeRate(), - cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), - cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), - ]) - - await bamm.setParams(20, 0, 100) - - // deposit - const liquidationShare = await this.pairHelper.contract.userBorrowPart(this.alice.address) //getBigNumber(20, 18); - const liquidationAmount = (await toAmount(this, this.b.address, liquidationShare)).add(11) - - // making sure bamm has sufficient funds - const depositAmonut = liquidationAmount - await this.b.connect(this.bob).approve(this.bentoBox.address, depositAmonut); - await this.bentoBox.connect(this.bob).deposit(this.b.address, this.bob.address, this.bob.address, depositAmonut, 0) - await setMasterContractApproval(this.bentoBox, this.bob, this.bob, this.bobPrivateKey, bamm.address, true) - await bamm.connect(this.bob).deposit(depositAmonut, true); - - const bammMimBalBefore = await getBentoBoxBalance(this, this.b.address, bamm.address) - const bobMimBalBefore = await this.b.balanceOf(this.bob.address) - const bammColBalBefore = await getBentoBoxBalance(this, this.a.address, bamm.address) - const pairMimBalBefore = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) - const nullAddr = "0x0000000000000000000000000000000000000000" - const rewardAddress = "0x0000000000000000000000000000000000000007" - - // liquidate - await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); - await bamm.connect(this.bob).liquidateLikeTiran(liquidationAmount, [this.alice.address], [liquidationShare], rewardAddress, nullAddr, false) - const bammMimBalAfter = await getBentoBoxBalance(this, this.b.address, bamm.address) - const bammColBalAfter = await getBentoBoxBalance(this, this.a.address, bamm.address) - const pairMimBalAfter = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) - - const deltaMimBamm = bammMimBalBefore.sub(bammMimBalAfter) - const deltaMimPair = pairMimBalAfter.sub(pairMimBalBefore) - const bobMimBalAfter = await this.b.balanceOf(this.bob.address) - - const rewardBalance = await this.a.balanceOf(rewardAddress) - - // tirans funds sould be returned - expect(bobMimBalAfter).to.be.equal(bobMimBalBefore) - - // tirans collateral should not get any collateral reward - expect(rewardBalance).to.be.equal(0) - - // check bamm MIM makes sense - expect( - isEqualWithRoundingErrorFlexability(bammMimBalBefore.sub(deltaMimPair), bammMimBalAfter, 2) - ).to.be.true - - const roundingFactor = getBigNumber(1, 11); - const deltaMimWithPermium = deltaMimPair.mul(112).div(100) - const collateralInMim = deltaMimWithPermium.mul(price).div(getBigNumber(1,18)).div(roundingFactor) - const roundedBammCollBalance = bammColBalAfter.div(roundingFactor) - - expect(bammColBalBefore).to.be.equal(0) - // liquidated collateral should be in the BAMM - expect(collateralInMim).to.be.equal(roundedBammCollBalance) - }) - it("liquidateLikeTiran via bentoBox", async function () { const bamm = this.BAMM const price = getBigNumber(11, 27); @@ -1348,6 +1145,7 @@ describe("KashiPair Basic", function () { const pairMimBalBefore = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) const nullAddr = "0x0000000000000000000000000000000000000000" const rewardAddress = "0x0000000000000000000000000000000000000007" + const rewardBalanceBefore = await getBentoBoxBalance(this, this.b.address, rewardAddress) // liquidate await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); @@ -1357,6 +1155,7 @@ describe("KashiPair Basic", function () { const deltaMimBamm = bammMimBalBefore.sub(bammMimBalAfter) const deltaMimPair = pairMimBalAfter.sub(pairMimBalBefore) + const bobMimBalAfter = await this.b.balanceOf(this.bob.address) const bobMimBentoBalAfter = await getBentoBoxBalance(this, this.b.address, this.bob.address) const rewardBalance = await getBentoBoxBalance(this, this.a.address, rewardAddress) // check bamm MIM is the same @@ -1372,18 +1171,30 @@ describe("KashiPair Basic", function () { expect(collateralInMim).to.be.equal(roundedRewardBalance) }) - it("liquidateLikeTiran insufficent funds", async function () { - const bamm = this.BAMM - const price = getBigNumber(11, 27); + // liquidate normal test - TODO + }) - // bob bento deposit setup - const depositAmonut = getBigNumber(1000, 0) - await this.b.connect(this.bob).approve(this.bentoBox.address, depositAmonut); - await this.bentoBox.connect(this.bob).deposit(this.b.address, this.bob.address, this.bob.address, depositAmonut, 0) - await setMasterContractApproval(this.bentoBox, this.bob, this.bob, this.bobPrivateKey, bamm.address, true) - await bamm.connect(this.bob).deposit(depositAmonut, true); + describe.only("Liquidate", function () { + + it("should not allow open liquidate yet", async function () { + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), + ]) + await expect( + this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) + ).to.be.revertedWith("KashiPair: all are solvent") + }) + it("should allow open liquidate", async function () { await this.pairHelper.run((cmd) => [ cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), @@ -1391,38 +1202,21 @@ describe("KashiPair Basic", function () { cmd.depositCollateral(getBigNumber(100)), cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), cmd.accrue(), - cmd.do(this.oracle.set, price.toString()), + cmd.do(this.oracle.set, "11000000000000000000000000000"), cmd.updateExchangeRate(), cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), ]) - - await bamm.setParams(20, 0, 100) - - // deposit - const liquidationShare = await this.pairHelper.contract.userBorrowPart(this.alice.address) //getBigNumber(20, 18); - const liquidationAmount = getBigNumber(1, 4)//(await toAmount(this, this.b.address, liquidationShare)).add(11) - const nullAddr = "0x0000000000000000000000000000000000000000" - const rewardAddress = "0x0000000000000000000000000000000000000007" - - await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); - await expect( - bamm.connect(this.bob) - .liquidateLikeTiran(liquidationAmount, [this.alice.address], [liquidationShare], rewardAddress, nullAddr, false) - ).to.be.revertedWith('BoringMath: Underflow') + await this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) }) - it("liquidateLikeTiran tiran calims to provide all funds but provides half", async function () { - const bamm = this.BAMM - const price = getBigNumber(11, 27); - const halfTheLiquidationAmount = getBigNumber(7500000027, 0).div(2) - // bob bento deposit setup - const depositAmonut = halfTheLiquidationAmount - await this.b.connect(this.bob).approve(this.bentoBox.address, depositAmonut); - await this.bentoBox.connect(this.bob).deposit(this.b.address, this.bob.address, this.bob.address, depositAmonut, 0) - await setMasterContractApproval(this.bentoBox, this.bob, this.bob, this.bobPrivateKey, bamm.address, true) - await bamm.connect(this.bob).deposit(depositAmonut, true); + it("should not allow liquidate for non b.protocol", async function () { + //await this.BkashiPair.setBProtocol(this.bob.address) + //console.log(this.BKashiPair) + await this.pairHelper.contract.connect(this.alice).setBProtocolMock(this.alice.address) await this.pairHelper.run((cmd) => [ cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), @@ -1431,26 +1225,87 @@ describe("KashiPair Basic", function () { cmd.depositCollateral(getBigNumber(100)), cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), cmd.accrue(), - cmd.do(this.oracle.set, price.toString()), + cmd.do(this.oracle.set, "11000000000000000000000000000"), cmd.updateExchangeRate(), cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), ]) + await expect( + this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.bob.address, "0x0000000000000000000000000000000000000000", true) + ).to.be.revertedWith("liquidate: not bprotocol") + }) - await bamm.setParams(20, 0, 100) + it("should allow open liquidate with swapper", async function () { + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + cmd.do(this.oracle.set, "11000000000000000000000000000"), + cmd.updateExchangeRate(), + cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), + ]) + await expect( + this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.swapper.address, this.swapper.address, true) + ) + .to.emit(this.pairHelper.contract, "LogRemoveCollateral") + .to.emit(this.pairHelper.contract, "LogRepay") + }) - // deposit - const liquidationShare = await this.pairHelper.contract.userBorrowPart(this.alice.address) //getBigNumber(20, 18); - const liquidationAmount = halfTheLiquidationAmount - const nullAddr = "0x0000000000000000000000000000000000000000" - const rewardAddress = "0x0000000000000000000000000000000000000007" + it("should allow closed liquidate", async function () { + await this.pairHelper.run((cmd) => [ + // Bob adds 290 asset amount (145 shares) + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + // Alice adds 100 collateral amount (76 shares) + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + // Alice borrows 75 asset amount + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + // Change oracle to put Alice into insolvency + cmd.do(this.oracle.set, "11000000000000000000000000000"), + //cmd.do(this.a.transfer, this.sushiSwapPair.address, getBigNumber(500)), + //cmd.do(this.sushiSwapPair.sync), + cmd.updateExchangeRate(), + ]) - await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); + // Bob liquidates Alice for 20 asset parts (approx 20 asset amount = 10 asset shares) + await this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.swapper.address, this.swapper.address, false) + }) + + it("should not allow closed liquidate with invalid swapper", async function () { + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(340, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + ]) + + await cmd.deploy( + "invalidSwapper", + "SushiSwapSwapper", + this.bentoBox.address, + this.factory.address, + await this.factory.pairCodeHash() + ) await expect( - bamm.connect(this.bob) - .liquidateLikeTiran(liquidationAmount, [this.alice.address], [liquidationShare], rewardAddress, nullAddr, false) - ).to.be.revertedWith('liquidateLikeTiran: insufficent extraMim') + this.pairHelper.contract + .connect(this.bob) + .liquidate([this.alice.address], [getBigNumber(20, 8)], this.invalidSwapper.address, this.invalidSwapper.address, false) + ).to.be.revertedWith("KashiPair: Invalid swapper") }) + }) describe("Withdraw Fees", function () { @@ -1483,9 +1338,6 @@ describe("KashiPair Basic", function () { await this.pairHelper.run((cmd) => [cmd.repay(part)]) await this.pairHelper.contract.withdrawFees() await expect(this.pairHelper.contract.withdrawFees()).to.emit(this.pairHelper.contract, "LogWithdrawFees") - - const bammMimDelta = bammMimBalAfter.sub(bammMimBalBefore) - const tiranMimDelta = tiranMimBalAfter.sub(tiranMimBalBefore) }) }) @@ -1506,4 +1358,4 @@ describe("KashiPair Basic", function () { await expect(this.pairHelper.contract.connect(this.bob).setFeeTo(this.bob.address)).to.be.revertedWith("caller is not the owner") }) }) -}) +}) \ No newline at end of file From 10e4ceef196a5bb0cbbfe81959d9b77a6de61e8b Mon Sep 17 00:00:00 2001 From: shmuel Date: Wed, 3 Nov 2021 11:07:25 +0200 Subject: [PATCH 4/7] fixing order of tests --- test/BProtocol.js | 157 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 153 insertions(+), 4 deletions(-) diff --git a/test/BProtocol.js b/test/BProtocol.js index 4ca3a60..9734da9 100644 --- a/test/BProtocol.js +++ b/test/BProtocol.js @@ -859,6 +859,8 @@ describe("KashiPair Basic", function () { }) + + /* it('test getSwapEthAmount', async () => { // --- SETUP --- @@ -1078,7 +1080,6 @@ describe("KashiPair Basic", function () { const pairMimBalBefore = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) const nullAddr = "0x0000000000000000000000000000000000000000" const rewardAddress = "0x0000000000000000000000000000000000000007" - const rewardBalanceBefore = await getBentoBoxBalance(this, this.b.address, rewardAddress) // liquidate await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); @@ -1108,6 +1109,7 @@ describe("KashiPair Basic", function () { expect(collateralInMim).to.be.equal(roundedRewardBalance) }) + it("liquidateLikeTiran via bentoBox", async function () { const bamm = this.BAMM const price = getBigNumber(11, 27); @@ -1145,7 +1147,6 @@ describe("KashiPair Basic", function () { const pairMimBalBefore = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) const nullAddr = "0x0000000000000000000000000000000000000000" const rewardAddress = "0x0000000000000000000000000000000000000007" - const rewardBalanceBefore = await getBentoBoxBalance(this, this.b.address, rewardAddress) // liquidate await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); @@ -1155,7 +1156,6 @@ describe("KashiPair Basic", function () { const deltaMimBamm = bammMimBalBefore.sub(bammMimBalAfter) const deltaMimPair = pairMimBalAfter.sub(pairMimBalBefore) - const bobMimBalAfter = await this.b.balanceOf(this.bob.address) const bobMimBentoBalAfter = await getBentoBoxBalance(this, this.b.address, this.bob.address) const rewardBalance = await getBentoBoxBalance(this, this.a.address, rewardAddress) // check bamm MIM is the same @@ -1171,7 +1171,156 @@ describe("KashiPair Basic", function () { expect(collateralInMim).to.be.equal(roundedRewardBalance) }) - // liquidate normal test - TODO + it("when BAMM has sufficient funds liquidateLikeTiran should return tiran money", async function () { + const bamm = this.BAMM + const price = getBigNumber(11, 27); + + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + cmd.do(this.oracle.set, price.toString()), + cmd.updateExchangeRate(), + cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), + cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), + ]) + + await bamm.setParams(20, 0, 100) + + // deposit + const liquidationShare = await this.pairHelper.contract.userBorrowPart(this.alice.address) //getBigNumber(20, 18); + const liquidationAmount = (await toAmount(this, this.b.address, liquidationShare)).add(11) + + // making sure bamm has sufficient funds + const depositAmonut = liquidationAmount + await this.b.connect(this.bob).approve(this.bentoBox.address, depositAmonut); + await this.bentoBox.connect(this.bob).deposit(this.b.address, this.bob.address, this.bob.address, depositAmonut, 0) + await setMasterContractApproval(this.bentoBox, this.bob, this.bob, this.bobPrivateKey, bamm.address, true) + await bamm.connect(this.bob).deposit(depositAmonut, true); + + const bammMimBalBefore = await getBentoBoxBalance(this, this.b.address, bamm.address) + const bobMimBalBefore = await this.b.balanceOf(this.bob.address) + const bammColBalBefore = await getBentoBoxBalance(this, this.a.address, bamm.address) + const pairMimBalBefore = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) + const nullAddr = "0x0000000000000000000000000000000000000000" + const rewardAddress = "0x0000000000000000000000000000000000000007" + + // liquidate + await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); + await bamm.connect(this.bob).liquidateLikeTiran(liquidationAmount, [this.alice.address], [liquidationShare], rewardAddress, nullAddr, false) + const bammMimBalAfter = await getBentoBoxBalance(this, this.b.address, bamm.address) + const bammColBalAfter = await getBentoBoxBalance(this, this.a.address, bamm.address) + const pairMimBalAfter = await getBentoBoxBalance(this, this.b.address, this.pairHelper.contract.address) + + const deltaMimBamm = bammMimBalBefore.sub(bammMimBalAfter) + const deltaMimPair = pairMimBalAfter.sub(pairMimBalBefore) + const bobMimBalAfter = await this.b.balanceOf(this.bob.address) + + const rewardBalance = await this.a.balanceOf(rewardAddress) + + // tirans funds sould be returned + expect(bobMimBalAfter).to.be.equal(bobMimBalBefore) + + // tirans collateral should not get any collateral reward + expect(rewardBalance).to.be.equal(0) + + // check bamm MIM makes sense + expect( + isEqualWithRoundingErrorFlexability(bammMimBalBefore.sub(deltaMimPair), bammMimBalAfter, 2) + ).to.be.true + + const roundingFactor = getBigNumber(1, 11); + const deltaMimWithPermium = deltaMimPair.mul(112).div(100) + const collateralInMim = deltaMimWithPermium.mul(price).div(getBigNumber(1,18)).div(roundingFactor) + const roundedBammCollBalance = bammColBalAfter.div(roundingFactor) + + expect(bammColBalBefore).to.be.equal(0) + // liquidated collateral should be in the BAMM + expect(collateralInMim).to.be.equal(roundedBammCollBalance) + }) + + it("liquidateLikeTiran insufficent funds", async function () { + const bamm = this.BAMM + const price = getBigNumber(11, 27); + + // bob bento deposit setup + const depositAmonut = getBigNumber(1000, 0) + await this.b.connect(this.bob).approve(this.bentoBox.address, depositAmonut); + await this.bentoBox.connect(this.bob).deposit(this.b.address, this.bob.address, this.bob.address, depositAmonut, 0) + await setMasterContractApproval(this.bentoBox, this.bob, this.bob, this.bobPrivateKey, bamm.address, true) + await bamm.connect(this.bob).deposit(depositAmonut, true); + + + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + cmd.do(this.oracle.set, price.toString()), + cmd.updateExchangeRate(), + cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), + cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), + ]) + + await bamm.setParams(20, 0, 100) + + // deposit + const liquidationShare = await this.pairHelper.contract.userBorrowPart(this.alice.address) //getBigNumber(20, 18); + const liquidationAmount = getBigNumber(1, 4)//(await toAmount(this, this.b.address, liquidationShare)).add(11) + const nullAddr = "0x0000000000000000000000000000000000000000" + const rewardAddress = "0x0000000000000000000000000000000000000007" + + await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); + await expect( + bamm.connect(this.bob) + .liquidateLikeTiran(liquidationAmount, [this.alice.address], [liquidationShare], rewardAddress, nullAddr, false) + ).to.be.revertedWith('BoringMath: Underflow') + }) + + it("liquidateLikeTiran tiran calims to provide all funds but provides half", async function () { + const bamm = this.BAMM + const price = getBigNumber(11, 27); + const halfTheLiquidationAmount = getBigNumber(7500000027, 0).div(2) + // bob bento deposit setup + const depositAmonut = halfTheLiquidationAmount + await this.b.connect(this.bob).approve(this.bentoBox.address, depositAmonut); + await this.bentoBox.connect(this.bob).deposit(this.b.address, this.bob.address, this.bob.address, depositAmonut, 0) + await setMasterContractApproval(this.bentoBox, this.bob, this.bob, this.bobPrivateKey, bamm.address, true) + await bamm.connect(this.bob).deposit(depositAmonut, true); + + + await this.pairHelper.run((cmd) => [ + cmd.as(this.bob).approveAsset(getBigNumber(310, 8)), + cmd.as(this.bob).depositAsset(getBigNumber(290, 8)), + cmd.approveCollateral(getBigNumber(100)), + cmd.depositCollateral(getBigNumber(100)), + cmd.borrow(sansBorrowFee(getBigNumber(75, 8))), + cmd.accrue(), + cmd.do(this.oracle.set, price.toString()), + cmd.updateExchangeRate(), + cmd.do(this.bentoBox.connect(this.bob).deposit, this.b.address, this.bob.address, this.bob.address, getBigNumber(20, 8), 0), + cmd.do(this.pairHelper.contract.connect(this.bob).removeAsset, this.bob.address, getBigNumber(50, 8)), + ]) + + await bamm.setParams(20, 0, 100) + + // deposit + const liquidationShare = await this.pairHelper.contract.userBorrowPart(this.alice.address) //getBigNumber(20, 18); + const liquidationAmount = halfTheLiquidationAmount + const nullAddr = "0x0000000000000000000000000000000000000000" + const rewardAddress = "0x0000000000000000000000000000000000000007" + + await this.b.connect(this.bob).approve(bamm.address, liquidationAmount); + await expect( + bamm.connect(this.bob) + .liquidateLikeTiran(liquidationAmount, [this.alice.address], [liquidationShare], rewardAddress, nullAddr, false) + ).to.be.revertedWith('liquidateLikeTiran: insufficent extraMim') + }) }) describe.only("Liquidate", function () { From 12d7f1e25b0439c24d53839a603ee097482f2673 Mon Sep 17 00:00:00 2001 From: shmuel Date: Wed, 3 Nov 2021 11:10:47 +0200 Subject: [PATCH 5/7] cleanUp --- test/BProtocol.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/BProtocol.js b/test/BProtocol.js index 9734da9..f0aa738 100644 --- a/test/BProtocol.js +++ b/test/BProtocol.js @@ -859,8 +859,6 @@ describe("KashiPair Basic", function () { }) - - /* it('test getSwapEthAmount', async () => { // --- SETUP --- From ce31403184248419608fea23682a698bdf41b79a Mon Sep 17 00:00:00 2001 From: shmuel Date: Thu, 4 Nov 2021 09:46:56 +0200 Subject: [PATCH 6/7] fail tests --- test/BProtocol.js | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/test/BProtocol.js b/test/BProtocol.js index f0aa738..60a805b 100644 --- a/test/BProtocol.js +++ b/test/BProtocol.js @@ -858,6 +858,90 @@ describe("KashiPair Basic", function () { expect(aliceMimBentoBalBefore.add(expectedMimDelta)).to.be.equal(aliceMimBentoBalAfter) }) + it.only("should fail when setParams is not called by owner", async function() { + const bamm = this.BAMM + await expect( + bamm.connect(this.bob).setParams(200, 100, 0) + ).to.be.revertedWith('Ownable: caller is not the owner') + }) + + it.only("should fail when setParams is with a fee above max fee", async function() { + const bamm = this.BAMM + await expect( + bamm.setParams(200, 101, 0) + ).to.be.revertedWith('setParams: fee is too big') + }) + + it.only("should fail when setParams is with a caller fee above max caller fee", async function() { + const bamm = this.BAMM + await expect( + bamm.setParams(200, 100, 101) + ).to.be.revertedWith('setParams: caller fee is too big') + }) + + it.only("should fail when setParams is with A param above max ", async function() { + const bamm = this.BAMM + await expect( + bamm.setParams(201, 100, 100) + ).to.be.revertedWith('setParams: A too big') + }) + + it.only("should fail when setParams is with A param below minimum ", async function() { + const bamm = this.BAMM + await expect( + bamm.setParams(19, 100, 100) + ).to.be.revertedWith('setParams: A too small') + }) + + it.only("should fail when setParams is with A param below minimum ", async function() { + const bamm = this.BAMM + await expect( + bamm.setParams(19, 100, 100) + ).to.be.revertedWith('setParams: A too small') + }) + + it.only("should fail to withdraw more than share", async function() { + const bamm = this.BAMM + const withdrawAmountShare = getBigNumber(1, 18); + // bob has 0 + expect(await bamm.balanceOf(this.bob.address)).to.be.equal(0) + // try to withdraw + await expect( + bamm.connect(this.bob).withdraw(withdrawAmountShare, false) + ).to.be.revertedWith('withdraw: insufficient balance') + }) + + it.only("swap should fail when swapper sets minimum gem to more than possible", async function () { + const bamm = this.BAMM + const mimAmonut = getBigNumber(600, 18) + const colAmount = "3979999999999999997" // almost 4e17 + const price = getBigNumber(105, 18) + const wad = getBigNumber(105, 17) + + // deposit + await this.b.connect(this.bob).approve(bamm.address, mimAmonut); + await bamm.connect(this.bob).deposit(mimAmonut, false); + + // transfer collateral + await this.a.connect(this.bob).approve(this.bentoBox.address, colAmount) + await this.bentoBox.connect(this.bob).deposit(this.a.address, this.bob.address, bamm.address, colAmount, 0) + //await this.a.connect(this.bob).transfer(bamm.address, getBigNumber(1, 18)) + await this.oracle.connect(this.alice).set(price.toString()) + await bamm.fetchPrice() + + // with fee + await bamm.setParams(200, 100, 0) + const expectedCol = await bamm.getSwapGemAmount(wad) + + // do the swap + await this.b.connect(this.bob).approve(bamm.address, wad); + const dest = "0x0000000000000000000000000000000000000007" + const minGem = expectedCol.mul(10) + await expect( + bamm.connect(this.bob).swap(wad, minGem, dest, false) + ).to.be.revertedWith("swap: low return") + }) + /* it('test getSwapEthAmount', async () => { From dd5cdcea68b9e693ebf11ed6a1a708c907c6096b Mon Sep 17 00:00:00 2001 From: shmuel Date: Thu, 4 Nov 2021 10:20:59 +0200 Subject: [PATCH 7/7] test price feed is down --- test/BProtocol.js | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/test/BProtocol.js b/test/BProtocol.js index 60a805b..9917d9a 100644 --- a/test/BProtocol.js +++ b/test/BProtocol.js @@ -858,49 +858,49 @@ describe("KashiPair Basic", function () { expect(aliceMimBentoBalBefore.add(expectedMimDelta)).to.be.equal(aliceMimBentoBalAfter) }) - it.only("should fail when setParams is not called by owner", async function() { + it("should fail when setParams is not called by owner", async function() { const bamm = this.BAMM await expect( bamm.connect(this.bob).setParams(200, 100, 0) ).to.be.revertedWith('Ownable: caller is not the owner') }) - it.only("should fail when setParams is with a fee above max fee", async function() { + it("should fail when setParams is with a fee above max fee", async function() { const bamm = this.BAMM await expect( bamm.setParams(200, 101, 0) ).to.be.revertedWith('setParams: fee is too big') }) - it.only("should fail when setParams is with a caller fee above max caller fee", async function() { + it("should fail when setParams is with a caller fee above max caller fee", async function() { const bamm = this.BAMM await expect( bamm.setParams(200, 100, 101) ).to.be.revertedWith('setParams: caller fee is too big') }) - it.only("should fail when setParams is with A param above max ", async function() { + it("should fail when setParams is with A param above max ", async function() { const bamm = this.BAMM await expect( bamm.setParams(201, 100, 100) ).to.be.revertedWith('setParams: A too big') }) - it.only("should fail when setParams is with A param below minimum ", async function() { + it("should fail when setParams is with A param below minimum ", async function() { const bamm = this.BAMM await expect( bamm.setParams(19, 100, 100) ).to.be.revertedWith('setParams: A too small') }) - it.only("should fail when setParams is with A param below minimum ", async function() { + it("should fail when setParams is with A param below minimum ", async function() { const bamm = this.BAMM await expect( bamm.setParams(19, 100, 100) ).to.be.revertedWith('setParams: A too small') }) - it.only("should fail to withdraw more than share", async function() { + it("should fail to withdraw more than share", async function() { const bamm = this.BAMM const withdrawAmountShare = getBigNumber(1, 18); // bob has 0 @@ -911,7 +911,7 @@ describe("KashiPair Basic", function () { ).to.be.revertedWith('withdraw: insufficient balance') }) - it.only("swap should fail when swapper sets minimum gem to more than possible", async function () { + it("swap should fail when swapper sets minimum gem to more than possible", async function () { const bamm = this.BAMM const mimAmonut = getBigNumber(600, 18) const colAmount = "3979999999999999997" // almost 4e17 @@ -942,6 +942,27 @@ describe("KashiPair Basic", function () { ).to.be.revertedWith("swap: low return") }) + it("when gem balance exist and price is 0 should fail with price feed is down", async function () { + const bamm = this.BAMM + const depositAmonut = getBigNumber(2, 18); + + // making sure price is zero + await this.pairHelper.run((cmd) => [ + cmd.do(this.oracle.set, getBigNumber(0, 18)), + cmd.updateExchangeRate() + ]) + // making sure gem balance is bigger than 0 + + await this.a.connect(this.bob).approve(this.bentoBox.address, depositAmonut) + await this.bentoBox.connect(this.bob).deposit(this.a.address, this.bob.address, bamm.address, depositAmonut, 0) + + //trying to deposit + await this.b.connect(this.bob).approve(bamm.address, depositAmonut); + await expect( + bamm.connect(this.bob).deposit(depositAmonut, false) + ).to.be.revertedWith("deposit: feed is down") + }) + /* it('test getSwapEthAmount', async () => {