diff --git a/programs/mango-v4/src/accounts_ix/mod.rs b/programs/mango-v4/src/accounts_ix/mod.rs index 1cd1b2a4e..d7eebcd74 100644 --- a/programs/mango-v4/src/accounts_ix/mod.rs +++ b/programs/mango-v4/src/accounts_ix/mod.rs @@ -67,6 +67,7 @@ pub use token_add_bank::*; pub use token_charge_collateral_fees::*; pub use token_conditional_swap_cancel::*; pub use token_conditional_swap_create::*; +pub use token_conditional_swap_purge::*; pub use token_conditional_swap_start::*; pub use token_conditional_swap_trigger::*; pub use token_deposit::*; @@ -150,6 +151,7 @@ mod token_add_bank; mod token_charge_collateral_fees; mod token_conditional_swap_cancel; mod token_conditional_swap_create; +mod token_conditional_swap_purge; mod token_conditional_swap_start; mod token_conditional_swap_trigger; mod token_deposit; diff --git a/programs/mango-v4/src/accounts_ix/token_conditional_swap_purge.rs b/programs/mango-v4/src/accounts_ix/token_conditional_swap_purge.rs new file mode 100644 index 000000000..3e0c2cb6c --- /dev/null +++ b/programs/mango-v4/src/accounts_ix/token_conditional_swap_purge.rs @@ -0,0 +1,31 @@ +use crate::error::*; +use crate::state::*; +use anchor_lang::prelude::*; + +#[derive(Accounts)] +pub struct TokenConditionalSwapCancel<'info> { + #[account( + constraint = group.load()?.is_ix_enabled(IxGate::TokenConditionalSwapCancel) @ MangoError::IxIsDisabled, + )] + pub group: AccountLoader<'info, Group>, + + #[account( + mut, + has_one = group, + constraint = account.load()?.is_operational() @ MangoError::AccountIsFrozen, + // owner is not checked on purpose + )] + pub account: AccountLoader<'info, MangoAccountFixed>, + + /// The bank's token_index is checked at #1 + #[account( + mut, + has_one = group, + )] + pub buy_bank: AccountLoader<'info, Bank>, + #[account( + mut, + has_one = group, + )] + pub sell_bank: AccountLoader<'info, Bank>, +} diff --git a/programs/mango-v4/src/instructions/mod.rs b/programs/mango-v4/src/instructions/mod.rs index 0ecc0225f..caa22e4b9 100644 --- a/programs/mango-v4/src/instructions/mod.rs +++ b/programs/mango-v4/src/instructions/mod.rs @@ -58,6 +58,7 @@ pub use token_add_bank::*; pub use token_charge_collateral_fees::*; pub use token_conditional_swap_cancel::*; pub use token_conditional_swap_create::*; +pub use token_conditional_swap_purge::*; pub use token_conditional_swap_start::*; pub use token_conditional_swap_trigger::*; pub use token_deposit::*; @@ -132,6 +133,7 @@ mod token_add_bank; mod token_charge_collateral_fees; mod token_conditional_swap_cancel; mod token_conditional_swap_create; +mod token_conditional_swap_purge; mod token_conditional_swap_start; mod token_conditional_swap_trigger; mod token_deposit; diff --git a/programs/mango-v4/src/instructions/token_conditional_swap_create.rs b/programs/mango-v4/src/instructions/token_conditional_swap_create.rs index 454c4a232..48d95d148 100644 --- a/programs/mango-v4/src/instructions/token_conditional_swap_create.rs +++ b/programs/mango-v4/src/instructions/token_conditional_swap_create.rs @@ -1,14 +1,18 @@ use anchor_lang::prelude::*; use crate::accounts_ix::*; +use crate::error::MangoError; use crate::logs::{emit_stack, TokenConditionalSwapCreateLogV3}; use crate::state::*; -#[allow(clippy::too_many_arguments)] +#[allow(clippy::too_many_arguments, unreachable_code)] pub fn token_conditional_swap_create( ctx: Context, token_conditional_swap: TokenConditionalSwap, ) -> Result<()> { + // disable creation of new TCS + return Err(MangoError::IxIsDisabled.into()); + let group = ctx.accounts.group.load()?; let now_ts: u64 = Clock::get()?.unix_timestamp.try_into().unwrap(); diff --git a/programs/mango-v4/src/instructions/token_conditional_swap_purge.rs b/programs/mango-v4/src/instructions/token_conditional_swap_purge.rs new file mode 100644 index 000000000..255722e38 --- /dev/null +++ b/programs/mango-v4/src/instructions/token_conditional_swap_purge.rs @@ -0,0 +1,52 @@ +use anchor_lang::prelude::*; + +use crate::accounts_ix::*; +use crate::error::MangoError; +use crate::logs::{emit_stack, TokenConditionalSwapCancelLog}; +use crate::state::*; + +#[allow(clippy::too_many_arguments)] +pub fn token_conditional_swap_purge( + ctx: Context, + token_conditional_swap_index: usize, + token_conditional_swap_id: u64, +) -> Result<()> { + let mut buy_bank = ctx.accounts.buy_bank.load_mut()?; + let mut sell_bank = ctx.accounts.sell_bank.load_mut()?; + + require!( + buy_bank.are_deposits_reduce_only() || sell_bank.are_borrows_reduce_only(), + MangoError::IxIsDisabled + ); + + let mut account = ctx.accounts.account.load_full_mut()?; + let tcs = account.token_conditional_swap_mut_by_index(token_conditional_swap_index)?; + require_eq!(tcs.buy_token_index, buy_bank.token_index); + require_eq!(tcs.sell_token_index, sell_bank.token_index); + + // If the tcs is already inactive, this just is a noop + if !tcs.is_configured() { + return Ok(()); + } + + require_eq!( + tcs.id, + token_conditional_swap_id, + MangoError::TokenConditionalSwapIndexIdMismatch + ); + *tcs = TokenConditionalSwap::default(); + + emit_stack(TokenConditionalSwapCancelLog { + mango_group: ctx.accounts.group.key(), + mango_account: ctx.accounts.account.key(), + id: token_conditional_swap_id, + }); + + let now_ts: u64 = Clock::get()?.unix_timestamp.try_into().unwrap(); + + // Free up any locks on token positions, possibly dust and deactivate them. + account.token_decrement_dust_deactivate(&mut buy_bank, now_ts, ctx.accounts.account.key())?; + account.token_decrement_dust_deactivate(&mut sell_bank, now_ts, ctx.accounts.account.key())?; + + Ok(()) +} diff --git a/programs/mango-v4/src/instructions/token_conditional_swap_start.rs b/programs/mango-v4/src/instructions/token_conditional_swap_start.rs index 4d3624ac0..16780d317 100644 --- a/programs/mango-v4/src/instructions/token_conditional_swap_start.rs +++ b/programs/mango-v4/src/instructions/token_conditional_swap_start.rs @@ -8,12 +8,15 @@ use crate::i80f48::ClampToInt; use crate::logs::{emit_stack, TokenBalanceLog, TokenConditionalSwapStartLog}; use crate::state::*; -#[allow(clippy::too_many_arguments)] +#[allow(clippy::too_many_arguments, unreachable_code)] pub fn token_conditional_swap_start( ctx: Context, token_conditional_swap_index: usize, token_conditional_swap_id: u64, ) -> Result<()> { + // disable start of new TCS + return Err(MangoError::IxIsDisabled.into()); + let group_pk = &ctx.accounts.group.key(); let liqee_key = ctx.accounts.liqee.key(); let liqor_key = ctx.accounts.liqor.key();