Add deposits/borrows tracking

This commit is contained in:
Christian Kamm 2022-02-23 10:09:01 +01:00
parent 8bc0416ef6
commit 5a4b6263ac
3 changed files with 65 additions and 12 deletions

View File

@ -1,5 +1,4 @@
use anchor_lang::prelude::*;
use anchor_spl::associated_token::AssociatedToken;
use anchor_spl::token::Mint;
use anchor_spl::token::Token;
use anchor_spl::token::TokenAccount;

View File

@ -1,5 +1,5 @@
use super::mango_group::*;
use crate::error::*;
use crate::state::*;
use anchor_lang::prelude::*;
use fixed::types::I80F48;
@ -13,7 +13,7 @@ pub struct IndexedPosition {
// todo: see https://github.com/blockworks-foundation/mango-v4/issues/1
// todo: how does ftx do this?
/// The deposit_index (if positive) or borrow_index (if negative) scaled position
pub value: I80F48,
pub indexed_value: I80F48,
/// index into MangoGroup.tokens
pub token_index: TokenIndex,
@ -23,7 +23,15 @@ pub struct IndexedPosition {
impl IndexedPosition {
pub fn is_active(&self) -> bool {
// maybe want to reserve token_index == 0?
self.value != I80F48::ZERO
self.indexed_value != I80F48::ZERO
}
pub fn native(&self, bank: &TokenBank) -> I80F48 {
if self.indexed_value.is_positive() {
self.indexed_value * bank.deposit_index
} else {
self.indexed_value * bank.borrow_index
}
}
}
@ -45,7 +53,7 @@ impl IndexedPositions {
pos = self.values.iter().position(|p| !p.is_active());
if let Some(i) = pos {
self.values[i] = IndexedPosition {
value: I80F48::ZERO,
indexed_value: I80F48::ZERO,
token_index: token_index as TokenIndex,
};
}

View File

@ -5,13 +5,14 @@ use super::IndexedPosition;
#[account(zero_copy)]
pub struct TokenBank {
/// native tokens deposited into or borrowed from this bank
pub deposits: u64,
pub borrows: u64,
/// the index used to scale the value of an IndexedPosition
/// TODO: should always be >= 0, add checks?
pub deposit_index: I80F48,
pub borrow_index: I80F48,
/// total deposits/borrows, for utilization
pub indexed_total_deposits: I80F48,
pub indexed_total_borrows: I80F48,
// todo: multi-leg interest
// pub optimal_util: I80F48,
// pub optimal_rate: I80F48,
@ -19,8 +20,53 @@ pub struct TokenBank {
}
impl TokenBank {
pub fn deposit(&mut self, position: &mut IndexedPosition, amount: u64) {
self.deposits = self.deposits.checked_add(amount).unwrap();
// TODO: adjust position.value according to the indexes
pub fn deposit(&mut self, position: &mut IndexedPosition, native_amount: u64) {
let mut native_amount = I80F48::from_num(native_amount);
let native_position = position.native(self);
if native_position.is_negative() {
if -native_position >= native_amount {
// pay back borrows only
let indexed_change = native_amount / self.borrow_index;
self.indexed_total_borrows -= indexed_change;
position.indexed_value += indexed_change;
return;
}
// pay back all borrows first
self.indexed_total_borrows += position.indexed_value; // position.value is negative
position.indexed_value = I80F48::ZERO;
native_amount += native_position;
}
// add to deposits
let indexed_change = native_amount / self.deposit_index;
self.indexed_total_deposits += indexed_change;
position.indexed_value += indexed_change;
}
pub fn withdraw(&mut self, position: &mut IndexedPosition, native_amount: u64) {
let mut native_amount = I80F48::from_num(native_amount);
let native_position = position.native(self);
if native_position.is_positive() {
if native_position >= native_amount {
// withdraw deposits only
let indexed_change = native_amount / self.deposit_index;
self.indexed_total_deposits -= indexed_change;
position.indexed_value -= indexed_change;
return;
}
// withdraw all deposits first
self.indexed_total_deposits -= position.indexed_value;
position.indexed_value = I80F48::ZERO;
native_amount -= native_position;
}
// add to borrows
let indexed_change = native_amount / self.borrow_index;
self.indexed_total_borrows += indexed_change;
position.indexed_value -= indexed_change;
}
}