Fix bug: only account for borrows we are offsetting (#513)

* Fix bug: only account for borrows we are offsetting

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* fix

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Bank: Unittest for net borrow limits

---------

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
Co-authored-by: Christian Kamm <mail@ckamm.de>
This commit is contained in:
microwavedcola1 2023-03-22 09:58:31 +01:00 committed by GitHub
parent 89f936c14a
commit 258d95d035
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 61 additions and 4 deletions

View File

@ -1,6 +1,7 @@
use super::{OracleConfig, TokenIndex, TokenPosition};
use crate::accounts_zerocopy::KeyedAccountReader;
use crate::error::*;
use crate::i80f48::ClampToInt;
use crate::state::{oracle, StablePriceModel};
use crate::util;
@ -302,9 +303,8 @@ impl Bank {
allow_dusting: bool,
now_ts: u64,
) -> Result<bool> {
self.update_net_borrows(-native_amount, now_ts);
let opening_indexed_position = position.indexed_position;
let result = self.deposit_internal(position, native_amount, allow_dusting)?;
let result = self.deposit_internal(position, native_amount, allow_dusting, now_ts)?;
self.update_cumulative_interest(position, opening_indexed_position);
Ok(result)
}
@ -315,6 +315,7 @@ impl Bank {
position: &mut TokenPosition,
mut native_amount: I80F48,
allow_dusting: bool,
now_ts: u64,
) -> Result<bool> {
require_gte!(native_amount, 0);
@ -336,6 +337,9 @@ impl Bank {
};
if native_position.is_negative() {
// Only account for the borrows we are repaying
self.update_net_borrows(native_position.max(-native_amount), now_ts);
let new_native_position = native_position + native_amount;
let indexed_change = div_rounding_up(native_amount, self.borrow_index);
// this is only correct if it's not positive, because it scales the whole amount by borrow_index
@ -585,13 +589,15 @@ impl Bank {
let in_new_window =
now_ts >= self.last_net_borrows_window_start_ts + self.net_borrow_limit_window_size_ts;
let amount = native_amount.ceil().clamp_to_i64();
self.net_borrows_in_window = if in_new_window {
// reset to latest window
self.last_net_borrows_window_start_ts = now_ts / self.net_borrow_limit_window_size_ts
* self.net_borrow_limit_window_size_ts;
native_amount.to_num::<i64>()
amount
} else {
self.net_borrows_in_window + native_amount.to_num::<i64>()
self.net_borrows_in_window + amount
};
}
@ -1015,4 +1021,55 @@ mod tests {
compute_new_avg_utilization_runner(&mut bank, I80F48::ONE, 1040);
assert_eq!(bank.avg_utilization, I80F48::ONE);
}
#[test]
pub fn test_net_borrows() -> Result<()> {
let mut bank = Bank::zeroed();
bank.net_borrow_limit_window_size_ts = 100;
bank.net_borrow_limit_per_window_quote = 1000;
bank.deposit_index = I80F48::from_num(100.0);
bank.borrow_index = I80F48::from_num(100.0);
let price = I80F48::from(2);
let mut account = TokenPosition::default();
bank.change_without_fee(&mut account, I80F48::from(100), 0, price)
.unwrap();
assert_eq!(bank.net_borrows_in_window, 0);
bank.change_without_fee(&mut account, I80F48::from(-100), 0, price)
.unwrap();
assert_eq!(bank.net_borrows_in_window, 0);
account = TokenPosition::default();
bank.change_without_fee(&mut account, I80F48::from(10), 0, price)
.unwrap();
bank.change_without_fee(&mut account, I80F48::from(-110), 0, price)
.unwrap();
assert_eq!(bank.net_borrows_in_window, 100);
bank.change_without_fee(&mut account, I80F48::from(50), 0, price)
.unwrap();
assert_eq!(bank.net_borrows_in_window, 50);
bank.change_without_fee(&mut account, I80F48::from(100), 0, price)
.unwrap();
assert_eq!(bank.net_borrows_in_window, 1); // rounding
account = TokenPosition::default();
bank.net_borrows_in_window = 0;
bank.change_without_fee(&mut account, I80F48::from(-450), 0, price)
.unwrap();
bank.change_without_fee(&mut account, I80F48::from(-51), 0, price)
.unwrap_err();
account = TokenPosition::default();
bank.net_borrows_in_window = 0;
bank.change_without_fee(&mut account, I80F48::from(-450), 0, price)
.unwrap();
bank.change_without_fee(&mut account, I80F48::from(-50), 0, price)
.unwrap();
bank.change_without_fee(&mut account, I80F48::from(-50), 101, price)
.unwrap();
Ok(())
}
}