Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion programs/drift/src/controller/insurance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ pub fn add_insurance_fund_stake(
user_stats: &mut UserStats,
spot_market: &mut SpotMarket,
now: i64,
admin_deposit: bool,
) -> DriftResult {
validate!(
!(insurance_vault_amount == 0 && spot_market.insurance_fund.total_shares != 0),
Expand Down Expand Up @@ -161,7 +162,11 @@ pub fn add_insurance_fund_stake(
emit!(InsuranceFundStakeRecord {
ts: now,
user_authority: user_stats.authority,
action: StakeAction::Stake,
action: if admin_deposit {
StakeAction::AdminDeposit
} else {
StakeAction::Stake
},
amount,
market_index: spot_market.market_index,
insurance_vault_amount_before: insurance_vault_amount,
Expand Down
23 changes: 22 additions & 1 deletion programs/drift/src/controller/insurance/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub fn basic_stake_if_test() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();
assert_eq!(if_stake.unchecked_if_shares(), amount as u128);
Expand Down Expand Up @@ -104,6 +105,7 @@ pub fn basic_stake_if_test() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();
assert_eq!(if_stake.cost_basis, 1234);
Expand Down Expand Up @@ -141,6 +143,7 @@ pub fn basic_seeded_stake_if_test() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();

Expand Down Expand Up @@ -202,6 +205,7 @@ pub fn basic_seeded_stake_if_test() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();
assert_eq!(if_stake.cost_basis, 1234);
Expand Down Expand Up @@ -245,6 +249,7 @@ pub fn large_num_seeded_stake_if_test() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();

Expand Down Expand Up @@ -334,6 +339,7 @@ pub fn large_num_seeded_stake_if_test() {
&mut user_stats,
&mut spot_market,
20,
false,
)
.unwrap();
assert_eq!(if_stake.cost_basis, 199033744205760);
Expand All @@ -346,6 +352,7 @@ pub fn large_num_seeded_stake_if_test() {
&mut user_stats,
&mut spot_market,
30,
false,
)
.unwrap();
assert_eq!(if_stake.cost_basis, 398067488411520);
Expand Down Expand Up @@ -378,6 +385,7 @@ pub fn gains_stake_if_test() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();
assert_eq!(if_stake.unchecked_if_shares(), amount as u128);
Expand Down Expand Up @@ -502,6 +510,7 @@ pub fn losses_stake_if_test() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();
assert_eq!(if_stake.unchecked_if_shares(), amount as u128);
Expand Down Expand Up @@ -631,6 +640,7 @@ pub fn escrow_losses_stake_if_test() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();
assert_eq!(if_stake.unchecked_if_shares(), amount as u128);
Expand Down Expand Up @@ -729,7 +739,8 @@ pub fn escrow_gains_stake_if_test() {
&mut if_stake,
&mut user_stats,
&mut spot_market,
0
0,
false,
)
.is_err());

Expand All @@ -741,6 +752,7 @@ pub fn escrow_gains_stake_if_test() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();

Expand Down Expand Up @@ -858,6 +870,7 @@ pub fn drained_stake_if_test_rebase_on_new_add() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.is_err());

Expand All @@ -877,6 +890,7 @@ pub fn drained_stake_if_test_rebase_on_new_add() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();
if_balance += amount;
Expand Down Expand Up @@ -912,6 +926,7 @@ pub fn drained_stake_if_test_rebase_on_new_add() {
&mut orig_user_stats,
&mut spot_market,
0,
false,
)
.unwrap();

Expand Down Expand Up @@ -1010,6 +1025,7 @@ pub fn drained_stake_if_test_rebase_on_old_remove_all() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();

Expand Down Expand Up @@ -1210,6 +1226,7 @@ pub fn drained_stake_if_test_rebase_on_old_remove_all_2() {
&mut user_stats,
&mut spot_market,
0,
false,
)
.unwrap();
if_balance += 10_000_000_000_000;
Expand Down Expand Up @@ -1254,6 +1271,7 @@ pub fn multiple_if_stakes_and_rebase() {
&mut user_stats_1,
&mut spot_market,
0,
false,
)
.unwrap();

Expand All @@ -1266,6 +1284,7 @@ pub fn multiple_if_stakes_and_rebase() {
&mut user_stats_2,
&mut spot_market,
0,
false,
)
.unwrap();

Expand Down Expand Up @@ -1392,6 +1411,7 @@ pub fn multiple_if_stakes_and_rebase_and_admin_remove() {
&mut user_stats_1,
&mut spot_market,
0,
false,
)
.unwrap();

Expand All @@ -1404,6 +1424,7 @@ pub fn multiple_if_stakes_and_rebase_and_admin_remove() {
&mut user_stats_2,
&mut spot_market,
0,
false,
)
.unwrap();

Expand Down
157 changes: 156 additions & 1 deletion programs/drift/src/instructions/if_staker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use anchor_lang::Discriminator;
use anchor_spl::token_interface::{TokenAccount, TokenInterface};

use crate::error::ErrorCode;
use crate::ids::if_rebalance_wallet;
use crate::ids::{admin_hot_wallet, if_rebalance_wallet};
use crate::instructions::constraints::*;
use crate::instructions::optional_accounts::{load_maps, AccountMaps};
use crate::optional_accounts::get_token_mint;
Expand Down Expand Up @@ -143,6 +143,7 @@ pub fn handle_add_insurance_fund_stake<'c: 'info, 'info>(
user_stats,
spot_market,
clock.unix_timestamp,
false,
)?;

controller::token::receive(
Expand Down Expand Up @@ -821,6 +822,114 @@ pub fn handle_transfer_protocol_if_shares_to_revenue_pool<'c: 'info, 'info>(
Ok(())
}

pub fn handle_deposit_into_insurance_fund_stake<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, DepositIntoInsuranceFundStake<'info>>,
market_index: u16,
amount: u64,
) -> Result<()> {
if amount == 0 {
return Err(ErrorCode::InsufficientDeposit.into());
}

let clock = Clock::get()?;
let now = clock.unix_timestamp;
let insurance_fund_stake = &mut load_mut!(ctx.accounts.insurance_fund_stake)?;
let user_stats = &mut load_mut!(ctx.accounts.user_stats)?;
let spot_market = &mut load_mut!(ctx.accounts.spot_market)?;
let state = &ctx.accounts.state;

let remaining_accounts_iter = &mut ctx.remaining_accounts.iter().peekable();
let mint = get_token_mint(remaining_accounts_iter)?;

validate!(
!spot_market.is_insurance_fund_operation_paused(InsuranceFundOperation::Add),
ErrorCode::InsuranceFundOperationPaused,
"if staking add disabled",
)?;

validate!(
insurance_fund_stake.market_index == market_index,
ErrorCode::IncorrectSpotMarketAccountPassed,
"insurance_fund_stake does not match market_index"
)?;

validate!(
spot_market.status != MarketStatus::Initialized,
ErrorCode::InvalidSpotMarketState,
"spot market = {} not active for insurance_fund_stake",
spot_market.market_index
)?;

validate!(
insurance_fund_stake.last_withdraw_request_shares == 0
&& insurance_fund_stake.last_withdraw_request_value == 0,
ErrorCode::IFWithdrawRequestInProgress,
"withdraw request in progress"
)?;

{
if spot_market.has_transfer_hook() {
controller::insurance::attempt_settle_revenue_to_insurance_fund(
&ctx.accounts.spot_market_vault,
&ctx.accounts.insurance_fund_vault,
spot_market,
now,
&ctx.accounts.token_program,
&ctx.accounts.drift_signer,
state,
&mint,
Some(&mut remaining_accounts_iter.clone()),
)?;
} else {
controller::insurance::attempt_settle_revenue_to_insurance_fund(
&ctx.accounts.spot_market_vault,
&ctx.accounts.insurance_fund_vault,
spot_market,
now,
&ctx.accounts.token_program,
&ctx.accounts.drift_signer,
state,
&mint,
None,
)?;
};

// reload the vault balances so they're up-to-date
ctx.accounts.spot_market_vault.reload()?;
ctx.accounts.insurance_fund_vault.reload()?;
math::spot_withdraw::validate_spot_market_vault_amount(
spot_market,
ctx.accounts.spot_market_vault.amount,
)?;
}

controller::insurance::add_insurance_fund_stake(
amount,
ctx.accounts.insurance_fund_vault.amount,
insurance_fund_stake,
user_stats,
spot_market,
clock.unix_timestamp,
true,
)?;

controller::token::receive(
&ctx.accounts.token_program,
&ctx.accounts.user_token_account,
&ctx.accounts.insurance_fund_vault,
&ctx.accounts.signer.to_account_info(),
amount,
&mint,
if spot_market.has_transfer_hook() {
Some(remaining_accounts_iter)
} else {
None
},
)?;

Ok(())
}

#[derive(Accounts)]
#[instruction(
market_index: u16,
Expand Down Expand Up @@ -1082,3 +1191,49 @@ pub struct TransferProtocolIfSharesToRevenuePool<'info> {
/// CHECK: forced drift_signer
pub drift_signer: AccountInfo<'info>,
}

