Bank: store interest curve scale and target util separately (#755)
Allows for better configurability independent of the previous MAX_RATE concept
This commit is contained in:
parent
8110dd1566
commit
3b28856692
|
@ -596,6 +596,14 @@
|
|||
{
|
||||
"name": "flashLoanSwapFeeRate",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestCurveScaling",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestTargetUtilization",
|
||||
"type": "f32"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -930,6 +938,18 @@
|
|||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "interestCurveScalingOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "interestTargetUtilizationOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -7033,12 +7053,29 @@
|
|||
"name": "flashLoanSwapFeeRate",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestTargetUtilization",
|
||||
"docs": [
|
||||
"Target utilization: If actual utilization is higher, scale up interest.",
|
||||
"If it's lower, scale down interest (if possible)"
|
||||
],
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestCurveScaling",
|
||||
"docs": [
|
||||
"Current interest curve scaling, always >= 1.0",
|
||||
"",
|
||||
"Except when first migrating to having this field, then 0.0"
|
||||
],
|
||||
"type": "f64"
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
2092
|
||||
2080
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -11335,6 +11372,56 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateRateLogV2",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mangoGroup",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "tokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "rate0",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "util0",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "rate1",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "util1",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "maxRate",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "curveScaling",
|
||||
"type": "f64",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "targetUtilization",
|
||||
"type": "f32",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenLiqWithTokenLog",
|
||||
"fields": [
|
||||
|
|
|
@ -42,6 +42,8 @@ pub fn token_edit(
|
|||
token_conditional_swap_taker_fee_rate_opt: Option<f32>,
|
||||
token_conditional_swap_maker_fee_rate_opt: Option<f32>,
|
||||
flash_loan_swap_fee_rate_opt: Option<f32>,
|
||||
interest_curve_scaling_opt: Option<f32>,
|
||||
interest_target_utilization_opt: Option<f32>,
|
||||
) -> Result<()> {
|
||||
let group = ctx.accounts.group.load()?;
|
||||
|
||||
|
@ -339,6 +341,27 @@ pub fn token_edit(
|
|||
bank.flash_loan_swap_fee_rate = fee_rate;
|
||||
require_group_admin = true;
|
||||
}
|
||||
|
||||
if let Some(interest_curve_scaling) = interest_curve_scaling_opt {
|
||||
msg!(
|
||||
"Interest curve scaling old {:?}, new {:?}",
|
||||
bank.interest_curve_scaling,
|
||||
interest_curve_scaling
|
||||
);
|
||||
require_gte!(interest_curve_scaling, 1.0);
|
||||
bank.interest_curve_scaling = interest_curve_scaling.into();
|
||||
require_group_admin = true;
|
||||
}
|
||||
if let Some(interest_target_utilization) = interest_target_utilization_opt {
|
||||
msg!(
|
||||
"Interest target utilization old {:?}, new {:?}",
|
||||
bank.interest_target_utilization,
|
||||
interest_target_utilization
|
||||
);
|
||||
require_gte!(interest_target_utilization, 0.0);
|
||||
bank.interest_target_utilization = interest_target_utilization;
|
||||
require_group_admin = true;
|
||||
}
|
||||
}
|
||||
|
||||
// account constraint #1
|
||||
|
|
|
@ -38,6 +38,8 @@ pub fn token_register(
|
|||
token_conditional_swap_taker_fee_rate: f32,
|
||||
token_conditional_swap_maker_fee_rate: f32,
|
||||
flash_loan_swap_fee_rate: f32,
|
||||
interest_curve_scaling: f32,
|
||||
interest_target_utilization: f32,
|
||||
) -> Result<()> {
|
||||
// Require token 0 to be in the insurance token
|
||||
if token_index == INSURANCE_TOKEN_INDEX {
|
||||
|
@ -108,7 +110,9 @@ pub fn token_register(
|
|||
token_conditional_swap_taker_fee_rate,
|
||||
token_conditional_swap_maker_fee_rate,
|
||||
flash_loan_swap_fee_rate: flash_loan_swap_fee_rate,
|
||||
reserved: [0; 2092],
|
||||
interest_target_utilization,
|
||||
interest_curve_scaling: interest_curve_scaling.into(),
|
||||
reserved: [0; 2080],
|
||||
};
|
||||
|
||||
if let Ok(oracle_price) =
|
||||
|
|
|
@ -46,10 +46,10 @@ pub fn token_register_trustless(
|
|||
// 10% daily adjustment at 0% or 100% utilization
|
||||
adjustment_factor: I80F48::from_num(0.004),
|
||||
util0: I80F48::from_num(0.5),
|
||||
rate0: I80F48::from_num(0.072),
|
||||
rate0: I80F48::from_num(0.018),
|
||||
util1: I80F48::from_num(0.8),
|
||||
rate1: I80F48::from_num(0.2),
|
||||
max_rate: I80F48::from_num(2.0),
|
||||
rate1: I80F48::from_num(0.05),
|
||||
max_rate: I80F48::from_num(0.5),
|
||||
collected_fees_native: I80F48::ZERO,
|
||||
loan_origination_fee_rate: I80F48::from_num(0.0005),
|
||||
loan_fee_rate: I80F48::from_num(0.005),
|
||||
|
@ -80,9 +80,10 @@ pub fn token_register_trustless(
|
|||
token_conditional_swap_taker_fee_rate: 0.0005,
|
||||
token_conditional_swap_maker_fee_rate: 0.0005,
|
||||
flash_loan_swap_fee_rate: 0.0005,
|
||||
reserved: [0; 2092],
|
||||
interest_target_utilization: 0.5,
|
||||
interest_curve_scaling: 4.0,
|
||||
reserved: [0; 2080],
|
||||
};
|
||||
require_gt!(bank.max_rate, MINIMUM_MAX_RATE);
|
||||
|
||||
if let Ok(oracle_price) =
|
||||
bank.oracle_price(&AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?, None)
|
||||
|
|
|
@ -2,7 +2,7 @@ use anchor_lang::prelude::*;
|
|||
|
||||
use crate::accounts_ix::*;
|
||||
use crate::error::MangoError;
|
||||
use crate::logs::{UpdateIndexLog, UpdateRateLog};
|
||||
use crate::logs::{UpdateIndexLog, UpdateRateLogV2};
|
||||
use crate::state::HOUR;
|
||||
use crate::{
|
||||
accounts_zerocopy::{AccountInfoRef, LoadMutZeroCopyRef, LoadZeroCopyRef},
|
||||
|
@ -140,32 +140,54 @@ pub fn token_update_index_and_rate(ctx: Context<TokenUpdateIndexAndRate>) -> Res
|
|||
|
||||
// compute optimal rates, and max rate and set them on the bank
|
||||
{
|
||||
let some_bank = ctx.remaining_accounts[0].load::<Bank>()?;
|
||||
let mut some_bank = ctx.remaining_accounts[0].load_mut::<Bank>()?;
|
||||
|
||||
let diff_ts = I80F48::from_num(now_ts - some_bank.bank_rate_last_updated);
|
||||
|
||||
// update each hour
|
||||
if diff_ts > HOUR {
|
||||
let (rate0, rate1, max_rate) = some_bank.compute_rates();
|
||||
// First setup when new parameters are introduced
|
||||
if some_bank.interest_curve_scaling == 0.0 {
|
||||
let old_max_rate = 0.5;
|
||||
some_bank.interest_curve_scaling =
|
||||
some_bank.max_rate.to_num::<f64>() / old_max_rate;
|
||||
some_bank.interest_target_utilization = some_bank.util0.to_num();
|
||||
|
||||
emit!(UpdateRateLog {
|
||||
let descale_factor = I80F48::from_num(1.0 / some_bank.interest_curve_scaling);
|
||||
some_bank.rate0 *= descale_factor;
|
||||
some_bank.rate1 *= descale_factor;
|
||||
some_bank.max_rate *= descale_factor;
|
||||
}
|
||||
|
||||
some_bank.update_interest_rate_scaling();
|
||||
|
||||
let rate0 = some_bank.rate0;
|
||||
let rate1 = some_bank.rate1;
|
||||
let max_rate = some_bank.max_rate;
|
||||
let scaling = some_bank.interest_curve_scaling;
|
||||
let target_util = some_bank.interest_target_utilization;
|
||||
|
||||
emit!(UpdateRateLogV2 {
|
||||
mango_group: mint_info.group.key(),
|
||||
token_index: mint_info.token_index,
|
||||
rate0: rate0.to_bits(),
|
||||
util0: some_bank.util0.to_bits(),
|
||||
rate1: rate1.to_bits(),
|
||||
util1: some_bank.util1.to_bits(),
|
||||
max_rate: max_rate.to_bits(),
|
||||
curve_scaling: some_bank.interest_curve_scaling,
|
||||
target_utilization: some_bank.interest_target_utilization,
|
||||
});
|
||||
|
||||
drop(some_bank);
|
||||
|
||||
msg!("rate0 {}", rate0);
|
||||
msg!("rate1 {}", rate1);
|
||||
msg!("max_rate {}", max_rate);
|
||||
|
||||
// Apply the new parameters to all banks
|
||||
for ai in ctx.remaining_accounts.iter() {
|
||||
let mut bank = ai.load_mut::<Bank>()?;
|
||||
|
||||
bank.bank_rate_last_updated = now_ts;
|
||||
bank.interest_curve_scaling = scaling;
|
||||
bank.interest_target_utilization = target_util;
|
||||
bank.rate0 = rate0;
|
||||
bank.rate1 = rate1;
|
||||
bank.max_rate = max_rate;
|
||||
|
|
|
@ -148,6 +148,8 @@ pub mod mango_v4 {
|
|||
token_conditional_swap_taker_fee_rate: f32,
|
||||
token_conditional_swap_maker_fee_rate: f32,
|
||||
flash_loan_swap_fee_rate: f32,
|
||||
interest_curve_scaling: f32,
|
||||
interest_target_utilization: f32,
|
||||
) -> Result<()> {
|
||||
#[cfg(feature = "enable-gpl")]
|
||||
instructions::token_register(
|
||||
|
@ -175,6 +177,8 @@ pub mod mango_v4 {
|
|||
token_conditional_swap_taker_fee_rate,
|
||||
token_conditional_swap_maker_fee_rate,
|
||||
flash_loan_swap_fee_rate,
|
||||
interest_curve_scaling,
|
||||
interest_target_utilization,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -219,6 +223,8 @@ pub mod mango_v4 {
|
|||
token_conditional_swap_taker_fee_rate_opt: Option<f32>,
|
||||
token_conditional_swap_maker_fee_rate_opt: Option<f32>,
|
||||
flash_loan_swap_fee_rate_opt: Option<f32>,
|
||||
interest_curve_scaling_opt: Option<f32>,
|
||||
interest_target_utilization_opt: Option<f32>,
|
||||
) -> Result<()> {
|
||||
#[cfg(feature = "enable-gpl")]
|
||||
instructions::token_edit(
|
||||
|
@ -250,6 +256,8 @@ pub mod mango_v4 {
|
|||
token_conditional_swap_taker_fee_rate_opt,
|
||||
token_conditional_swap_maker_fee_rate_opt,
|
||||
flash_loan_swap_fee_rate_opt,
|
||||
interest_curve_scaling_opt,
|
||||
interest_target_utilization_opt,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -300,6 +300,20 @@ pub struct UpdateRateLog {
|
|||
pub max_rate: i128, // I80F48
|
||||
}
|
||||
|
||||
#[event]
|
||||
pub struct UpdateRateLogV2 {
|
||||
pub mango_group: Pubkey,
|
||||
pub token_index: u16,
|
||||
// contrary to v1 these do not have curve_scaling factored in!
|
||||
pub rate0: i128, // I80F48
|
||||
pub util0: i128, // I80F48
|
||||
pub rate1: i128, // I80F48
|
||||
pub util1: i128, // I80F48
|
||||
pub max_rate: i128, // I80F48
|
||||
pub curve_scaling: f64,
|
||||
pub target_utilization: f32,
|
||||
}
|
||||
|
||||
#[event]
|
||||
pub struct TokenLiqWithTokenLog {
|
||||
pub mango_group: Pubkey,
|
||||
|
|
|
@ -18,7 +18,6 @@ pub const DAY: i64 = 86400;
|
|||
pub const DAY_I80F48: I80F48 = I80F48::from_bits(86_400 * I80F48::ONE.to_bits());
|
||||
pub const ONE_BPS: I80F48 = I80F48::from_bits(28147497671);
|
||||
pub const YEAR_I80F48: I80F48 = I80F48::from_bits(31_536_000 * I80F48::ONE.to_bits());
|
||||
pub const MINIMUM_MAX_RATE: I80F48 = I80F48::from_bits(I80F48::ONE.to_bits() / 2);
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug)]
|
||||
|
@ -148,8 +147,17 @@ pub struct Bank {
|
|||
|
||||
pub flash_loan_swap_fee_rate: f32,
|
||||
|
||||
/// Target utilization: If actual utilization is higher, scale up interest.
|
||||
/// If it's lower, scale down interest (if possible)
|
||||
pub interest_target_utilization: f32,
|
||||
|
||||
/// Current interest curve scaling, always >= 1.0
|
||||
///
|
||||
/// Except when first migrating to having this field, then 0.0
|
||||
pub interest_curve_scaling: f64,
|
||||
|
||||
#[derivative(Debug = "ignore")]
|
||||
pub reserved: [u8; 2092],
|
||||
pub reserved: [u8; 2080],
|
||||
}
|
||||
const_assert_eq!(
|
||||
size_of::<Bank>(),
|
||||
|
@ -180,8 +188,9 @@ const_assert_eq!(
|
|||
+ 1
|
||||
+ 6
|
||||
+ 8
|
||||
+ 3 * 4
|
||||
+ 2092
|
||||
+ 4 * 4
|
||||
+ 8
|
||||
+ 2080
|
||||
);
|
||||
const_assert_eq!(size_of::<Bank>(), 3064);
|
||||
const_assert_eq!(size_of::<Bank>() % 8, 0);
|
||||
|
@ -211,9 +220,11 @@ impl Bank {
|
|||
indexed_deposits: I80F48::ZERO,
|
||||
indexed_borrows: I80F48::ZERO,
|
||||
collected_fees_native: I80F48::ZERO,
|
||||
fees_withdrawn: 0,
|
||||
dust: I80F48::ZERO,
|
||||
flash_loan_approved_amount: 0,
|
||||
flash_loan_token_account_initial: u64::MAX,
|
||||
net_borrows_in_window: 0,
|
||||
bump,
|
||||
bank_num,
|
||||
|
||||
|
@ -245,22 +256,24 @@ impl Bank {
|
|||
token_index: existing_bank.token_index,
|
||||
mint_decimals: existing_bank.mint_decimals,
|
||||
oracle_config: existing_bank.oracle_config,
|
||||
stable_price_model: StablePriceModel::default(),
|
||||
stable_price_model: existing_bank.stable_price_model,
|
||||
min_vault_to_deposits_ratio: existing_bank.min_vault_to_deposits_ratio,
|
||||
net_borrow_limit_per_window_quote: existing_bank.net_borrow_limit_per_window_quote,
|
||||
net_borrow_limit_window_size_ts: existing_bank.net_borrow_limit_window_size_ts,
|
||||
last_net_borrows_window_start_ts: existing_bank.last_net_borrows_window_start_ts,
|
||||
net_borrows_in_window: 0,
|
||||
borrow_weight_scale_start_quote: f64::MAX,
|
||||
deposit_weight_scale_start_quote: f64::MAX,
|
||||
reduce_only: 0,
|
||||
force_close: 0,
|
||||
borrow_weight_scale_start_quote: existing_bank.borrow_weight_scale_start_quote,
|
||||
deposit_weight_scale_start_quote: existing_bank.deposit_weight_scale_start_quote,
|
||||
reduce_only: existing_bank.reduce_only,
|
||||
force_close: existing_bank.force_close,
|
||||
padding: [0; 6],
|
||||
fees_withdrawn: 0,
|
||||
token_conditional_swap_taker_fee_rate: 0.0,
|
||||
token_conditional_swap_maker_fee_rate: 0.0,
|
||||
flash_loan_swap_fee_rate: 0.0,
|
||||
reserved: [0; 2092],
|
||||
token_conditional_swap_taker_fee_rate: existing_bank
|
||||
.token_conditional_swap_taker_fee_rate,
|
||||
token_conditional_swap_maker_fee_rate: existing_bank
|
||||
.token_conditional_swap_maker_fee_rate,
|
||||
flash_loan_swap_fee_rate: existing_bank.flash_loan_swap_fee_rate,
|
||||
interest_target_utilization: existing_bank.interest_target_utilization,
|
||||
interest_curve_scaling: existing_bank.interest_curve_scaling,
|
||||
reserved: [0; 2080],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,7 +283,7 @@ impl Bank {
|
|||
require_gte!(self.rate0, I80F48::ZERO);
|
||||
require_gte!(self.util1, I80F48::ZERO);
|
||||
require_gte!(self.rate1, I80F48::ZERO);
|
||||
require_gte!(self.max_rate, MINIMUM_MAX_RATE);
|
||||
require_gte!(self.max_rate, I80F48::ZERO);
|
||||
require_gte!(self.loan_fee_rate, 0.0);
|
||||
require_gte!(self.loan_origination_fee_rate, 0.0);
|
||||
require_gte!(self.maint_asset_weight, 0.0);
|
||||
|
@ -286,6 +299,8 @@ impl Bank {
|
|||
require_gte!(self.token_conditional_swap_taker_fee_rate, 0.0);
|
||||
require_gte!(self.token_conditional_swap_maker_fee_rate, 0.0);
|
||||
require_gte!(self.flash_loan_swap_fee_rate, 0.0);
|
||||
require_gte!(self.interest_curve_scaling, 1.0);
|
||||
require_gte!(self.interest_target_utilization, 0.0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -795,6 +810,7 @@ impl Bank {
|
|||
self.util1,
|
||||
self.rate1,
|
||||
self.max_rate,
|
||||
self.interest_curve_scaling,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -808,8 +824,9 @@ impl Bank {
|
|||
util1: I80F48,
|
||||
rate1: I80F48,
|
||||
max_rate: I80F48,
|
||||
scaling: f64,
|
||||
) -> I80F48 {
|
||||
if utilization <= util0 {
|
||||
let v = if utilization <= util0 {
|
||||
let slope = rate0 / util0;
|
||||
slope * utilization
|
||||
} else if utilization <= util1 {
|
||||
|
@ -820,6 +837,13 @@ impl Bank {
|
|||
let extra_util = utilization - util1;
|
||||
let slope = (max_rate - rate1) / (I80F48::ONE - util1);
|
||||
rate1 + slope * extra_util
|
||||
};
|
||||
|
||||
// scaling will be 0 when it's introduced
|
||||
if scaling == 0.0 {
|
||||
v
|
||||
} else {
|
||||
v * I80F48::from_num(scaling)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -855,34 +879,23 @@ impl Bank {
|
|||
}
|
||||
|
||||
// computes new optimal rates and max rate
|
||||
pub fn compute_rates(&self) -> (I80F48, I80F48, I80F48) {
|
||||
// interest rate legs 2 and 3 are seen as punitive legs, encouraging utilization to move towards optimal utilization
|
||||
// lets choose util0 as optimal utilization and 0 to utli0 as the leg where we want the utlization to preferably be
|
||||
let optimal_util = self.util0;
|
||||
pub fn update_interest_rate_scaling(&mut self) {
|
||||
// Interest increases above target_util, decreases below
|
||||
let target_util = self.interest_target_utilization as f64;
|
||||
|
||||
// use avg_utilization and not instantaneous_utilization so that rates cannot be manipulated easily
|
||||
let avg_util = self.avg_utilization;
|
||||
let avg_util = self.avg_utilization.to_num::<f64>();
|
||||
|
||||
// move rates up when utilization is above optimal utilization, and vice versa
|
||||
// util factor is between -1 (avg util = 0) and +1 (avg util = 100%)
|
||||
let util_factor = if avg_util > optimal_util {
|
||||
(avg_util - optimal_util) / (I80F48::ONE - optimal_util)
|
||||
let util_factor = if avg_util > target_util {
|
||||
(avg_util - target_util) / (1.0 - target_util)
|
||||
} else {
|
||||
(avg_util - optimal_util) / optimal_util
|
||||
(avg_util - target_util) / target_util
|
||||
};
|
||||
let adjustment = I80F48::ONE + self.adjustment_factor * util_factor;
|
||||
let adjustment = 1.0 + self.adjustment_factor.to_num::<f64>() * util_factor;
|
||||
|
||||
// 1. irrespective of which leg current utilization is in, update all rates
|
||||
// 2. only update rates as long as new adjusted rates are above MINIMUM_MAX_RATE,
|
||||
// since we don't want to fall to such low rates that it would take a long time to
|
||||
// recover to high rates if utilization suddently increases to a high value
|
||||
if (self.max_rate * adjustment) > MINIMUM_MAX_RATE {
|
||||
(
|
||||
(self.rate0 * adjustment),
|
||||
(self.rate1 * adjustment),
|
||||
(self.max_rate * adjustment),
|
||||
)
|
||||
} else {
|
||||
(self.rate0, self.rate1, self.max_rate)
|
||||
}
|
||||
self.interest_curve_scaling = (self.interest_curve_scaling * adjustment).max(1.0)
|
||||
}
|
||||
|
||||
pub fn oracle_price(
|
||||
|
|
|
@ -997,6 +997,8 @@ impl ClientInstruction for TokenRegisterInstruction {
|
|||
token_conditional_swap_taker_fee_rate: 0.0,
|
||||
token_conditional_swap_maker_fee_rate: 0.0,
|
||||
flash_loan_swap_fee_rate: 0.0,
|
||||
interest_curve_scaling: 1.0,
|
||||
interest_target_utilization: 0.5,
|
||||
};
|
||||
|
||||
let bank = Pubkey::find_program_address(
|
||||
|
@ -1241,6 +1243,8 @@ pub fn token_edit_instruction_default() -> mango_v4::instruction::TokenEdit {
|
|||
token_conditional_swap_taker_fee_rate_opt: None,
|
||||
token_conditional_swap_maker_fee_rate_opt: None,
|
||||
flash_loan_swap_fee_rate_opt: None,
|
||||
interest_curve_scaling_opt: None,
|
||||
interest_target_utilization_opt: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -410,6 +410,8 @@ export class MangoClient {
|
|||
params.tokenConditionalSwapTakerFeeRate,
|
||||
params.tokenConditionalSwapMakerFeeRate,
|
||||
params.flashLoanSwapFeeRate,
|
||||
params.interestCurveScaling,
|
||||
params.interestTargetUtilization,
|
||||
)
|
||||
.accounts({
|
||||
group: group.publicKey,
|
||||
|
@ -485,6 +487,8 @@ export class MangoClient {
|
|||
params.tokenConditionalSwapTakerFeeRate,
|
||||
params.tokenConditionalSwapMakerFeeRate,
|
||||
params.flashLoanSwapFeeRate,
|
||||
params.interestCurveScaling,
|
||||
params.interestTargetUtilization,
|
||||
)
|
||||
.accounts({
|
||||
group: group.publicKey,
|
||||
|
|
|
@ -25,6 +25,8 @@ export interface TokenRegisterParams {
|
|||
tokenConditionalSwapTakerFeeRate: number;
|
||||
tokenConditionalSwapMakerFeeRate: number;
|
||||
flashLoanSwapFeeRate: number;
|
||||
interestCurveScaling: number;
|
||||
interestTargetUtilization: number;
|
||||
}
|
||||
|
||||
export const DefaultTokenRegisterParams: TokenRegisterParams = {
|
||||
|
@ -35,10 +37,10 @@ export const DefaultTokenRegisterParams: TokenRegisterParams = {
|
|||
groupInsuranceFund: false,
|
||||
interestRateParams: {
|
||||
util0: 0.5,
|
||||
rate0: 0.072,
|
||||
rate0: 0.018,
|
||||
util1: 0.8,
|
||||
rate1: 0.2,
|
||||
maxRate: 2,
|
||||
rate1: 0.05,
|
||||
maxRate: 0.5,
|
||||
adjustmentFactor: 0.004,
|
||||
},
|
||||
loanFeeRate: 0.0005,
|
||||
|
@ -60,6 +62,8 @@ export const DefaultTokenRegisterParams: TokenRegisterParams = {
|
|||
tokenConditionalSwapTakerFeeRate: 0.0005,
|
||||
tokenConditionalSwapMakerFeeRate: 0.0005,
|
||||
flashLoanSwapFeeRate: 0.0005,
|
||||
interestCurveScaling: 4.0,
|
||||
interestTargetUtilization: 0.5,
|
||||
};
|
||||
|
||||
export interface TokenEditParams {
|
||||
|
@ -90,6 +94,8 @@ export interface TokenEditParams {
|
|||
tokenConditionalSwapTakerFeeRate: number | null;
|
||||
tokenConditionalSwapMakerFeeRate: number | null;
|
||||
flashLoanSwapFeeRate: number | null;
|
||||
interestCurveScaling: number | null;
|
||||
interestTargetUtilization: number | null;
|
||||
}
|
||||
|
||||
export const NullTokenEditParams: TokenEditParams = {
|
||||
|
@ -120,6 +126,8 @@ export const NullTokenEditParams: TokenEditParams = {
|
|||
tokenConditionalSwapTakerFeeRate: null,
|
||||
tokenConditionalSwapMakerFeeRate: null,
|
||||
flashLoanSwapFeeRate: null,
|
||||
interestCurveScaling: null,
|
||||
interestTargetUtilization: null,
|
||||
};
|
||||
|
||||
export interface PerpEditParams {
|
||||
|
|
|
@ -596,6 +596,14 @@ export type MangoV4 = {
|
|||
{
|
||||
"name": "flashLoanSwapFeeRate",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestCurveScaling",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestTargetUtilization",
|
||||
"type": "f32"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -930,6 +938,18 @@ export type MangoV4 = {
|
|||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "interestCurveScalingOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "interestTargetUtilizationOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -7033,12 +7053,29 @@ export type MangoV4 = {
|
|||
"name": "flashLoanSwapFeeRate",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestTargetUtilization",
|
||||
"docs": [
|
||||
"Target utilization: If actual utilization is higher, scale up interest.",
|
||||
"If it's lower, scale down interest (if possible)"
|
||||
],
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestCurveScaling",
|
||||
"docs": [
|
||||
"Current interest curve scaling, always >= 1.0",
|
||||
"",
|
||||
"Except when first migrating to having this field, then 0.0"
|
||||
],
|
||||
"type": "f64"
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
2092
|
||||
2080
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -11335,6 +11372,56 @@ export type MangoV4 = {
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateRateLogV2",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mangoGroup",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "tokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "rate0",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "util0",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "rate1",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "util1",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "maxRate",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "curveScaling",
|
||||
"type": "f64",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "targetUtilization",
|
||||
"type": "f32",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenLiqWithTokenLog",
|
||||
"fields": [
|
||||
|
@ -13699,6 +13786,14 @@ export const IDL: MangoV4 = {
|
|||
{
|
||||
"name": "flashLoanSwapFeeRate",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestCurveScaling",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestTargetUtilization",
|
||||
"type": "f32"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -14033,6 +14128,18 @@ export const IDL: MangoV4 = {
|
|||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "interestCurveScalingOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "interestTargetUtilizationOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -20136,12 +20243,29 @@ export const IDL: MangoV4 = {
|
|||
"name": "flashLoanSwapFeeRate",
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestTargetUtilization",
|
||||
"docs": [
|
||||
"Target utilization: If actual utilization is higher, scale up interest.",
|
||||
"If it's lower, scale down interest (if possible)"
|
||||
],
|
||||
"type": "f32"
|
||||
},
|
||||
{
|
||||
"name": "interestCurveScaling",
|
||||
"docs": [
|
||||
"Current interest curve scaling, always >= 1.0",
|
||||
"",
|
||||
"Except when first migrating to having this field, then 0.0"
|
||||
],
|
||||
"type": "f64"
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
2092
|
||||
2080
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -24438,6 +24562,56 @@ export const IDL: MangoV4 = {
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateRateLogV2",
|
||||
"fields": [
|
||||
{
|
||||
"name": "mangoGroup",
|
||||
"type": "publicKey",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "tokenIndex",
|
||||
"type": "u16",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "rate0",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "util0",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "rate1",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "util1",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "maxRate",
|
||||
"type": "i128",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "curveScaling",
|
||||
"type": "f64",
|
||||
"index": false
|
||||
},
|
||||
{
|
||||
"name": "targetUtilization",
|
||||
"type": "f32",
|
||||
"index": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TokenLiqWithTokenLog",
|
||||
"fields": [
|
||||
|
|
Loading…
Reference in New Issue