Skip to content

Commit

Permalink
sdk: add calculateBaseAssetAmountToCoverMarginShortage (#1409)
Browse files Browse the repository at this point in the history
* sdk: add calculateBaseAssetAmountToCoverMarginShortage

* add calculateMaxPctToLiquidate

* prettify
  • Loading branch information
crispheaney authored Jan 4, 2025
1 parent dd9b8d7 commit 1d8bfcb
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
3 changes: 3 additions & 0 deletions sdk/src/constants/numericConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ export const MARGIN_PRECISION = TEN_THOUSAND;
export const BID_ASK_SPREAD_PRECISION = new BN(1000000); // 10^6
export const LIQUIDATION_PCT_PRECISION = TEN_THOUSAND;
export const FUNDING_RATE_OFFSET_DENOMINATOR = new BN(5000);
export const PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO = PRICE_PRECISION.mul(
AMM_TO_QUOTE_PRECISION_RATIO
);

export const FIVE_MINUTE = new BN(60 * 5);
export const ONE_HOUR = new BN(60 * 60);
Expand Down
1 change: 1 addition & 0 deletions sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export * from './math/amm';
export * from './math/trade';
export * from './math/orders';
export * from './math/repeg';
export * from './math/liquidation';
export * from './math/margin';
export * from './math/insurance';
export * from './math/superStake';
Expand Down
79 changes: 79 additions & 0 deletions sdk/src/math/liquidation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { BN } from '@coral-xyz/anchor';
import {
PRICE_PRECISION,
LIQUIDATION_FEE_PRECISION,
MARGIN_PRECISION,
PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO,
QUOTE_PRECISION,
LIQUIDATION_PCT_PRECISION,
} from '../constants/numericConstants';

export function calculateBaseAssetAmountToCoverMarginShortage(
marginShortage: BN,
marginRatio: number,
liquidationFee: number,
ifLiquidationFee: number,
oraclePrice: BN,
quoteOraclePrice: BN
): BN | undefined {
const marginRatioBN = new BN(marginRatio)
.mul(LIQUIDATION_FEE_PRECISION)
.div(MARGIN_PRECISION);
const liquidationFeeBN = new BN(liquidationFee);

if (oraclePrice.eq(new BN(0)) || marginRatioBN.lte(liquidationFeeBN)) {
// undefined is max
return undefined;
}

return marginShortage.mul(PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO).div(
oraclePrice
.mul(quoteOraclePrice)
.div(PRICE_PRECISION)
.mul(marginRatioBN.sub(liquidationFeeBN))
.div(LIQUIDATION_FEE_PRECISION)
.sub(
oraclePrice.mul(new BN(ifLiquidationFee)).div(LIQUIDATION_FEE_PRECISION)
)
);
}

export function calculateMaxPctToLiquidate(
userLastActiveSlot: BN,
userLiquidationMarginFreed: BN,
marginShortage: BN,
slot: BN,
initialPctToLiquidate: BN,
liquidationDuration: BN
): BN {
// if margin shortage is tiny, accelerate liquidation
if (marginShortage.lt(new BN(50).mul(QUOTE_PRECISION))) {
return LIQUIDATION_PCT_PRECISION;
}

let slotsElapsed;
if (userLiquidationMarginFreed.gt(new BN(0))) {
slotsElapsed = BN.max(slot.sub(userLastActiveSlot), new BN(0));
} else {
slotsElapsed = new BN(0);
}

const pctFreeable = BN.min(
slotsElapsed
.mul(LIQUIDATION_PCT_PRECISION)
.div(liquidationDuration) // ~ 1 minute if per slot is 400ms
.add(initialPctToLiquidate),
LIQUIDATION_PCT_PRECISION
);

const totalMarginShortage = marginShortage.add(userLiquidationMarginFreed);
const maxMarginFreed = totalMarginShortage
.mul(pctFreeable)
.div(LIQUIDATION_PCT_PRECISION);
const marginFreeable = BN.max(
maxMarginFreed.sub(userLiquidationMarginFreed),
new BN(0)
);

return marginFreeable.mul(LIQUIDATION_PCT_PRECISION).div(marginShortage);
}

0 comments on commit 1d8bfcb

Please sign in to comment.