Skip to content

Commit 94af1bd

Browse files
crispheaneywphan
andauthored
program: deposit into if stake from admin (#1899)
* program: deposit into if stake from admin * add test * change action * cargo fmt -- * move depositIntoInsuranceFundStake to adminClient --------- Co-authored-by: wphan <[email protected]>
1 parent 10c9c14 commit 94af1bd

File tree

8 files changed

+341
-3
lines changed

8 files changed

+341
-3
lines changed

programs/drift/src/controller/insurance.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ pub fn add_insurance_fund_stake(
112112
user_stats: &mut UserStats,
113113
spot_market: &mut SpotMarket,
114114
now: i64,
115+
admin_deposit: bool,
115116
) -> DriftResult {
116117
validate!(
117118
!(insurance_vault_amount == 0 && spot_market.insurance_fund.total_shares != 0),
@@ -161,7 +162,11 @@ pub fn add_insurance_fund_stake(
161162
emit!(InsuranceFundStakeRecord {
162163
ts: now,
163164
user_authority: user_stats.authority,
164-
action: StakeAction::Stake,
165+
action: if admin_deposit {
166+
StakeAction::AdminDeposit
167+
} else {
168+
StakeAction::Stake
169+
},
165170
amount,
166171
market_index: spot_market.market_index,
167172
insurance_vault_amount_before: insurance_vault_amount,

programs/drift/src/controller/insurance/tests.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub fn basic_stake_if_test() {
4141
&mut user_stats,
4242
&mut spot_market,
4343
0,
44+
false,
4445
)
4546
.unwrap();
4647
assert_eq!(if_stake.unchecked_if_shares(), amount as u128);
@@ -104,6 +105,7 @@ pub fn basic_stake_if_test() {
104105
&mut user_stats,
105106
&mut spot_market,
106107
0,
108+
false,
107109
)
108110
.unwrap();
109111
assert_eq!(if_stake.cost_basis, 1234);
@@ -141,6 +143,7 @@ pub fn basic_seeded_stake_if_test() {
141143
&mut user_stats,
142144
&mut spot_market,
143145
0,
146+
false,
144147
)
145148
.unwrap();
146149

@@ -202,6 +205,7 @@ pub fn basic_seeded_stake_if_test() {
202205
&mut user_stats,
203206
&mut spot_market,
204207
0,
208+
false,
205209
)
206210
.unwrap();
207211
assert_eq!(if_stake.cost_basis, 1234);
@@ -245,6 +249,7 @@ pub fn large_num_seeded_stake_if_test() {
245249
&mut user_stats,
246250
&mut spot_market,
247251
0,
252+
false,
248253
)
249254
.unwrap();
250255

@@ -334,6 +339,7 @@ pub fn large_num_seeded_stake_if_test() {
334339
&mut user_stats,
335340
&mut spot_market,
336341
20,
342+
false,
337343
)
338344
.unwrap();
339345
assert_eq!(if_stake.cost_basis, 199033744205760);
@@ -346,6 +352,7 @@ pub fn large_num_seeded_stake_if_test() {
346352
&mut user_stats,
347353
&mut spot_market,
348354
30,
355+
false,
349356
)
350357
.unwrap();
351358
assert_eq!(if_stake.cost_basis, 398067488411520);
@@ -378,6 +385,7 @@ pub fn gains_stake_if_test() {
378385
&mut user_stats,
379386
&mut spot_market,
380387
0,
388+
false,
381389
)
382390
.unwrap();
383391
assert_eq!(if_stake.unchecked_if_shares(), amount as u128);
@@ -502,6 +510,7 @@ pub fn losses_stake_if_test() {
502510
&mut user_stats,
503511
&mut spot_market,
504512
0,
513+
false,
505514
)
506515
.unwrap();
507516
assert_eq!(if_stake.unchecked_if_shares(), amount as u128);
@@ -631,6 +640,7 @@ pub fn escrow_losses_stake_if_test() {
631640
&mut user_stats,
632641
&mut spot_market,
633642
0,
643+
false,
634644
)
635645
.unwrap();
636646
assert_eq!(if_stake.unchecked_if_shares(), amount as u128);
@@ -729,7 +739,8 @@ pub fn escrow_gains_stake_if_test() {
729739
&mut if_stake,
730740
&mut user_stats,
731741
&mut spot_market,
732-
0
742+
0,
743+
false,
733744
)
734745
.is_err());
735746

@@ -741,6 +752,7 @@ pub fn escrow_gains_stake_if_test() {
741752
&mut user_stats,
742753
&mut spot_market,
743754
0,
755+
false,
744756
)
745757
.unwrap();
746758

@@ -858,6 +870,7 @@ pub fn drained_stake_if_test_rebase_on_new_add() {
858870
&mut user_stats,
859871
&mut spot_market,
860872
0,
873+
false,
861874
)
862875
.is_err());
863876

@@ -877,6 +890,7 @@ pub fn drained_stake_if_test_rebase_on_new_add() {
877890
&mut user_stats,
878891
&mut spot_market,
879892
0,
893+
false,
880894
)
881895
.unwrap();
882896
if_balance += amount;
@@ -912,6 +926,7 @@ pub fn drained_stake_if_test_rebase_on_new_add() {
912926
&mut orig_user_stats,
913927
&mut spot_market,
914928
0,
929+
false,
915930
)
916931
.unwrap();
917932

@@ -1010,6 +1025,7 @@ pub fn drained_stake_if_test_rebase_on_old_remove_all() {
10101025
&mut user_stats,
10111026
&mut spot_market,
10121027
0,
1028+
false,
10131029
)
10141030
.unwrap();
10151031

@@ -1210,6 +1226,7 @@ pub fn drained_stake_if_test_rebase_on_old_remove_all_2() {
12101226
&mut user_stats,
12111227
&mut spot_market,
12121228
0,
1229+
false,
12131230
)
12141231
.unwrap();
12151232
if_balance += 10_000_000_000_000;
@@ -1254,6 +1271,7 @@ pub fn multiple_if_stakes_and_rebase() {
12541271
&mut user_stats_1,
12551272
&mut spot_market,
12561273
0,
1274+
false,
12571275
)
12581276
.unwrap();
12591277

@@ -1266,6 +1284,7 @@ pub fn multiple_if_stakes_and_rebase() {
12661284
&mut user_stats_2,
12671285
&mut spot_market,
12681286
0,
1287+
false,
12691288
)
12701289
.unwrap();
12711290

@@ -1392,6 +1411,7 @@ pub fn multiple_if_stakes_and_rebase_and_admin_remove() {
13921411
&mut user_stats_1,
13931412
&mut spot_market,
13941413
0,
1414+
false,
13951415
)
13961416
.unwrap();
13971417

@@ -1404,6 +1424,7 @@ pub fn multiple_if_stakes_and_rebase_and_admin_remove() {
14041424
&mut user_stats_2,
14051425
&mut spot_market,
14061426
0,
1427+
false,
14071428
)
14081429
.unwrap();
14091430

programs/drift/src/instructions/if_staker.rs

Lines changed: 156 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use anchor_lang::Discriminator;
33
use anchor_spl::token_interface::{TokenAccount, TokenInterface};
44

55
use crate::error::ErrorCode;
6-
use crate::ids::if_rebalance_wallet;
6+
use crate::ids::{admin_hot_wallet, if_rebalance_wallet};
77
use crate::instructions::constraints::*;
88
use crate::instructions::optional_accounts::{load_maps, AccountMaps};
99
use crate::optional_accounts::get_token_mint;
@@ -143,6 +143,7 @@ pub fn handle_add_insurance_fund_stake<'c: 'info, 'info>(
143143
user_stats,
144144
spot_market,
145145
clock.unix_timestamp,
146+
false,
146147
)?;
147148

148149
controller::token::receive(
@@ -821,6 +822,114 @@ pub fn handle_transfer_protocol_if_shares_to_revenue_pool<'c: 'info, 'info>(
821822
Ok(())
822823
}
823824

825+
pub fn handle_deposit_into_insurance_fund_stake<'c: 'info, 'info>(
826+
ctx: Context<'_, '_, 'c, 'info, DepositIntoInsuranceFundStake<'info>>,
827+
market_index: u16,
828+
amount: u64,
829+
) -> Result<()> {
830+
if amount == 0 {
831+
return Err(ErrorCode::InsufficientDeposit.into());
832+
}
833+
834+
let clock = Clock::get()?;
835+
let now = clock.unix_timestamp;
836+
let insurance_fund_stake = &mut load_mut!(ctx.accounts.insurance_fund_stake)?;
837+
let user_stats = &mut load_mut!(ctx.accounts.user_stats)?;
838+
let spot_market = &mut load_mut!(ctx.accounts.spot_market)?;
839+
let state = &ctx.accounts.state;
840+
841+
let remaining_accounts_iter = &mut ctx.remaining_accounts.iter().peekable();
842+
let mint = get_token_mint(remaining_accounts_iter)?;
843+
844+
validate!(
845+
!spot_market.is_insurance_fund_operation_paused(InsuranceFundOperation::Add),
846+
ErrorCode::InsuranceFundOperationPaused,
847+
"if staking add disabled",
848+
)?;
849+
850+
validate!(
851+
insurance_fund_stake.market_index == market_index,
852+
ErrorCode::IncorrectSpotMarketAccountPassed,
853+
"insurance_fund_stake does not match market_index"
854+
)?;
855+
856+
validate!(
857+
spot_market.status != MarketStatus::Initialized,
858+
ErrorCode::InvalidSpotMarketState,
859+
"spot market = {} not active for insurance_fund_stake",
860+
spot_market.market_index
861+
)?;
862+
863+
validate!(
864+
insurance_fund_stake.last_withdraw_request_shares == 0
865+
&& insurance_fund_stake.last_withdraw_request_value == 0,
866+
ErrorCode::IFWithdrawRequestInProgress,
867+
"withdraw request in progress"
868+
)?;
869+
870+
{
871+
if spot_market.has_transfer_hook() {
872+
controller::insurance::attempt_settle_revenue_to_insurance_fund(
873+
&ctx.accounts.spot_market_vault,
874+
&ctx.accounts.insurance_fund_vault,
875+
spot_market,
876+
now,
877+
&ctx.accounts.token_program,
878+
&ctx.accounts.drift_signer,
879+
state,
880+
&mint,
881+
Some(&mut remaining_accounts_iter.clone()),
882+
)?;
883+
} else {
884+
controller::insurance::attempt_settle_revenue_to_insurance_fund(
885+
&ctx.accounts.spot_market_vault,
886+
&ctx.accounts.insurance_fund_vault,
887+
spot_market,
888+
now,
889+
&ctx.accounts.token_program,
890+
&ctx.accounts.drift_signer,
891+
state,
892+
&mint,
893+
None,
894+
)?;
895+
};
896+
897+
// reload the vault balances so they're up-to-date
898+
ctx.accounts.spot_market_vault.reload()?;
899+
ctx.accounts.insurance_fund_vault.reload()?;
900+
math::spot_withdraw::validate_spot_market_vault_amount(
901+
spot_market,
902+
ctx.accounts.spot_market_vault.amount,
903+
)?;
904+
}
905+
906+
controller::insurance::add_insurance_fund_stake(
907+
amount,
908+
ctx.accounts.insurance_fund_vault.amount,
909+
insurance_fund_stake,
910+
user_stats,
911+
spot_market,
912+
clock.unix_timestamp,
913+
true,
914+
)?;
915+
916+
controller::token::receive(
917+
&ctx.accounts.token_program,
918+
&ctx.accounts.user_token_account,
919+
&ctx.accounts.insurance_fund_vault,
920+
&ctx.accounts.signer.to_account_info(),
921+
amount,
922+
&mint,
923+
if spot_market.has_transfer_hook() {
924+
Some(remaining_accounts_iter)
925+
} else {
926+
None
927+
},
928+
)?;
929+
930+
Ok(())
931+
}
932+
824933
#[derive(Accounts)]
825934
#[instruction(
826935
market_index: u16,
@@ -1082,3 +1191,49 @@ pub struct TransferProtocolIfSharesToRevenuePool<'info> {
10821191
/// CHECK: forced drift_signer
10831192
pub drift_signer: AccountInfo<'info>,
10841193
}
1194+
1195+
#[derive(Accounts)]
1196+
#[instruction(market_index: u16,)]
1197+
pub struct DepositIntoInsuranceFundStake<'info> {
1198+
pub signer: Signer<'info>,
1199+
#[account(
1200+
mut,
1201+
constraint = signer.key() == admin_hot_wallet::id() || signer.key() == state.admin
1202+
)]
1203+
pub state: Box<Account<'info, State>>,
1204+
#[account(
1205+
mut,
1206+
seeds = [b"spot_market", market_index.to_le_bytes().as_ref()],
1207+
bump
1208+
)]
1209+
pub spot_market: AccountLoader<'info, SpotMarket>,
1210+
#[account(
1211+
mut,
1212+
seeds = [b"insurance_fund_stake", user_stats.load()?.authority.as_ref(), market_index.to_le_bytes().as_ref()],
1213+
bump,
1214+
)]
1215+
pub insurance_fund_stake: AccountLoader<'info, InsuranceFundStake>,
1216+
#[account(mut)]
1217+
pub user_stats: AccountLoader<'info, UserStats>,
1218+
#[account(
1219+
mut,
1220+
seeds = [b"spot_market_vault".as_ref(), market_index.to_le_bytes().as_ref()],
1221+
bump,
1222+
)]
1223+
pub spot_market_vault: Box<InterfaceAccount<'info, TokenAccount>>,
1224+
#[account(
1225+
mut,
1226+
seeds = [b"insurance_fund_vault".as_ref(), market_index.to_le_bytes().as_ref()],
1227+
bump,
1228+
)]
1229+
pub insurance_fund_vault: Box<InterfaceAccount<'info, TokenAccount>>,
1230+
#[account(
1231+
mut,
1232+
token::mint = insurance_fund_vault.mint,
1233+
token::authority = signer
1234+
)]
1235+
pub user_token_account: Box<InterfaceAccount<'info, TokenAccount>>,
1236+
pub token_program: Interface<'info, TokenInterface>,
1237+
/// CHECK: forced drift_signer
1238+
pub drift_signer: AccountInfo<'info>,
1239+
}

programs/drift/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,14 @@ pub mod drift {
813813
handle_transfer_protocol_if_shares_to_revenue_pool(ctx, market_index, amount)
814814
}
815815

816+
pub fn deposit_into_insurance_fund_stake<'c: 'info, 'info>(
817+
ctx: Context<'_, '_, 'c, 'info, DepositIntoInsuranceFundStake<'info>>,
818+
market_index: u16,
819+
amount: u64,
820+
) -> Result<()> {
821+
handle_deposit_into_insurance_fund_stake(ctx, market_index, amount)
822+
}
823+
816824
pub fn update_pyth_pull_oracle(
817825
ctx: Context<UpdatePythPullOraclePriceFeed>,
818826
feed_id: [u8; 32],

programs/drift/src/state/events.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ pub enum StakeAction {
580580
Unstake,
581581
UnstakeTransfer,
582582
StakeTransfer,
583+
AdminDeposit,
583584
}
584585

585586
#[event]

0 commit comments

Comments
 (0)