Add loan amount to WithdrawLoanLog. Add withdraw loan logging to toke… (#599)
* Add loan amount to WithdrawLoanLog. Add withdraw loan logging to token_force_close_borrows_with_token * Address review comments.
This commit is contained in:
parent
7803f1dc9d
commit
defbd8c2b1
|
@ -9,7 +9,7 @@ use crate::state::*;
|
|||
use super::{apply_settle_changes, OpenOrdersAmounts, OpenOrdersSlim};
|
||||
use crate::accounts_ix::*;
|
||||
use crate::logs::Serum3OpenOrdersBalanceLogV2;
|
||||
use crate::logs::{LoanOriginationFeeInstruction, WithdrawLoanOriginationFeeLog};
|
||||
use crate::logs::{LoanOriginationFeeInstruction, WithdrawLoanLog};
|
||||
|
||||
/// Settling means moving free funds from the serum3 open orders account
|
||||
/// back into the mango account wallet.
|
||||
|
@ -171,17 +171,18 @@ pub fn charge_loan_origination_fees(
|
|||
// now that the loan is actually materialized, charge the loan origination fee
|
||||
// note: the withdraw has already happened while placing the order
|
||||
let base_token_account = account.token_position_mut(base_bank.token_index)?.0;
|
||||
let (_, fee) = base_bank.withdraw_loan_origination_fee(
|
||||
let withdraw_result = base_bank.withdraw_loan_origination_fee(
|
||||
base_token_account,
|
||||
actualized_base_loan,
|
||||
now_ts,
|
||||
)?;
|
||||
|
||||
emit!(WithdrawLoanOriginationFeeLog {
|
||||
emit!(WithdrawLoanLog {
|
||||
mango_group: *group_pubkey,
|
||||
mango_account: *account_pubkey,
|
||||
token_index: base_bank.token_index,
|
||||
loan_origination_fee: fee.to_bits(),
|
||||
loan_amount: withdraw_result.loan_amount.to_bits(),
|
||||
loan_origination_fee: withdraw_result.loan_origination_fee.to_bits(),
|
||||
instruction: LoanOriginationFeeInstruction::Serum3SettleFunds,
|
||||
});
|
||||
}
|
||||
|
@ -199,17 +200,18 @@ pub fn charge_loan_origination_fees(
|
|||
// now that the loan is actually materialized, charge the loan origination fee
|
||||
// note: the withdraw has already happened while placing the order
|
||||
let quote_token_account = account.token_position_mut(quote_bank.token_index)?.0;
|
||||
let (_, fee) = quote_bank.withdraw_loan_origination_fee(
|
||||
let withdraw_result = quote_bank.withdraw_loan_origination_fee(
|
||||
quote_token_account,
|
||||
actualized_quote_loan,
|
||||
now_ts,
|
||||
)?;
|
||||
|
||||
emit!(WithdrawLoanOriginationFeeLog {
|
||||
emit!(WithdrawLoanLog {
|
||||
mango_group: *group_pubkey,
|
||||
mango_account: *account_pubkey,
|
||||
token_index: quote_bank.token_index,
|
||||
loan_origination_fee: fee.to_bits(),
|
||||
loan_amount: withdraw_result.loan_amount.to_bits(),
|
||||
loan_origination_fee: withdraw_result.loan_origination_fee.to_bits(),
|
||||
instruction: LoanOriginationFeeInstruction::Serum3SettleFunds,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ pub fn token_force_close_borrows_with_token(
|
|||
liab_bank.deposit_with_dusting(liqee_liab_position, liab_transfer, now_ts)?;
|
||||
let liqee_liab_indexed_position = liqee_liab_position.indexed_position;
|
||||
|
||||
let (liqor_liab_active, loan_origination_fee) =
|
||||
let liqor_liab_withdraw_result =
|
||||
liab_bank.withdraw_with_fee(liqor_liab_position, liab_transfer, now_ts)?;
|
||||
let liqor_liab_indexed_position = liqor_liab_position.indexed_position;
|
||||
let liqee_liab_native_after = liqee_liab_position.native(liab_bank);
|
||||
|
@ -174,6 +174,12 @@ pub fn token_force_close_borrows_with_token(
|
|||
fee_factor: fee_factor.to_bits(),
|
||||
});
|
||||
|
||||
// liqor should never have a borrow
|
||||
require!(
|
||||
liqor_liab_withdraw_result.loan_amount.is_zero(),
|
||||
MangoError::SomeError
|
||||
);
|
||||
|
||||
let liqee_health_cache = new_health_cache(&liqee.borrow(), &mut account_retriever)
|
||||
.context("create liqee health cache")?;
|
||||
let liqee_liq_end_health = liqee_health_cache.health(HealthType::LiquidationEnd);
|
||||
|
@ -191,7 +197,7 @@ pub fn token_force_close_borrows_with_token(
|
|||
if !liqor_asset_active {
|
||||
liqor.deactivate_token_position_and_log(liqor_asset_raw_index, liqor_key);
|
||||
}
|
||||
if !liqor_liab_active {
|
||||
if !liqor_liab_withdraw_result.position_is_active {
|
||||
liqor.deactivate_token_position_and_log(liqor_liab_raw_index, liqor_key)
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,8 +9,7 @@ use crate::state::*;
|
|||
|
||||
use crate::accounts_ix::*;
|
||||
use crate::logs::{
|
||||
LoanOriginationFeeInstruction, TokenBalanceLog, TokenLiqBankruptcyLog,
|
||||
WithdrawLoanOriginationFeeLog,
|
||||
LoanOriginationFeeInstruction, TokenBalanceLog, TokenLiqBankruptcyLog, WithdrawLoanLog,
|
||||
};
|
||||
|
||||
pub fn token_liq_bankruptcy(
|
||||
|
@ -149,7 +148,7 @@ pub fn token_liq_bankruptcy(
|
|||
// transfer liab from liqee to liqor
|
||||
let (liqor_liab, liqor_liab_raw_token_index, _) =
|
||||
liqor.ensure_token_position(liab_token_index)?;
|
||||
let (liqor_liab_active, loan_origination_fee) =
|
||||
let liqor_liab_withdraw_result =
|
||||
liab_bank.withdraw_with_fee(liqor_liab, liab_transfer, now_ts)?;
|
||||
|
||||
// liqor liab
|
||||
|
@ -169,12 +168,16 @@ pub fn token_liq_bankruptcy(
|
|||
require!(liqor_health >= 0, MangoError::HealthMustBePositive);
|
||||
}
|
||||
|
||||
if loan_origination_fee.is_positive() {
|
||||
emit!(WithdrawLoanOriginationFeeLog {
|
||||
if liqor_liab_withdraw_result
|
||||
.loan_origination_fee
|
||||
.is_positive()
|
||||
{
|
||||
emit!(WithdrawLoanLog {
|
||||
mango_group: ctx.accounts.group.key(),
|
||||
mango_account: ctx.accounts.liqor.key(),
|
||||
token_index: liab_token_index,
|
||||
loan_origination_fee: loan_origination_fee.to_bits(),
|
||||
loan_amount: liqor_liab_withdraw_result.loan_amount.to_bits(),
|
||||
loan_origination_fee: liqor_liab_withdraw_result.loan_origination_fee.to_bits(),
|
||||
instruction: LoanOriginationFeeInstruction::LiqTokenBankruptcy
|
||||
});
|
||||
}
|
||||
|
@ -185,7 +188,7 @@ pub fn token_liq_bankruptcy(
|
|||
ctx.accounts.liqor.key(),
|
||||
);
|
||||
}
|
||||
if !liqor_liab_active {
|
||||
if !liqor_liab_withdraw_result.position_is_active {
|
||||
liqor.deactivate_token_position_and_log(
|
||||
liqor_liab_raw_token_index,
|
||||
ctx.accounts.liqor.key(),
|
||||
|
|
|
@ -5,8 +5,7 @@ use crate::accounts_ix::*;
|
|||
use crate::error::*;
|
||||
use crate::health::*;
|
||||
use crate::logs::{
|
||||
LoanOriginationFeeInstruction, TokenBalanceLog, TokenLiqWithTokenLog,
|
||||
WithdrawLoanOriginationFeeLog,
|
||||
LoanOriginationFeeInstruction, TokenBalanceLog, TokenLiqWithTokenLog, WithdrawLoanLog,
|
||||
};
|
||||
use crate::state::*;
|
||||
|
||||
|
@ -221,7 +220,7 @@ pub(crate) fn liquidation_action(
|
|||
|
||||
let (liqor_liab_position, liqor_liab_raw_index, _) =
|
||||
liqor.ensure_token_position(liab_token_index)?;
|
||||
let (liqor_liab_active, loan_origination_fee) =
|
||||
let liqor_liab_withdraw_result =
|
||||
liab_bank.withdraw_with_fee(liqor_liab_position, liab_transfer, now_ts)?;
|
||||
let liqor_liab_indexed_position = liqor_liab_position.indexed_position;
|
||||
let liqee_liab_native_after = liqee_liab_position.native(liab_bank);
|
||||
|
@ -289,12 +288,16 @@ pub(crate) fn liquidation_action(
|
|||
borrow_index: liab_bank.borrow_index.to_bits(),
|
||||
});
|
||||
|
||||
if loan_origination_fee.is_positive() {
|
||||
emit!(WithdrawLoanOriginationFeeLog {
|
||||
if liqor_liab_withdraw_result
|
||||
.loan_origination_fee
|
||||
.is_positive()
|
||||
{
|
||||
emit!(WithdrawLoanLog {
|
||||
mango_group: liqee.fixed.group,
|
||||
mango_account: liqor_key,
|
||||
token_index: liab_token_index,
|
||||
loan_origination_fee: loan_origination_fee.to_bits(),
|
||||
loan_amount: liqor_liab_withdraw_result.loan_amount.to_bits(),
|
||||
loan_origination_fee: liqor_liab_withdraw_result.loan_origination_fee.to_bits(),
|
||||
instruction: LoanOriginationFeeInstruction::LiqTokenWithToken
|
||||
});
|
||||
}
|
||||
|
@ -309,7 +312,7 @@ pub(crate) fn liquidation_action(
|
|||
if !liqor_asset_active {
|
||||
liqor.deactivate_token_position_and_log(liqor_asset_raw_index, liqor_key);
|
||||
}
|
||||
if !liqor_liab_active {
|
||||
if !liqor_liab_withdraw_result.position_is_active {
|
||||
liqor.deactivate_token_position_and_log(liqor_liab_raw_index, liqor_key)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,7 @@ use anchor_spl::token;
|
|||
use fixed::types::I80F48;
|
||||
|
||||
use crate::accounts_ix::*;
|
||||
use crate::logs::{
|
||||
LoanOriginationFeeInstruction, TokenBalanceLog, WithdrawLoanOriginationFeeLog, WithdrawLog,
|
||||
};
|
||||
use crate::logs::{LoanOriginationFeeInstruction, TokenBalanceLog, WithdrawLoanLog, WithdrawLog};
|
||||
|
||||
pub fn token_withdraw(ctx: Context<TokenWithdraw>, amount: u64, allow_borrow: bool) -> Result<()> {
|
||||
require_msg!(amount > 0, "withdraw amount must be positive");
|
||||
|
@ -65,7 +63,7 @@ pub fn token_withdraw(ctx: Context<TokenWithdraw>, amount: u64, allow_borrow: bo
|
|||
)?;
|
||||
|
||||
// Update the bank and position
|
||||
let (position_is_active, loan_origination_fee) = bank.withdraw_with_fee(
|
||||
let withdraw_result = bank.withdraw_with_fee(
|
||||
position,
|
||||
amount_i80f48,
|
||||
Clock::get()?.unix_timestamp.try_into().unwrap(),
|
||||
|
@ -116,7 +114,7 @@ pub fn token_withdraw(ctx: Context<TokenWithdraw>, amount: u64, allow_borrow: bo
|
|||
// remaining_accounts for all banks/oracles, including the account that will now be
|
||||
// deactivated.
|
||||
//
|
||||
if !position_is_active {
|
||||
if !withdraw_result.position_is_active {
|
||||
account.deactivate_token_position_and_log(raw_token_index, ctx.accounts.account.key());
|
||||
}
|
||||
|
||||
|
@ -129,12 +127,13 @@ pub fn token_withdraw(ctx: Context<TokenWithdraw>, amount: u64, allow_borrow: bo
|
|||
price: oracle_price.to_bits(),
|
||||
});
|
||||
|
||||
if loan_origination_fee.is_positive() {
|
||||
emit!(WithdrawLoanOriginationFeeLog {
|
||||
if withdraw_result.loan_origination_fee.is_positive() {
|
||||
emit!(WithdrawLoanLog {
|
||||
mango_group: ctx.accounts.group.key(),
|
||||
mango_account: ctx.accounts.account.key(),
|
||||
token_index,
|
||||
loan_origination_fee: loan_origination_fee.to_bits(),
|
||||
loan_amount: withdraw_result.loan_amount.to_bits(),
|
||||
loan_origination_fee: withdraw_result.loan_origination_fee.to_bits(),
|
||||
instruction: LoanOriginationFeeInstruction::TokenWithdraw,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -257,6 +257,16 @@ pub struct WithdrawLoanOriginationFeeLog {
|
|||
pub instruction: LoanOriginationFeeInstruction,
|
||||
}
|
||||
|
||||
#[event]
|
||||
pub struct WithdrawLoanLog {
|
||||
pub mango_group: Pubkey,
|
||||
pub mango_account: Pubkey,
|
||||
pub token_index: u16,
|
||||
pub loan_amount: i128,
|
||||
pub loan_origination_fee: i128,
|
||||
pub instruction: LoanOriginationFeeInstruction,
|
||||
}
|
||||
|
||||
#[event]
|
||||
pub struct TokenLiqBankruptcyLog {
|
||||
pub mango_group: Pubkey,
|
||||
|
|
|
@ -170,6 +170,12 @@ const_assert_eq!(
|
|||
const_assert_eq!(size_of::<Bank>(), 3064);
|
||||
const_assert_eq!(size_of::<Bank>() % 8, 0);
|
||||
|
||||
pub struct WithdrawResult {
|
||||
pub position_is_active: bool,
|
||||
pub loan_origination_fee: I80F48,
|
||||
pub loan_amount: I80F48,
|
||||
}
|
||||
|
||||
impl Bank {
|
||||
pub fn from_existing_bank(
|
||||
existing_bank: &Bank,
|
||||
|
@ -403,13 +409,15 @@ impl Bank {
|
|||
native_amount: I80F48,
|
||||
now_ts: u64,
|
||||
) -> Result<bool> {
|
||||
let (position_is_active, _) = self.withdraw_internal_wrapper(
|
||||
let position_is_active = self
|
||||
.withdraw_internal_wrapper(
|
||||
position,
|
||||
native_amount,
|
||||
false,
|
||||
!position.is_in_use(),
|
||||
now_ts,
|
||||
)?;
|
||||
)?
|
||||
.position_is_active;
|
||||
|
||||
Ok(position_is_active)
|
||||
}
|
||||
|
@ -424,7 +432,7 @@ impl Bank {
|
|||
now_ts: u64,
|
||||
) -> Result<bool> {
|
||||
self.withdraw_internal_wrapper(position, native_amount, false, true, now_ts)
|
||||
.map(|(not_dusted, _)| not_dusted || position.is_in_use())
|
||||
.map(|withdraw_result| withdraw_result.position_is_active || position.is_in_use())
|
||||
}
|
||||
|
||||
/// Withdraws `native_amount` while applying the loan origination fee if a borrow is created.
|
||||
|
@ -440,7 +448,7 @@ impl Bank {
|
|||
position: &mut TokenPosition,
|
||||
native_amount: I80F48,
|
||||
now_ts: u64,
|
||||
) -> Result<(bool, I80F48)> {
|
||||
) -> Result<WithdrawResult> {
|
||||
self.withdraw_internal_wrapper(position, native_amount, true, !position.is_in_use(), now_ts)
|
||||
}
|
||||
|
||||
|
@ -452,7 +460,7 @@ impl Bank {
|
|||
with_loan_origination_fee: bool,
|
||||
allow_dusting: bool,
|
||||
now_ts: u64,
|
||||
) -> Result<(bool, I80F48)> {
|
||||
) -> Result<WithdrawResult> {
|
||||
let opening_indexed_position = position.indexed_position;
|
||||
let res = self.withdraw_internal(
|
||||
position,
|
||||
|
@ -473,7 +481,7 @@ impl Bank {
|
|||
with_loan_origination_fee: bool,
|
||||
allow_dusting: bool,
|
||||
now_ts: u64,
|
||||
) -> Result<(bool, I80F48)> {
|
||||
) -> Result<WithdrawResult> {
|
||||
require_gte!(native_amount, 0);
|
||||
let native_position = position.native(self);
|
||||
|
||||
|
@ -486,13 +494,21 @@ impl Bank {
|
|||
self.dust += new_native_position;
|
||||
self.indexed_deposits -= position.indexed_position;
|
||||
position.indexed_position = I80F48::ZERO;
|
||||
return Ok((false, I80F48::ZERO));
|
||||
return Ok(WithdrawResult {
|
||||
position_is_active: false,
|
||||
loan_origination_fee: I80F48::ZERO,
|
||||
loan_amount: I80F48::ZERO,
|
||||
});
|
||||
} else {
|
||||
// withdraw some deposits leaving a positive balance
|
||||
let indexed_change = native_amount / self.deposit_index;
|
||||
self.indexed_deposits -= indexed_change;
|
||||
position.indexed_position -= indexed_change;
|
||||
return Ok((true, I80F48::ZERO));
|
||||
return Ok(WithdrawResult {
|
||||
position_is_active: true,
|
||||
loan_origination_fee: I80F48::ZERO,
|
||||
loan_amount: I80F48::ZERO,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,7 +535,11 @@ impl Bank {
|
|||
// withdraws and not borrows
|
||||
self.update_net_borrows(native_amount, now_ts);
|
||||
|
||||
Ok((true, loan_origination_fee))
|
||||
Ok(WithdrawResult {
|
||||
position_is_active: true,
|
||||
loan_origination_fee,
|
||||
loan_amount: native_amount,
|
||||
})
|
||||
}
|
||||
|
||||
// withdraw the loan origination fee for a borrow that happenend earlier
|
||||
|
@ -528,19 +548,26 @@ impl Bank {
|
|||
position: &mut TokenPosition,
|
||||
already_borrowed_native_amount: I80F48,
|
||||
now_ts: u64,
|
||||
) -> Result<(bool, I80F48)> {
|
||||
) -> Result<WithdrawResult> {
|
||||
let loan_origination_fee = self.loan_origination_fee_rate * already_borrowed_native_amount;
|
||||
self.collected_fees_native += loan_origination_fee;
|
||||
|
||||
let (position_is_active, _) = self.withdraw_internal_wrapper(
|
||||
let position_is_active = self
|
||||
.withdraw_internal_wrapper(
|
||||
position,
|
||||
loan_origination_fee,
|
||||
false,
|
||||
!position.is_in_use(),
|
||||
now_ts,
|
||||
)?;
|
||||
)?
|
||||
.position_is_active;
|
||||
|
||||
Ok((position_is_active, loan_origination_fee))
|
||||
Ok(WithdrawResult {
|
||||
position_is_active,
|
||||
loan_origination_fee,
|
||||
// To avoid double counting of loans return loan_amount of 0 here (as the loan_amount has already been returned earlier with loan_origination_fee == 0)
|
||||
loan_amount: I80F48::ZERO,
|
||||
})
|
||||
}
|
||||
|
||||
/// Change a position without applying the loan origination fee
|
||||
|
@ -563,9 +590,13 @@ impl Bank {
|
|||
position: &mut TokenPosition,
|
||||
native_amount: I80F48,
|
||||
now_ts: u64,
|
||||
) -> Result<(bool, I80F48)> {
|
||||
) -> Result<WithdrawResult> {
|
||||
if native_amount >= 0 {
|
||||
Ok((self.deposit(position, native_amount, now_ts)?, I80F48::ZERO))
|
||||
Ok(WithdrawResult {
|
||||
position_is_active: self.deposit(position, native_amount, now_ts)?,
|
||||
loan_origination_fee: I80F48::ZERO,
|
||||
loan_amount: I80F48::ZERO,
|
||||
})
|
||||
} else {
|
||||
self.withdraw_with_fee(position, -native_amount, now_ts)
|
||||
}
|
||||
|
@ -948,7 +979,9 @@ mod tests {
|
|||
let change = I80F48::from(change);
|
||||
let dummy_now_ts = 1 as u64;
|
||||
let dummy_price = I80F48::ZERO;
|
||||
let (is_active, _) = bank.change_with_fee(&mut account, change, dummy_now_ts)?;
|
||||
let is_active = bank
|
||||
.change_with_fee(&mut account, change, dummy_now_ts)?
|
||||
.position_is_active;
|
||||
|
||||
let mut expected_native = start_native + change;
|
||||
if expected_native >= 0.0 && expected_native < 1.0 && !is_in_use {
|
||||
|
|
Loading…
Reference in New Issue