Skip to content

Commit

Permalink
program: flag idle users on-chain (#386)
Browse files Browse the repository at this point in the history
* init

* add updateUserInactive ix

* sdk: add canMakeInactive

* sdk: add fetchAllUserAccounts

* rename to idle

* update sdk to use idle nomenclature

* check last update slot before making use inactive

* make slots before idle different for devnet/mainnet

* CHANGELOG
  • Loading branch information
crispheaney authored Mar 14, 2023
1 parent 1869dba commit 43b937e
Show file tree
Hide file tree
Showing 15 changed files with 314 additions and 38 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- program: flag users as idle on-chain ([#386](https://github.com/drift-labs/protocol-v2/pull/386))

### Fixes

### Breaking
Expand Down
30 changes: 15 additions & 15 deletions programs/drift/src/controller/liquidation/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1490,7 +1490,7 @@ pub mod liquidate_perp {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 1);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 7010000);
assert_eq!(user.perp_positions[0].base_asset_amount, 2000000000);

Expand All @@ -1515,7 +1515,7 @@ pub mod liquidate_perp {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 1);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 9610000);
assert_eq!(user.perp_positions[0].base_asset_amount, 1480000000);

Expand Down Expand Up @@ -1558,7 +1558,7 @@ pub mod liquidate_perp {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 1);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 9610000); // no new margin freed
assert_eq!(user.perp_positions[0].base_asset_amount, 1480000000);

Expand All @@ -1583,7 +1583,7 @@ pub mod liquidate_perp {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 1);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 12310000);
assert_eq!(user.perp_positions[0].base_asset_amount, 940000000);

Expand Down Expand Up @@ -1627,7 +1627,7 @@ pub mod liquidate_perp {
.unwrap();

assert_eq!(user.status, UserStatus::Active);
assert_eq!(user.liquidation_start_slot, 0);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 0);
assert_eq!(user.perp_positions[0].base_asset_amount, 200000000);
}
Expand Down Expand Up @@ -1750,7 +1750,7 @@ pub mod liquidate_perp {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 1);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 1560000);
assert_eq!(user.perp_positions[0].base_asset_amount, 610000000);
}
Expand Down Expand Up @@ -2740,7 +2740,7 @@ pub mod liquidate_spot {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 1);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 700032);
assert_eq!(user.spot_positions[0].scaled_balance, 99055856000);
assert_eq!(user.spot_positions[1].scaled_balance, 940676999);
Expand Down Expand Up @@ -2784,7 +2784,7 @@ pub mod liquidate_spot {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 1);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 3032982);
assert_eq!(user.spot_positions[0].scaled_balance, 79245846000);
assert_eq!(user.spot_positions[1].scaled_balance, 742971998);
Expand Down Expand Up @@ -2828,7 +2828,7 @@ pub mod liquidate_spot {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 0);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 0);
assert_eq!(user.spot_positions[0].scaled_balance, 45559160000);
assert_eq!(user.spot_positions[1].scaled_balance, 406777997);
Expand Down Expand Up @@ -3928,7 +3928,7 @@ pub mod liquidate_borrow_for_perp_pnl {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 1);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 699993);
assert_eq!(user.spot_positions[0].scaled_balance, 935773999);
assert_eq!(user.perp_positions[0].quote_asset_amount, 98506681);
Expand Down Expand Up @@ -3972,7 +3972,7 @@ pub mod liquidate_borrow_for_perp_pnl {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 1);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 3032859);
assert_eq!(user.spot_positions[0].scaled_balance, 721727998);
assert_eq!(user.perp_positions[0].quote_asset_amount, 76866395);
Expand Down Expand Up @@ -4017,7 +4017,7 @@ pub mod liquidate_borrow_for_perp_pnl {
.unwrap();

assert_eq!(user.liquidation_margin_freed, 0);
assert_eq!(user.liquidation_start_slot, 0);
assert_eq!(user.last_active_slot, 1);
}
}

Expand Down Expand Up @@ -5075,7 +5075,7 @@ pub mod liquidate_perp_pnl_for_deposit {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 1);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 100051);
assert_eq!(user.spot_positions[0].scaled_balance, 988766000);
assert_eq!(user.perp_positions[0].quote_asset_amount, -89888889);
Expand Down Expand Up @@ -5119,7 +5119,7 @@ pub mod liquidate_perp_pnl_for_deposit {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 1);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 433231);
assert_eq!(user.spot_positions[0].scaled_balance, 951337000);
assert_eq!(user.perp_positions[0].quote_asset_amount, -86187099);
Expand Down Expand Up @@ -5163,7 +5163,7 @@ pub mod liquidate_perp_pnl_for_deposit {
)
.unwrap();

assert_eq!(user.liquidation_start_slot, 0);
assert_eq!(user.last_active_slot, 1);
assert_eq!(user.liquidation_margin_freed, 0);
}

Expand Down
51 changes: 43 additions & 8 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ use crate::math::serum::{
use crate::math::spot_balance::{get_signed_token_amount, get_token_amount};
use crate::math::stats::calculate_new_twap;
use crate::math::{amm, fees, margin::*, orders::*};
use crate::{controller, load, PostOnlyParam};
use crate::{controller, PostOnlyParam};

use crate::math::amm::calculate_amm_available_liquidity;
use crate::math::safe_unwrap::SafeUnwrap;
Expand Down Expand Up @@ -369,6 +369,8 @@ pub fn place_perp_order(
};
emit!(order_record);

user.update_last_active_slot(slot);

Ok(())
}

