Skip to content

Commit

Permalink
Remove max insurance fund before deleveraging (#614)
Browse files Browse the repository at this point in the history
  • Loading branch information
jayy04 authored Oct 13, 2023
1 parent 3d4a03c commit 5406cda
Show file tree
Hide file tree
Showing 16 changed files with 91 additions and 294 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import * as _m0 from "protobufjs/minimal";
import { Long, DeepPartial } from "../../helpers";
import { DeepPartial, Long } from "../../helpers";
/** LiquidationsConfig stores all configurable fields related to liquidations. */

export interface LiquidationsConfig {
/**
* The maximum number of quote quantums (inclusive) that the insurance fund
* can have for deleverages to be enabled. This is typically some non-zero
* value since it is difficult to fully-drain the insurance fund (to
* zero without rounding error).
*/
maxInsuranceFundQuantumsForDeleveraging: Long;
/**
* The maximum liquidation fee (in parts-per-million). This fee goes
* 100% to the insurance fund.
*/

maxLiquidationFeePpm: number;
/**
* Limits around how much of a single position can be liquidated
Expand All @@ -38,18 +30,10 @@ export interface LiquidationsConfig {
/** LiquidationsConfig stores all configurable fields related to liquidations. */

export interface LiquidationsConfigSDKType {
/**
* The maximum number of quote quantums (inclusive) that the insurance fund
* can have for deleverages to be enabled. This is typically some non-zero
* value since it is difficult to fully-drain the insurance fund (to
* zero without rounding error).
*/
max_insurance_fund_quantums_for_deleveraging: Long;
/**
* The maximum liquidation fee (in parts-per-million). This fee goes
* 100% to the insurance fund.
*/

max_liquidation_fee_ppm: number;
/**
* Limits around how much of a single position can be liquidated
Expand Down Expand Up @@ -179,7 +163,6 @@ export interface FillablePriceConfigSDKType {

function createBaseLiquidationsConfig(): LiquidationsConfig {
return {
maxInsuranceFundQuantumsForDeleveraging: Long.UZERO,
maxLiquidationFeePpm: 0,
positionBlockLimits: undefined,
subaccountBlockLimits: undefined,
Expand All @@ -189,24 +172,20 @@ function createBaseLiquidationsConfig(): LiquidationsConfig {

export const LiquidationsConfig = {
encode(message: LiquidationsConfig, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
if (!message.maxInsuranceFundQuantumsForDeleveraging.isZero()) {
writer.uint32(8).uint64(message.maxInsuranceFundQuantumsForDeleveraging);
}

if (message.maxLiquidationFeePpm !== 0) {
writer.uint32(16).uint32(message.maxLiquidationFeePpm);
writer.uint32(8).uint32(message.maxLiquidationFeePpm);
}

if (message.positionBlockLimits !== undefined) {
PositionBlockLimits.encode(message.positionBlockLimits, writer.uint32(26).fork()).ldelim();
PositionBlockLimits.encode(message.positionBlockLimits, writer.uint32(18).fork()).ldelim();
}

if (message.subaccountBlockLimits !== undefined) {
SubaccountBlockLimits.encode(message.subaccountBlockLimits, writer.uint32(34).fork()).ldelim();
SubaccountBlockLimits.encode(message.subaccountBlockLimits, writer.uint32(26).fork()).ldelim();
}

if (message.fillablePriceConfig !== undefined) {
FillablePriceConfig.encode(message.fillablePriceConfig, writer.uint32(42).fork()).ldelim();
FillablePriceConfig.encode(message.fillablePriceConfig, writer.uint32(34).fork()).ldelim();
}

return writer;
Expand All @@ -222,22 +201,18 @@ export const LiquidationsConfig = {

switch (tag >>> 3) {
case 1:
message.maxInsuranceFundQuantumsForDeleveraging = (reader.uint64() as Long);
break;

case 2:
message.maxLiquidationFeePpm = reader.uint32();
break;

case 3:
case 2:
message.positionBlockLimits = PositionBlockLimits.decode(reader, reader.uint32());
break;

case 4:
case 3:
message.subaccountBlockLimits = SubaccountBlockLimits.decode(reader, reader.uint32());
break;

case 5:
case 4:
message.fillablePriceConfig = FillablePriceConfig.decode(reader, reader.uint32());
break;

Expand All @@ -252,7 +227,6 @@ export const LiquidationsConfig = {

fromPartial(object: DeepPartial<LiquidationsConfig>): LiquidationsConfig {
const message = createBaseLiquidationsConfig();
message.maxInsuranceFundQuantumsForDeleveraging = object.maxInsuranceFundQuantumsForDeleveraging !== undefined && object.maxInsuranceFundQuantumsForDeleveraging !== null ? Long.fromValue(object.maxInsuranceFundQuantumsForDeleveraging) : Long.UZERO;
message.maxLiquidationFeePpm = object.maxLiquidationFeePpm ?? 0;
message.positionBlockLimits = object.positionBlockLimits !== undefined && object.positionBlockLimits !== null ? PositionBlockLimits.fromPartial(object.positionBlockLimits) : undefined;
message.subaccountBlockLimits = object.subaccountBlockLimits !== undefined && object.subaccountBlockLimits !== null ? SubaccountBlockLimits.fromPartial(object.subaccountBlockLimits) : undefined;
Expand Down
14 changes: 4 additions & 10 deletions proto/dydxprotocol/clob/liquidations_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,23 @@ option go_package = "github.com/dydxprotocol/v4-chain/protocol/x/clob/types";

// LiquidationsConfig stores all configurable fields related to liquidations.
message LiquidationsConfig {
// The maximum number of quote quantums (inclusive) that the insurance fund
// can have for deleverages to be enabled. This is typically some non-zero
// value since it is difficult to fully-drain the insurance fund (to
// zero without rounding error).
uint64 max_insurance_fund_quantums_for_deleveraging = 1;

// The maximum liquidation fee (in parts-per-million). This fee goes
// 100% to the insurance fund.
uint32 max_liquidation_fee_ppm = 2;
uint32 max_liquidation_fee_ppm = 1;

// Limits around how much of a single position can be liquidated
// within a single block.
PositionBlockLimits position_block_limits = 3
PositionBlockLimits position_block_limits = 2
[ (gogoproto.nullable) = false ];

// Limits around how many quote quantums from a single subaccount can
// be liquidated within a single block.
SubaccountBlockLimits subaccount_block_limits = 4
SubaccountBlockLimits subaccount_block_limits = 3
[ (gogoproto.nullable) = false ];

// Config about how the fillable-price spread from the oracle price
// increases based on the adjusted bankruptcy rating of the subaccount.
FillablePriceConfig fillable_price_config = 5
FillablePriceConfig fillable_price_config = 4
[ (gogoproto.nullable) = false ];
}

Expand Down
1 change: 0 additions & 1 deletion protocol/app/testdata/default_genesis_state.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
"clob": {
"clob_pairs": [],
"liquidations_config": {
"max_insurance_fund_quantums_for_deleveraging": "0",
"max_liquidation_fee_ppm": 5000,
"position_block_limits": {
"min_position_notional_liquidated": "1000",
Expand Down
1 change: 0 additions & 1 deletion protocol/scripts/genesis/sample_pregenesis.json
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,6 @@
"bankruptcy_adjustment_ppm": 1000000,
"spread_to_maintenance_margin_ratio_ppm": 1500000
},
"max_insurance_fund_quantums_for_deleveraging": 100000000000,
"max_liquidation_fee_ppm": 15000,
"position_block_limits": {
"max_position_portion_liquidated_ppm": 100000,
Expand Down
1 change: 0 additions & 1 deletion protocol/testing/genesis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1316,7 +1316,6 @@ function edit_genesis() {
dasel put -t int -f "$GENESIS" '.app_state.clob.clob_pairs.[32].quantum_conversion_exponent' -v '-9'

# Liquidations
dasel put -t int -f "$GENESIS" '.app_state.clob.liquidations_config.max_insurance_fund_quantums_for_deleveraging' -v '100000000000' # 100_000 USDC
dasel put -t int -f "$GENESIS" '.app_state.clob.liquidations_config.max_liquidation_fee_ppm' -v '15000' # 1.5%
dasel put -t int -f "$GENESIS" '.app_state.clob.liquidations_config.position_block_limits.min_position_notional_liquidated' -v '1000'
dasel put -t int -f "$GENESIS" '.app_state.clob.liquidations_config.position_block_limits.max_position_portion_liquidated_ppm' -v '100000' # 10%
Expand Down
1 change: 0 additions & 1 deletion protocol/testutil/constants/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,6 @@ const GenesisState = `{
"bankruptcy_adjustment_ppm": 1000000,
"spread_to_maintenance_margin_ratio_ppm": 100000
},
"max_insurance_fund_quantums_for_deleveraging": "0",
"max_liquidation_fee_ppm": 5000,
"position_block_limits": {
"max_position_portion_liquidated_ppm": 1000000,
Expand Down
7 changes: 0 additions & 7 deletions protocol/testutil/constants/liquidation_configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,4 @@ var (
MaxQuantumsInsuranceLost: 10_000_000_000, // $10,000
},
}
LiquidationsConfig_10bMaxInsuranceFundQuantumsForDeleveraging = clobtypes.LiquidationsConfig{
MaxInsuranceFundQuantumsForDeleveraging: 10_000_000_000, // $10,000
MaxLiquidationFeePpm: 5_000,
FillablePriceConfig: FillablePriceConfig_Default,
PositionBlockLimits: PositionBlockLimits_No_Limit,
SubaccountBlockLimits: SubaccountBlockLimits_No_Limit,
}
)
6 changes: 0 additions & 6 deletions protocol/testutil/sim_helpers/genesis_parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,6 @@ var (
Valid: math.MaxUint32,
}

MaxInsuranceFundQuantumsForDeleveragingBuckets = []int{
0, // min
1_000_000,
100_000_000,
1_000_000_000_000, // $1,000,000
}
MinPositionNotionalBuckets = []int{
1, // min
1_000_000,
Expand Down
14 changes: 1 addition & 13 deletions protocol/x/clob/keeper/deleveraging.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,23 +127,12 @@ func (k Keeper) GetInsuranceFundBalance(

// CanDeleverageSubaccount returns true if a subaccount can be deleveraged.
// Specifically, this function returns true if both of the following are true:
// - The insurance fund balance is less-than-or-equal to `MaxInsuranceFundQuantumsForDeleveraging`.
// - The subaccount's total net collateral is negative.
// This function returns an error if `GetNetCollateralAndMarginRequirements` returns an error.
func (k Keeper) CanDeleverageSubaccount(
ctx sdk.Context,
subaccountId satypes.SubaccountId,
) (bool, error) {
currentInsuranceFundBalance := k.GetInsuranceFundBalance(ctx)
liquidationConfig := k.GetLiquidationsConfig(ctx)
bigMaxInsuranceFundForDeleveraging := new(big.Int).SetUint64(liquidationConfig.MaxInsuranceFundQuantumsForDeleveraging)

// Deleveraging cannot be performed if the current insurance fund balance is greater than the
// max insurance fund for deleveraging,
if currentInsuranceFundBalance.Cmp(bigMaxInsuranceFundForDeleveraging) > 0 {
return false, nil
}

bigNetCollateral,
_,
_,
Expand All @@ -160,8 +149,7 @@ func (k Keeper) CanDeleverageSubaccount(
return false, nil
}

// The insurance fund balance is less-than-or-equal to `MaxInsuranceFundQuantumsForDeleveraging`
// and the subaccount's total net collateral is negative, so deleveraging can be performed.
// The subaccount's total net collateral is negative, so deleveraging can be performed.
return true, nil
}

Expand Down
59 changes: 6 additions & 53 deletions protocol/x/clob/keeper/deleveraging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,8 @@ func TestCanDeleverageSubaccount(t *testing.T) {
// Expectations.
expectedCanDeleverageSubaccount bool
}{
`Cannot deleverage when subaccount has positive TNC, insurance fund balance is greater than
MaxInsuranceFundQuantumsForDeleveraging`: {
liquidationConfig: constants.LiquidationsConfig_10bMaxInsuranceFundQuantumsForDeleveraging,
`Cannot deleverage when subaccount has positive TNC`: {
liquidationConfig: constants.LiquidationsConfig_No_Limit,
insuranceFundBalance: big.NewInt(10_000_000_001), // $10,000.000001
subaccount: constants.Carl_Num0_1BTC_Short_54999USD,
marketIdToOraclePriceOverride: map[uint32]uint64{
Expand All @@ -231,9 +230,8 @@ func TestCanDeleverageSubaccount(t *testing.T) {

expectedCanDeleverageSubaccount: false,
},
`Cannot deleverage when subaccount has zero TNC, insurance fund balance is greater than
MaxInsuranceFundQuantumsForDeleveraging`: {
liquidationConfig: constants.LiquidationsConfig_10bMaxInsuranceFundQuantumsForDeleveraging,
`Cannot deleverage when subaccount has zero TNC`: {
liquidationConfig: constants.LiquidationsConfig_No_Limit,
insuranceFundBalance: big.NewInt(10_000_000_001), // $10,000.000001
subaccount: constants.Carl_Num0_1BTC_Short_54999USD,
marketIdToOraclePriceOverride: map[uint32]uint64{
Expand All @@ -242,59 +240,14 @@ func TestCanDeleverageSubaccount(t *testing.T) {

expectedCanDeleverageSubaccount: false,
},
`Cannot deleverage when subaccount has negative TNC, insurance fund balance is greater than
MaxInsuranceFundQuantumsForDeleveraging`: {
liquidationConfig: constants.LiquidationsConfig_10bMaxInsuranceFundQuantumsForDeleveraging,
insuranceFundBalance: big.NewInt(10_000_000_001), // $10,000.000001
subaccount: constants.Carl_Num0_1BTC_Short_54999USD,
marketIdToOraclePriceOverride: map[uint32]uint64{
constants.BtcUsd.MarketId: 5_500_000_000, // $55,000 / BTC
},

expectedCanDeleverageSubaccount: false,
},
`Cannot deleverage when subaccount has zero TNC, insurance fund balance is equal to
MaxInsuranceFundQuantumsForDeleveraging`: {
liquidationConfig: constants.LiquidationsConfig_10bMaxInsuranceFundQuantumsForDeleveraging,
insuranceFundBalance: big.NewInt(10_000_000_000), // $10,000
subaccount: constants.Carl_Num0_1BTC_Short_54999USD,
marketIdToOraclePriceOverride: map[uint32]uint64{
constants.BtcUsd.MarketId: 5_499_000_000, // $54,999 / BTC
},

expectedCanDeleverageSubaccount: false,
},
`Cannot deleverage when subaccount has zero TNC, insurance fund balance is less than
MaxInsuranceFundQuantumsForDeleveraging`: {
liquidationConfig: constants.LiquidationsConfig_10bMaxInsuranceFundQuantumsForDeleveraging,
insuranceFundBalance: big.NewInt(0), // $0
subaccount: constants.Carl_Num0_1BTC_Short_54999USD,
marketIdToOraclePriceOverride: map[uint32]uint64{
constants.BtcUsd.MarketId: 5_499_000_000, // $54,999 / BTC
},

expectedCanDeleverageSubaccount: false,
},
`Can deleverage when subaccount has negative TNC, insurance fund balance is equal to
MaxInsuranceFundQuantumsForDeleveraging`: {
liquidationConfig: constants.LiquidationsConfig_10bMaxInsuranceFundQuantumsForDeleveraging,
`Can deleverage when subaccount has negative TNC`: {
liquidationConfig: constants.LiquidationsConfig_No_Limit,
insuranceFundBalance: big.NewInt(10_000_000_000), // $10,000
subaccount: constants.Carl_Num0_1BTC_Short_54999USD,
marketIdToOraclePriceOverride: map[uint32]uint64{
constants.BtcUsd.MarketId: 5_500_000_000, // $55,000 / BTC
},

expectedCanDeleverageSubaccount: true,
},
`Can deleverage when subaccount has negative TNC, insurance fund balance is less than
MaxInsuranceFundQuantumsForDeleveraging`: {
liquidationConfig: constants.LiquidationsConfig_10bMaxInsuranceFundQuantumsForDeleveraging,
insuranceFundBalance: big.NewInt(0), // $0
subaccount: constants.Carl_Num0_1BTC_Short_54999USD,
marketIdToOraclePriceOverride: map[uint32]uint64{
constants.BtcUsd.MarketId: 5_500_000_000, // $55,000 / BTC
},

expectedCanDeleverageSubaccount: true,
},
}
Expand Down
Loading

0 comments on commit 5406cda

Please sign in to comment.