Skip to content

Commit

Permalink
program: safer market initialization (#413)
Browse files Browse the repository at this point in the history
* bigz/market-initializer-improve

* fix tests/multipleMakerOrders.ts

* fix tests

* fix tests/admin.ts

* init delete_initialized_perp_market

* fix test/ idl

* fix red err tests lines

* update admin.rs for deletecontext

* update error code

* update validate for state.number_of_markets

* actually delete perp account

* try fix referrer test

* update idl

* fix tests

* CHANGELOG

---------

Co-authored-by: Chris Heaney <[email protected]>
  • Loading branch information
0xbigz and crispheaney committed Apr 6, 2023
1 parent 50781b5 commit 51c8be0
Show file tree
Hide file tree
Showing 48 changed files with 201 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Features

- program: ability to delete a market that was just initialized ([#413](https://github.com/drift-labs/protocol-v2/pull/413))
- program: revenue pool wont settle to IF if utilization unhealthy ([#402](https://github.com/drift-labs/protocol-v2/pull/402))

### Fixes

- program: add ctx.accounts.insurance_fund_vault.reload()? after vault updates ([#402](https://github.com/drift-labs/protocol-v2/pull/402))

### Breaking

## [2.23.0] - 2023-04-03
Expand Down
2 changes: 2 additions & 0 deletions programs/drift/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,8 @@ pub enum ErrorCode {
UserNotInactive,
#[msg("RevertFill")]
RevertFill,
#[msg("Invalid MarketAccount for Deletion")]
InvalidMarketAccountforDeletion,
}

#[macro_export]
Expand Down
69 changes: 67 additions & 2 deletions programs/drift/src/instructions/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use crate::validation::margin::{validate_margin, validate_margin_weights};
use crate::validation::perp_market::validate_perp_market;
use crate::validation::spot_market::validate_borrow_rate;
use crate::{controller, QUOTE_PRECISION_I64};
use crate::{math, safe_increment};
use crate::{math, safe_decrement, safe_increment};

pub fn handle_initialize(ctx: Context<Initialize>) -> Result<()> {
let (drift_signer, drift_signer_nonce) =
Expand Down Expand Up @@ -443,6 +443,7 @@ pub fn handle_update_serum_vault(ctx: Context<UpdateSerumVault>) -> Result<()> {

pub fn handle_initialize_perp_market(
ctx: Context<InitializePerpMarket>,
market_index: u16,
amm_base_asset_reserve: u128,
amm_quote_asset_reserve: u128,
amm_periodicity: i64,
Expand Down Expand Up @@ -551,7 +552,14 @@ pub fn handle_initialize_perp_market(
)?;

let state = &mut ctx.accounts.state;
let market_index = state.number_of_markets;
validate!(
market_index == state.number_of_markets,
ErrorCode::MarketIndexAlreadyInitialized,
"market_index={} != state.number_of_markets={}",
market_index,
state.number_of_markets
)?;

**perp_market = PerpMarket {
contract_type: ContractType::Perpetual,
contract_tier: ContractTier::Speculative, // default
Expand Down Expand Up @@ -679,6 +687,46 @@ pub fn handle_initialize_perp_market(
Ok(())
}

pub fn handle_delete_initialized_perp_market(
ctx: Context<DeleteInitializedPerpMarket>,
market_index: u16,
) -> Result<()> {
let perp_market = &mut ctx.accounts.perp_market.load_init()?;
let state = &mut ctx.accounts.state;

// to preserve all protocol invariants, can only remove the last market if it hasn't been "activated"

validate!(
state.number_of_markets - 1 == market_index,
ErrorCode::InvalidMarketAccountforDeletion,
"state.number_of_markets={} != market_index={}",
state.number_of_markets,
market_index
)?;
validate!(
perp_market.status == MarketStatus::Initialized,
ErrorCode::InvalidMarketAccountforDeletion,
"perp_market.status != Initialized",
)?;
validate!(
perp_market.number_of_users == 0,
ErrorCode::InvalidMarketAccountforDeletion,
"perp_market.number_of_users={} != 0",
perp_market.number_of_users,
)?;
validate!(
perp_market.market_index == market_index,
ErrorCode::InvalidMarketAccountforDeletion,
"market_index={} != perp_market.market_index={}",
market_index,
perp_market.market_index
)?;

safe_decrement!(state.number_of_markets, 1);

Ok(())
}

#[access_control(
spot_market_valid(&ctx.accounts.spot_market)
)]
Expand Down Expand Up @@ -2247,6 +2295,23 @@ pub struct InitializePerpMarket<'info> {
pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct DeleteInitializedPerpMarket<'info> {
#[account(mut)]
pub admin: Signer<'info>,
#[account(
mut,
has_one = admin
)]
pub state: Box<Account<'info, State>>,
#[account(mut, close = admin)]
pub perp_market: AccountLoader<'info, PerpMarket>,
/// CHECK: checked in `initialize_perp_market`
pub oracle: AccountInfo<'info>,
pub rent: Sysvar<'info, Rent>,
pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct AdminUpdatePerpMarket<'info> {
pub admin: Signer<'info>,
Expand Down
9 changes: 9 additions & 0 deletions programs/drift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ pub mod drift {

pub fn initialize_perp_market(
ctx: Context<InitializePerpMarket>,
market_index: u16,
amm_base_asset_reserve: u128,
amm_quote_asset_reserve: u128,
amm_periodicity: i64,
Expand All @@ -487,6 +488,7 @@ pub mod drift {
) -> Result<()> {
handle_initialize_perp_market(
ctx,
market_index,
amm_base_asset_reserve,
amm_quote_asset_reserve,
amm_periodicity,
Expand All @@ -500,6 +502,13 @@ pub mod drift {
)
}

pub fn delete_initialized_perp_market(
ctx: Context<DeleteInitializedPerpMarket>,
market_index: u16,
) -> Result<()> {
handle_delete_initialized_perp_market(ctx, market_index)
}

pub fn move_amm_price(
ctx: Context<AdminUpdatePerpMarket>,
base_asset_reserve: u128,
Expand Down
2 changes: 2 additions & 0 deletions sdk/src/adminClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ export class AdminClient extends DriftClient {
}

public async initializePerpMarket(
marketIndex: number,
priceOracle: PublicKey,
baseAssetReserve: BN,
quoteAssetReserve: BN,
Expand All @@ -203,6 +204,7 @@ export class AdminClient extends DriftClient {
const nameBuffer = encodeName(name);
const initializeMarketTx =
await this.program.transaction.initializePerpMarket(
marketIndex,
baseAssetReserve,
quoteAssetReserve,
periodicity,
Expand Down
50 changes: 50 additions & 0 deletions sdk/src/idl/drift.json
Original file line number Diff line number Diff line change
Expand Up @@ -2283,6 +2283,10 @@
}
],
"args": [
{
"name": "marketIndex",
"type": "u16"
},
{
"name": "ammBaseAssetReserve",
"type": "u128"
Expand Down Expand Up @@ -2332,6 +2336,47 @@
}
]
},
{
"name": "deleteInitializedPerpMarket",
"accounts": [
{
"name": "admin",
"isMut": true,
"isSigner": true
},
{
"name": "state",
"isMut": true,
"isSigner": false
},
{
"name": "perpMarket",
"isMut": true,
"isSigner": false
},
{
"name": "oracle",
"isMut": false,
"isSigner": false
},
{
"name": "rent",
"isMut": false,
"isSigner": false
},
{
"name": "systemProgram",
"isMut": false,
"isSigner": false
}
],
"args": [
{
"name": "marketIndex",
"type": "u16"
}
]
},
{
"name": "moveAmmPrice",
"accounts": [
Expand Down Expand Up @@ -8826,6 +8871,11 @@
"code": 6239,
"name": "RevertFill",
"msg": "RevertFill"
},
{
"code": 6240,
"name": "InvalidMarketAccountforDeletion",
"msg": "Invalid MarketAccount for Deletion"
}
]
}
1 change: 1 addition & 0 deletions tests/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ describe('admin', () => {
const periodicity = new BN(60 * 60); // 1 HOUR

await driftClient.initializePerpMarket(
0,
solUsd,
new BN(1000),
new BN(1000),
Expand Down
1 change: 1 addition & 0 deletions tests/assetTier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ describe('asset tiers', () => {

const periodicity = new BN(60 * 60); // 1 HOUR
await driftClient.initializePerpMarket(
0,
solOracle,
AMM_RESERVE_PRECISION,
AMM_RESERVE_PRECISION,
Expand Down
1 change: 1 addition & 0 deletions tests/cancelAllOrders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ describe('cancel all orders', () => {
const periodicity = new BN(0);

await driftClient.initializePerpMarket(
0,
oracle,
ammInitialBaseAssetReserve,
ammInitialQuoteAssetReserve,
Expand Down
12 changes: 11 additions & 1 deletion tests/cappedSymFunding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
PRICE_PRECISION,
FUNDING_RATE_BUFFER_PRECISION,
PEG_PRECISION,
TestClient,
User,
PositionDirection,
QUOTE_PRECISION,
Expand Down Expand Up @@ -183,6 +182,7 @@ async function updateFundingRateHelper(
}

async function cappedSymFundingScenario(
rollingMarketNum: number,
driftClient: TestClient,
userAccount: User,
driftClient2: TestClient,
Expand All @@ -197,6 +197,7 @@ async function cappedSymFundingScenario(
const periodicity = new BN(0);

await driftClient.initializePerpMarket(
rollingMarketNum,
priceFeedAddress,
kSqrt,
kSqrt,
Expand Down Expand Up @@ -546,6 +547,7 @@ describe('capped funding', () => {
totalFee,
cumulativeFee,
] = await cappedSymFundingScenario(
rollingMarketNum - 1,
driftClient,
userAccount,
driftClient2,
Expand Down Expand Up @@ -604,6 +606,7 @@ describe('capped funding', () => {
totalFee,
cumulativeFee,
] = await cappedSymFundingScenario(
rollingMarketNum - 1,
driftClient,
userAccount,
driftClient2,
Expand Down Expand Up @@ -663,6 +666,7 @@ describe('capped funding', () => {
totalFee,
cumulativeFee,
] = await cappedSymFundingScenario(
rollingMarketNum - 1,
driftClient,
userAccount,
driftClient2,
Expand Down Expand Up @@ -720,6 +724,7 @@ describe('capped funding', () => {
totalFee,
cumulativeFee,
] = await cappedSymFundingScenario(
rollingMarketNum - 1,
driftClient,
userAccount,
driftClient2,
Expand Down Expand Up @@ -781,6 +786,7 @@ describe('capped funding', () => {
totalFee,
cumulativeFee,
] = await cappedSymFundingScenario(
rollingMarketNum - 1,
driftClient,
userAccount,
driftClient2,
Expand Down Expand Up @@ -880,6 +886,7 @@ describe('capped funding', () => {
totalFee,
cumulativeFee,
] = await cappedSymFundingScenario(
rollingMarketNum - 1,
driftClient,
userAccount,
driftClient2,
Expand Down Expand Up @@ -975,6 +982,7 @@ describe('capped funding', () => {
totalFee,
cumulativeFee,
] = await cappedSymFundingScenario(
rollingMarketNum - 1,
driftClient,
userAccount,
driftClient2,
Expand Down Expand Up @@ -1036,6 +1044,7 @@ describe('capped funding', () => {
totalFee,
cumulativeFee,
] = await cappedSymFundingScenario(
rollingMarketNum - 1,
driftClient,
userAccount,
driftClient2,
Expand Down Expand Up @@ -1098,6 +1107,7 @@ describe('capped funding', () => {
totalFee,
cumulativeFee,
] = await cappedSymFundingScenario(
rollingMarketNum - 1,
driftClient,
userAccount,
driftClient2,
Expand Down
1 change: 1 addition & 0 deletions tests/curve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ describe('AMM Curve', () => {
const periodicity = new BN(60 * 60); // 1 HOUR

await driftClient.initializePerpMarket(
0,
solUsdOracle,
ammInitialBaseAssetAmount,
ammInitialQuoteAssetAmount,
Expand Down
1 change: 1 addition & 0 deletions tests/delistMarket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ describe('delist market', () => {
const periodicity = new BN(0);

await driftClient.initializePerpMarket(
0,
solOracle,
ammInitialBaseAssetReserve,
ammInitialQuoteAssetReserve,
Expand Down
1 change: 1 addition & 0 deletions tests/delistMarketLiq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ describe('delist market, liquidation of expired position', () => {
const periodicity = new BN(0);

await driftClient.initializePerpMarket(
0,
solOracle,
ammInitialBaseAssetReserve,
ammInitialQuoteAssetReserve,
Expand Down
1 change: 1 addition & 0 deletions tests/driftClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ describe('drift client', () => {

const marketIndex = 0;
const txSig = await driftClient.initializePerpMarket(
0,
solUsd,
ammInitialBaseAssetAmount,
ammInitialQuoteAssetAmount,
Expand Down
Loading

0 comments on commit 51c8be0

Please sign in to comment.