#[derive(Accounts)]
#[instruction(market_index: u16,)]
pub struct DepositIntoInsuranceFundStake<'info> {
pub signer: Signer<'info>,
#[account(
mut,
constraint = signer.key() == admin_hot_wallet::id() || signer.key() == state.admin
)]
pub state: Box<Account<'info, State>>,
#[account(
mut,
seeds = [b"spot_market", market_index.to_le_bytes().as_ref()],
bump
)]
pub spot_market: AccountLoader<'info, SpotMarket>,
#[account(
mut,
seeds = [b"insurance_fund_stake", user_stats.load()?.authority.as_ref(), market_index.to_le_bytes().as_ref()],
bump,
)]
pub insurance_fund_stake: AccountLoader<'info, InsuranceFundStake>,
#[account(mut)]
pub user_stats: AccountLoader<'info, UserStats>,
#[account(
mut,
seeds = [b"spot_market_vault".as_ref(), market_index.to_le_bytes().as_ref()],
bump,
)]
pub spot_market_vault: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(
mut,
seeds = [b"insurance_fund_vault".as_ref(), market_index.to_le_bytes().as_ref()],
bump,
)]
pub insurance_fund_vault: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(
mut,
token::mint = insurance_fund_vault.mint,
token::authority = signer
)]
pub user_token_account: Box<InterfaceAccount<'info, TokenAccount>>,
pub token_program: Interface<'info, TokenInterface>,
/// CHECK: forced drift_signer
pub drift_signer: AccountInfo<'info>,
}
8 changes: 8 additions & 0 deletions programs/drift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,14 @@ pub mod drift {
handle_transfer_protocol_if_shares_to_revenue_pool(ctx, market_index, amount)
}

pub fn deposit_into_insurance_fund_stake<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, DepositIntoInsuranceFundStake<'info>>,
market_index: u16,
amount: u64,
) -> Result<()> {
handle_deposit_into_insurance_fund_stake(ctx, market_index, amount)
}

pub fn update_pyth_pull_oracle(
ctx: Context<UpdatePythPullOraclePriceFeed>,
feed_id: [u8; 32],
Expand Down
1 change: 1 addition & 0 deletions programs/drift/src/state/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@ pub enum StakeAction {
Unstake,
UnstakeTransfer,
StakeTransfer,
AdminDeposit,
}

#[event]
Expand Down
Loading
Loading