Expand Down Expand Up @@ -481,6 +483,8 @@ pub fn cancel_orders(
)?;
}

user.update_last_active_slot(slot);

Ok(canceled_order_ids)
}

Expand Down Expand Up @@ -515,7 +519,11 @@ pub fn cancel_order_by_order_id(
None,
0,
false,
)
)?;

user.update_last_active_slot(clock.slot);

Ok(())
}

pub fn cancel_order_by_user_order_id(
Expand Down Expand Up @@ -553,7 +561,11 @@ pub fn cancel_order_by_user_order_id(
None,
0,
false,
)
)?;

user.update_last_active_slot(clock.slot);

Ok(())
}

pub fn cancel_order(
Expand Down Expand Up @@ -813,8 +825,12 @@ pub fn fill_perp_order(
slot,
)?;

let referrer_info =
get_referrer_info(user_stats, makers_and_referrer, makers_and_referrer_stats)?;
let referrer_info = get_referrer_info(
user_stats,
makers_and_referrer,
makers_and_referrer_stats,
slot,
)?;

let should_expire_order = should_expire_order(user, order_index, now)?;

Expand Down Expand Up @@ -960,6 +976,8 @@ pub fn fill_perp_order(
)?;
}

user.update_last_active_slot(slot);

Ok((base_asset_amount, updated_user_state))
}

Expand Down Expand Up @@ -1069,6 +1087,8 @@ fn get_maker_orders_info(
continue;
}

maker.update_last_active_slot(slot);

settle_funding_payment(&mut maker, maker_key, &mut market, now)?;

let initial_margin_ratio = market.margin_ratio_initial;
Expand Down Expand Up @@ -1192,6 +1212,7 @@ fn get_referrer_info(
user_stats: &UserStats,
makers_and_referrer: &UserMap,
makers_and_referrer_stats: &UserStatsMap,
slot: u64,
) -> DriftResult<Option<(Pubkey, Pubkey)>> {
if user_stats.referrer.eq(&Pubkey::default()) {
return Ok(None);
Expand All @@ -1207,7 +1228,7 @@ fn get_referrer_info(
let referrer_authority_key = user_stats.referrer;
let mut referrer_user_key = Pubkey::default();
for (referrer_key, referrer) in makers_and_referrer.0.iter() {
let referrer = load!(referrer)?;
let mut referrer = load_mut!(referrer)?;
if referrer.authority != referrer_authority_key {
continue;
}
Expand All @@ -1218,6 +1239,8 @@ fn get_referrer_info(
"Referrer must be user id 0"
)?;

referrer.update_last_active_slot(slot);

referrer_user_key = *referrer_key;
}

Expand Down Expand Up @@ -2394,6 +2417,8 @@ pub fn trigger_order(
)?;
}

user.update_last_active_slot(slot);

Ok(())
}

Expand Down Expand Up @@ -2489,6 +2514,8 @@ pub fn force_cancel_orders(
total_fee,
)?;

user.update_last_active_slot(slot);

Ok(())
}

Expand Down Expand Up @@ -2833,6 +2860,8 @@ pub fn place_spot_order(
};
emit!(order_record);

user.update_last_active_slot(slot);

Ok(())
}

Expand Down Expand Up @@ -2934,7 +2963,7 @@ pub fn fill_spot_order(
(None, None)
};

let (mut maker, mut maker_stats, maker_key, maker_order_index) = sanitize_spot_maker_order(
let (mut maker, mut maker_stats, maker_key, maker_order_index) = get_spot_maker_order(
perp_market_map,
spot_market_map,
oracle_map,
Expand Down Expand Up @@ -3076,11 +3105,13 @@ pub fn fill_spot_order(
)?
}

user.update_last_active_slot(slot);

Ok(base_asset_amount)
}

#[allow(clippy::type_complexity)]
fn sanitize_spot_maker_order<'a>(
fn get_spot_maker_order<'a>(
perp_market_map: &PerpMarketMap,
spot_market_map: &SpotMarketMap,
oracle_map: &mut OracleMap,
Expand Down Expand Up @@ -3113,6 +3144,8 @@ fn sanitize_spot_maker_order<'a>(
let maker_key = maker.key();
let mut maker = load_mut!(maker)?;

maker.update_last_active_slot(slot);

let maker_stats = if &maker.authority == taker_authority {
None
} else {
Expand Down Expand Up @@ -4356,6 +4389,8 @@ pub fn trigger_spot_order(
)?;
}

user.update_last_active_slot(slot);

Ok(())
}

Expand Down
2 changes: 2 additions & 0 deletions programs/drift/src/controller/orders/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7509,6 +7509,7 @@ pub mod fulfill_spot_order {
..SpotPosition::default()
};
expected_taker.cumulative_spot_fees = -100000;
expected_taker.last_active_slot = clock.slot;

let mut expected_maker = maker;
expected_maker.orders[1] = Order::default();
Expand All @@ -7527,6 +7528,7 @@ pub mod fulfill_spot_order {
..SpotPosition::default()
};
expected_maker.cumulative_spot_fees = 20000;
expected_maker.last_active_slot = clock.slot;

let base_asset_amount = fill_spot_order(
1,
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 @@ -481,6 +481,8 @@ pub enum ErrorCode {
UserStatsNotFound,
#[msg("UnableToLoadUserStatsAccount")]
UnableToLoadUserStatsAccount,
#[msg("User Not Inactive")]
UserNotInactive,
}

#[macro_export]
Expand Down
Loading

0 comments on commit 43b937e

Please sign in to comment.