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.
This commit is contained in:
Christian Kamm 2023-03-31 12:48:34 +02:00 committed by GitHub
parent 7080c9bf3c
commit 762608ecce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 2 deletions

View File

@ -71,7 +71,12 @@ pub fn token_update_index_and_rate(ctx: Context<TokenUpdateIndexAndRate>) -> Res
{ {
let mut some_bank = ctx.remaining_accounts[0].load_mut::<Bank>()?; let mut some_bank = ctx.remaining_accounts[0].load_mut::<Bank>()?;
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) = let (deposit_index, borrow_index, borrow_fees, borrow_rate, deposit_rate) =
some_bank.compute_index(indexed_total_deposits, indexed_total_borrows, diff_ts)?; some_bank.compute_index(indexed_total_deposits, indexed_total_borrows, diff_ts)?;

View File

@ -288,7 +288,14 @@ impl PerpMarket {
(None, None) => I80F48::ZERO, (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 time_factor = diff_ts / DAY_I80F48;
let base_lot_size = I80F48::from_num(self.base_lot_size); let base_lot_size = I80F48::from_num(self.base_lot_size);