Skip to content

Instantly share code, notes, and snippets.

@bzpassersby
Last active May 10, 2023 14:54
Show Gist options
  • Save bzpassersby/45e4de45f2216c3d00198db220dd94b2 to your computer and use it in GitHub Desktop.
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
////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