From 762608ecce596b8cd110b1fd3a7e4b0de1b32164 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Fri, 31 Mar 2023 12:48:34 +0200 Subject: [PATCH] Limit funding and interest accrual during downtimes (#529) Previously, if the funding or interest updating instruction wasn't called for a long time (like for a solana downtime or the security council halting the program), the next update would apply funding or interest for the whole time interval since the last update. This could lead to a bad downtime situation becoming worse. Instead, limit the maximum funding and interest time interval to one hour. --- .../src/instructions/token_update_index_and_rate.rs | 7 ++++++- programs/mango-v4/src/state/perp_market.rs | 9 ++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/programs/mango-v4/src/instructions/token_update_index_and_rate.rs b/programs/mango-v4/src/instructions/token_update_index_and_rate.rs index 9c7d68a70..15cb1ec57 100644 --- a/programs/mango-v4/src/instructions/token_update_index_and_rate.rs +++ b/programs/mango-v4/src/instructions/token_update_index_and_rate.rs @@ -71,7 +71,12 @@ pub fn token_update_index_and_rate(ctx: Context) -> Res { let mut some_bank = ctx.remaining_accounts[0].load_mut::()?; - let diff_ts = I80F48::from_num(now_ts - some_bank.index_last_updated); + // Limit the maximal time interval that interest is applied for. This means we won't use + // a fixed interest rate for a very long time period in exceptional circumstances, like + // when there is a solana downtime or the security council disables this instruction. + let max_interest_timestep = 3600; // hour + let diff_ts = + I80F48::from_num((now_ts - some_bank.index_last_updated).min(max_interest_timestep)); let (deposit_index, borrow_index, borrow_fees, borrow_rate, deposit_rate) = some_bank.compute_index(indexed_total_deposits, indexed_total_borrows, diff_ts)?; diff --git a/programs/mango-v4/src/state/perp_market.rs b/programs/mango-v4/src/state/perp_market.rs index 00f0751b3..67b640e1c 100644 --- a/programs/mango-v4/src/state/perp_market.rs +++ b/programs/mango-v4/src/state/perp_market.rs @@ -288,7 +288,14 @@ impl PerpMarket { (None, None) => I80F48::ZERO, }; - let diff_ts = I80F48::from_num(now_ts - self.funding_last_updated as u64); + // Limit the maximal time interval that funding is applied for. This means we won't use + // the funding rate computed from a single orderbook snapshot for a very long time period + // in exceptional circumstances, like a solana downtime or the security council disabling + // funding updates. + let max_funding_timestep = 3600; // one hour + let diff_ts = + I80F48::from_num((now_ts - self.funding_last_updated as u64).min(max_funding_timestep)); + let time_factor = diff_ts / DAY_I80F48; let base_lot_size = I80F48::from_num(self.base_lot_size);