Last active
May 10, 2023 14:54
-
-
Save bzpassersby/45e4de45f2216c3d00198db220dd94b2 to your computer and use it in GitHub Desktop.
a trader can maximally withdraw against temporary PnL and being liquidated instantly after with profits
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////note: a trader can maximally withdraw against temporary PnL and being liquidated instantly after with profits | |
////note: Two tests conditions below. The first test results in bad debts not covered. The second test trader maximally withdraw before and after liquidation with profits. | |
////note: This test is in the context of JOJO unit tet file- liquidation-test.ts-"check position" | |
////note: a trader can maximally withdraw against temporary PnL leaving bad debts | |
it("trader withdraw maximally against temporary PnL leaving bad debts", async () => { | |
////note: withdraw | |
await context.dealer | |
.connect(trader1) | |
.requestWithdraw(utils.parseEther("5000"), utils.parseEther("4010")); | |
await timeJump(100); | |
await context.dealer | |
.connect(trader1) | |
.executeWithdraw(trader1.address, false); | |
await checkCredit(context, trader1.address, "0", "990"); ////note: trader1 has 30 JUSD as secondary deposit. | |
// await checkCredit(context, trader2.address, "0", "0"); | |
await context.priceSourceList[0].setMarkPrice(utils.parseEther("33000")); | |
////note: open position and trade | |
await openPosition( | |
trader1, | |
trader2, | |
"1", | |
"30000", | |
context.perpList[0], | |
orderEnv | |
); | |
////note: trader1 is in good standing after trade with 0 collateral tokens | |
expect(await context.dealer.isSafe(trader2.address)).to.be.true; | |
expect(await context.dealer.isSafe(trader1.address)).to.be.true; | |
await checkCredit(context, trader1.address, "0", "990"); | |
await checkBalance(context.perpList[0], trader1.address, "1", "-30015"); | |
const risk = await context.dealer.getTraderRisk(trader1.address); | |
console.log(risk.netValue.toString()); | |
expect(risk.netValue.toString()).to.equal(utils.parseEther("3975")); | |
//log: 3975000000000000000000 (3975 USD) trader1 net value is 3975 USD | |
console.log(risk.maintenanceMargin.toString()); | |
expect(risk.maintenanceMargin.toString()).to.equal( | |
utils.parseEther("990") | |
); | |
//log: 990000000000000000000 (990 USD) trader1 maintenance margin is 990 USD | |
await context.dealer | |
.connect(trader1) | |
.requestWithdraw(utils.parseEther("2985"), utils.parseEther("0")); | |
await timeJump(100); | |
await context.dealer | |
.connect(trader1) | |
.executeWithdraw(trader1.address, false); | |
await checkCredit(context, trader1.address, "-2985", "990"); | |
const bal = await context.primaryAsset.balanceOf(trader1.address); | |
expect(bal.toString()).to.equal(utils.parseEther("1002985")); | |
await context.priceSourceList[0].setMarkPrice(utils.parseEther("32000")); | |
expect(await context.dealer.isSafe(trader1.address)).to.be.false; | |
await perp0 | |
.connect(liquidator) | |
.liquidate( | |
liquidator.address, | |
trader1.address, | |
utils.parseEther("1"), | |
utils.parseEther("-33000") | |
); | |
await checkBalance(perp0, liquidator.address, "1", "-31680"); //: liqtor: 32000-320=31680 , liqed: 31680-316.80= 31363.2 | |
await checkBalance(perp0, trader1.address, "0", "0"); | |
const credit = await context.dealer.getCreditOf(insurance); | |
console.log(credit.primaryCredit.toString()); | |
console.log(credit.secondaryCredit.toString()); | |
const credit1 = await context.dealer.getCreditOf(trader1.address); //: trader1 credit=-30015+31363.2= 1348.2, newReducedCredit=1348.2, primaryCredit=-2985+1348.2= -1636.8 | |
console.log(credit1.primaryCredit.toString()); | |
console.log(credit1.secondaryCredit.toString()); | |
expect(await context.dealer.isSafe(trader1.address)).to.be.true; | |
await checkCredit(context, insurance, "-1320", "990"); //: -1636.8+316.80= -1320 | |
await checkCredit(context, trader1.address, "0", "0"); | |
console.log("insurance loss:", -1320 + 990); | |
}); | |
////note: a trader can maximally withdraw against temporary PnL with decent profits | |
it("trader withdraw maximally against temporary PnL liquidated with Profits", async () => { | |
////note: test preparation to make sure trader1 starts only with some secondary asset deposits | |
await context.dealer | |
.connect(trader1) | |
.requestWithdraw(utils.parseEther("5000"), utils.parseEther("4010")); | |
await timeJump(100); | |
await context.dealer | |
.connect(trader1) | |
.executeWithdraw(trader1.address, false); | |
await checkCredit(context, trader1.address, "0", "990"); ////note: trader1 has 30 JUSD as secondary deposit. | |
await context.priceSourceList[0].setMarkPrice(utils.parseEther("33000")); | |
////note: open position and trade | |
await openPosition( | |
trader1, | |
trader2, | |
"1", | |
"30000", | |
context.perpList[0], | |
orderEnv | |
); | |
////note: trader1 is in good standing after trade with 0 collateral tokens | |
expect(await context.dealer.isSafe(trader2.address)).to.be.true; | |
expect(await context.dealer.isSafe(trader1.address)).to.be.true; | |
await checkCredit(context, trader1.address, "0", "990"); | |
await checkBalance(context.perpList[0], trader1.address, "1", "-30015"); | |
const risk = await context.dealer.getTraderRisk(trader1.address); | |
console.log(risk.netValue.toString()); | |
expect(risk.netValue.toString()).to.equal(utils.parseEther("3975")); | |
//log: 3975000000000000000000 (3975 USD) trader1 net value is 3975 USD | |
console.log(risk.maintenanceMargin.toString()); | |
expect(risk.maintenanceMargin.toString()).to.equal( | |
utils.parseEther("990") | |
); | |
//log: 990000000000000000000 (990 USD) trader1 maintenance margin is 990 USD | |
await context.dealer | |
.connect(trader1) | |
.requestWithdraw(utils.parseEther("2985"), utils.parseEther("0")); | |
await timeJump(100); | |
await context.dealer | |
.connect(trader1) | |
.executeWithdraw(trader1.address, false); | |
await checkCredit(context, trader1.address, "-2985", "990"); | |
const bal = await context.primaryAsset.balanceOf(trader1.address); | |
expect(bal.toString()).to.equal(utils.parseEther("1002985")); | |
await context.priceSourceList[0].setMarkPrice(utils.parseEther("32999")); | |
expect(await context.dealer.isSafe(trader1.address)).to.be.false; | |
await perp0 | |
.connect(liquidator) | |
.liquidate( | |
liquidator.address, | |
trader1.address, | |
utils.parseEther("1"), | |
utils.parseEther("-33000") | |
); | |
await checkBalance(perp0, liquidator.address, "1", "-32669.01"); //: liqtor: 32999-329.99= 32669.01, liqed: 32669.01-326.69= 32342.32 | |
await checkBalance(perp0, trader1.address, "0", "0"); | |
const credit = await context.dealer.getCreditOf(insurance); | |
console.log(credit.primaryCredit.toString()); | |
console.log(credit.secondaryCredit.toString()); | |
const credit1 = await context.dealer.getCreditOf(trader1.address); //: trader1 credit=-30015+32342.32= 2327.32, newReducedCredit=2327.32, primaryCredit=-2985+2327.32= -656.68 | |
console.log(credit1.primaryCredit.toString()); | |
console.log(credit1.secondaryCredit.toString()); | |
expect(await context.dealer.isSafe(trader1.address)).to.be.true; | |
//trader can still withdraw secondaryAsset after liquidation: 990-657.6801= 332.3199 | |
await context.dealer | |
.connect(trader1) | |
.requestWithdraw(utils.parseEther("0"), utils.parseEther("332.3199")); | |
await timeJump(100); | |
await context.dealer | |
.connect(trader1) | |
.executeWithdraw(trader1.address, false); | |
await checkCredit(context, trader1.address, "-657.6801", "657.6801"); | |
console.log("trader1 profit:", 2985 - 657.6801); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment