Configurable interest rate for 0% utilization (#848)
This commit is contained in:
parent
637b43fec4
commit
18729cf04c
|
@ -623,6 +623,10 @@
|
|||
{
|
||||
"name": "depositLimit",
|
||||
"type": "u64"
|
||||
},
|
||||
{
|
||||
"name": "zeroUtilRate",
|
||||
"type": "f32"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1021,6 +1025,12 @@
|
|||
"type": {
|
||||
"option": "u64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "zeroUtilRateOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -7137,6 +7147,16 @@
|
|||
},
|
||||
{
|
||||
"name": "util0",
|
||||
"docs": [
|
||||
"The unscaled borrow interest curve is defined as continuous piecewise linear with the points:",
|
||||
"",
|
||||
"- 0% util: zero_util_rate",
|
||||
"- util0% util: rate0",
|
||||
"- util1% util: rate1",
|
||||
"- 100% util: max_rate",
|
||||
"",
|
||||
"The final rate is this unscaled curve multiplied by interest_curve_scaling."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -7161,6 +7181,12 @@
|
|||
},
|
||||
{
|
||||
"name": "maxRate",
|
||||
"docs": [
|
||||
"the 100% utilization rate",
|
||||
"",
|
||||
"This isn't the max_rate, since this still gets scaled by interest_curve_scaling,",
|
||||
"which is >=1."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -7421,12 +7447,23 @@
|
|||
],
|
||||
"type": "u64"
|
||||
},
|
||||
{
|
||||
"name": "zeroUtilRate",
|
||||
"docs": [
|
||||
"The unscaled borrow interest curve point for zero utilization.",
|
||||
"",
|
||||
"See util0, rate0, util1, rate1, max_rate"
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1968
|
||||
1952
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ pub fn token_edit(
|
|||
maint_weight_shift_abort: bool,
|
||||
set_fallback_oracle: bool,
|
||||
deposit_limit_opt: Option<u64>,
|
||||
zero_util_rate: Option<f32>,
|
||||
) -> Result<()> {
|
||||
let group = ctx.accounts.group.load()?;
|
||||
|
||||
|
@ -462,6 +463,16 @@ pub fn token_edit(
|
|||
bank.deposit_limit = deposit_limit;
|
||||
require_group_admin = true;
|
||||
}
|
||||
|
||||
if let Some(zero_util_rate) = zero_util_rate {
|
||||
msg!(
|
||||
"Zero utilization rate old {:?}, new {:?}",
|
||||
bank.zero_util_rate,
|
||||
zero_util_rate
|
||||
);
|
||||
bank.zero_util_rate = I80F48::from_num(zero_util_rate);
|
||||
require_group_admin = true;
|
||||
}
|
||||
}
|
||||
|
||||
// account constraint #1
|
||||
|
|
|
@ -42,6 +42,7 @@ pub fn token_register(
|
|||
interest_target_utilization: f32,
|
||||
group_insurance_fund: bool,
|
||||
deposit_limit: u64,
|
||||
zero_util_rate: f32,
|
||||
) -> Result<()> {
|
||||
// Require token 0 to be in the insurance token
|
||||
if token_index == INSURANCE_TOKEN_INDEX {
|
||||
|
@ -122,7 +123,8 @@ pub fn token_register(
|
|||
maint_weight_shift_liab_target: I80F48::ZERO,
|
||||
fallback_oracle: ctx.accounts.fallback_oracle.key(),
|
||||
deposit_limit,
|
||||
reserved: [0; 1968],
|
||||
zero_util_rate: I80F48::from_num(zero_util_rate),
|
||||
reserved: [0; 1952],
|
||||
};
|
||||
|
||||
let oracle_ref = &AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?;
|
||||
|
|
|
@ -104,7 +104,8 @@ pub fn token_register_trustless(
|
|||
maint_weight_shift_liab_target: I80F48::ZERO,
|
||||
fallback_oracle: ctx.accounts.fallback_oracle.key(),
|
||||
deposit_limit: 0,
|
||||
reserved: [0; 1968],
|
||||
zero_util_rate: I80F48::ZERO,
|
||||
reserved: [0; 1952],
|
||||
};
|
||||
let oracle_ref = &AccountInfoRef::borrow(ctx.accounts.oracle.as_ref())?;
|
||||
if let Ok(oracle_price) = bank.oracle_price(&OracleAccountInfos::from_reader(oracle_ref), None)
|
||||
|
|
|
@ -155,6 +155,7 @@ pub mod mango_v4 {
|
|||
interest_target_utilization: f32,
|
||||
group_insurance_fund: bool,
|
||||
deposit_limit: u64,
|
||||
zero_util_rate: f32,
|
||||
) -> Result<()> {
|
||||
#[cfg(feature = "enable-gpl")]
|
||||
instructions::token_register(
|
||||
|
@ -186,6 +187,7 @@ pub mod mango_v4 {
|
|||
interest_target_utilization,
|
||||
group_insurance_fund,
|
||||
deposit_limit,
|
||||
zero_util_rate,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -239,6 +241,7 @@ pub mod mango_v4 {
|
|||
maint_weight_shift_abort: bool,
|
||||
set_fallback_oracle: bool,
|
||||
deposit_limit_opt: Option<u64>,
|
||||
zero_util_rate_opt: Option<f32>,
|
||||
) -> Result<()> {
|
||||
#[cfg(feature = "enable-gpl")]
|
||||
instructions::token_edit(
|
||||
|
@ -279,6 +282,7 @@ pub mod mango_v4 {
|
|||
maint_weight_shift_abort,
|
||||
set_fallback_oracle,
|
||||
deposit_limit_opt,
|
||||
zero_util_rate_opt,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -59,10 +59,24 @@ pub struct Bank {
|
|||
pub avg_utilization: I80F48,
|
||||
|
||||
pub adjustment_factor: I80F48,
|
||||
|
||||
/// The unscaled borrow interest curve is defined as continuous piecewise linear with the points:
|
||||
///
|
||||
/// - 0% util: zero_util_rate
|
||||
/// - util0% util: rate0
|
||||
/// - util1% util: rate1
|
||||
/// - 100% util: max_rate
|
||||
///
|
||||
/// The final rate is this unscaled curve multiplied by interest_curve_scaling.
|
||||
pub util0: I80F48,
|
||||
pub rate0: I80F48,
|
||||
pub util1: I80F48,
|
||||
pub rate1: I80F48,
|
||||
|
||||
/// the 100% utilization rate
|
||||
///
|
||||
/// This isn't the max_rate, since this still gets scaled by interest_curve_scaling,
|
||||
/// which is >=1.
|
||||
pub max_rate: I80F48,
|
||||
|
||||
// TODO: add ix/logic to regular send this to DAO
|
||||
|
@ -182,8 +196,13 @@ pub struct Bank {
|
|||
/// zero means none, in token native
|
||||
pub deposit_limit: u64,
|
||||
|
||||
/// The unscaled borrow interest curve point for zero utilization.
|
||||
///
|
||||
/// See util0, rate0, util1, rate1, max_rate
|
||||
pub zero_util_rate: I80F48,
|
||||
|
||||
#[derivative(Debug = "ignore")]
|
||||
pub reserved: [u8; 1968],
|
||||
pub reserved: [u8; 1952],
|
||||
}
|
||||
const_assert_eq!(
|
||||
size_of::<Bank>(),
|
||||
|
@ -220,7 +239,8 @@ const_assert_eq!(
|
|||
+ 16 * 3
|
||||
+ 32
|
||||
+ 8
|
||||
+ 1968
|
||||
+ 16
|
||||
+ 1952
|
||||
);
|
||||
const_assert_eq!(size_of::<Bank>(), 3064);
|
||||
const_assert_eq!(size_of::<Bank>() % 8, 0);
|
||||
|
@ -324,7 +344,8 @@ impl Bank {
|
|||
maint_weight_shift_liab_target: existing_bank.maint_weight_shift_liab_target,
|
||||
fallback_oracle: existing_bank.oracle,
|
||||
deposit_limit: existing_bank.deposit_limit,
|
||||
reserved: [0; 1968],
|
||||
zero_util_rate: existing_bank.zero_util_rate,
|
||||
reserved: [0; 1952],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,6 +376,7 @@ impl Bank {
|
|||
require_gte!(self.maint_weight_shift_duration_inv, 0.0);
|
||||
require_gte!(self.maint_weight_shift_asset_target, 0.0);
|
||||
require_gte!(self.maint_weight_shift_liab_target, 0.0);
|
||||
require_gte!(self.zero_util_rate, I80F48::ZERO);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1000,6 +1022,7 @@ impl Bank {
|
|||
pub fn compute_interest_rate(&self, utilization: I80F48) -> I80F48 {
|
||||
Bank::interest_rate_curve_calculator(
|
||||
utilization,
|
||||
self.zero_util_rate,
|
||||
self.util0,
|
||||
self.rate0,
|
||||
self.util1,
|
||||
|
@ -1014,6 +1037,7 @@ impl Bank {
|
|||
#[inline(always)]
|
||||
pub fn interest_rate_curve_calculator(
|
||||
utilization: I80F48,
|
||||
zero_util_rate: I80F48,
|
||||
util0: I80F48,
|
||||
rate0: I80F48,
|
||||
util1: I80F48,
|
||||
|
@ -1025,8 +1049,8 @@ impl Bank {
|
|||
let utilization = utilization.max(I80F48::ZERO).min(I80F48::ONE);
|
||||
|
||||
let v = if utilization <= util0 {
|
||||
let slope = rate0 / util0;
|
||||
slope * utilization
|
||||
let slope = (rate0 - zero_util_rate) / util0;
|
||||
zero_util_rate + slope * utilization
|
||||
} else if utilization <= util1 {
|
||||
let extra_util = utilization - util0;
|
||||
let slope = (rate1 - rate0) / (util1 - util0);
|
||||
|
@ -1683,4 +1707,45 @@ mod tests {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bank_interest_rate_curve() {
|
||||
let mut bank = Bank::zeroed();
|
||||
bank.zero_util_rate = I80F48::from(1);
|
||||
bank.rate0 = I80F48::from(3);
|
||||
bank.rate1 = I80F48::from(7);
|
||||
bank.max_rate = I80F48::from(13);
|
||||
|
||||
bank.util0 = I80F48::from_num(0.5);
|
||||
bank.util1 = I80F48::from_num(0.75);
|
||||
|
||||
let interest = |v: f64| {
|
||||
bank.compute_interest_rate(I80F48::from_num(v))
|
||||
.to_num::<f64>()
|
||||
};
|
||||
let d = |a: f64, b: f64| (a - b).abs();
|
||||
|
||||
// the points
|
||||
let eps = 0.0001;
|
||||
assert!(d(interest(-0.5), 1.0) <= eps);
|
||||
assert!(d(interest(0.0), 1.0) <= eps);
|
||||
assert!(d(interest(0.5), 3.0) <= eps);
|
||||
assert!(d(interest(0.75), 7.0) <= eps);
|
||||
assert!(d(interest(1.0), 13.0) <= eps);
|
||||
assert!(d(interest(1.5), 13.0) <= eps);
|
||||
|
||||
// midpoints
|
||||
assert!(d(interest(0.25), 2.0) <= eps);
|
||||
assert!(d(interest((0.5 + 0.75) / 2.0), 5.0) <= eps);
|
||||
assert!(d(interest((0.75 + 1.0) / 2.0), 10.0) <= eps);
|
||||
|
||||
// around the points
|
||||
let delta = 0.000001;
|
||||
assert!(d(interest(0.0 + delta), 1.0) <= eps);
|
||||
assert!(d(interest(0.5 - delta), 3.0) <= eps);
|
||||
assert!(d(interest(0.5 + delta), 3.0) <= eps);
|
||||
assert!(d(interest(0.75 - delta), 7.0) <= eps);
|
||||
assert!(d(interest(0.75 + delta), 7.0) <= eps);
|
||||
assert!(d(interest(1.0 - delta), 13.0) <= eps);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1074,6 +1074,7 @@ impl ClientInstruction for TokenRegisterInstruction {
|
|||
interest_target_utilization: 0.5,
|
||||
group_insurance_fund: true,
|
||||
deposit_limit: 0,
|
||||
zero_util_rate: 0.0,
|
||||
};
|
||||
|
||||
let bank = Pubkey::find_program_address(
|
||||
|
@ -1319,6 +1320,7 @@ pub fn token_edit_instruction_default() -> mango_v4::instruction::TokenEdit {
|
|||
maint_weight_shift_abort: false,
|
||||
set_fallback_oracle: false,
|
||||
deposit_limit_opt: None,
|
||||
zero_util_rate_opt: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { BN } from '@coral-xyz/anchor';
|
||||
import { utf8 } from '@coral-xyz/anchor/dist/cjs/utils/bytes';
|
||||
import { PublicKey } from '@solana/web3.js';
|
||||
import { format } from 'path';
|
||||
import { I80F48, I80F48Dto, ONE_I80F48, ZERO_I80F48 } from '../numbers/I80F48';
|
||||
import { As, toUiDecimals } from '../utils';
|
||||
import { OracleProvider, isOracleStaleOrUnconfident } from './oracle';
|
||||
|
@ -79,6 +80,7 @@ export class Bank implements BankForHealth {
|
|||
public maintWeightShiftDurationInv: I80F48;
|
||||
public maintWeightShiftAssetTarget: I80F48;
|
||||
public maintWeightShiftLiabTarget: I80F48;
|
||||
public zeroUtilRate: I80F48;
|
||||
|
||||
static from(
|
||||
publicKey: PublicKey,
|
||||
|
@ -139,6 +141,7 @@ export class Bank implements BankForHealth {
|
|||
maintWeightShiftAssetTarget: I80F48Dto;
|
||||
maintWeightShiftLiabTarget: I80F48Dto;
|
||||
depositLimit: BN;
|
||||
zeroUtilRate: I80F48Dto;
|
||||
},
|
||||
): Bank {
|
||||
return new Bank(
|
||||
|
@ -199,6 +202,7 @@ export class Bank implements BankForHealth {
|
|||
obj.maintWeightShiftAssetTarget,
|
||||
obj.maintWeightShiftLiabTarget,
|
||||
obj.depositLimit,
|
||||
obj.zeroUtilRate,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -260,6 +264,7 @@ export class Bank implements BankForHealth {
|
|||
maintWeightShiftAssetTarget: I80F48Dto,
|
||||
maintWeightShiftLiabTarget: I80F48Dto,
|
||||
public depositLimit: BN,
|
||||
zeroUtilRate: I80F48Dto,
|
||||
) {
|
||||
this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0];
|
||||
this.oracleConfig = {
|
||||
|
@ -289,6 +294,7 @@ export class Bank implements BankForHealth {
|
|||
this.maintWeightShiftDurationInv = I80F48.from(maintWeightShiftDurationInv);
|
||||
this.maintWeightShiftAssetTarget = I80F48.from(maintWeightShiftAssetTarget);
|
||||
this.maintWeightShiftLiabTarget = I80F48.from(maintWeightShiftLiabTarget);
|
||||
this.zeroUtilRate = I80F48.from(zeroUtilRate);
|
||||
this._price = undefined;
|
||||
this._uiPrice = undefined;
|
||||
this._oracleLastUpdatedSlot = undefined;
|
||||
|
@ -508,13 +514,16 @@ export class Bank implements BankForHealth {
|
|||
return ZERO_I80F48();
|
||||
}
|
||||
|
||||
const utilization = totalBorrows.div(totalDeposits);
|
||||
const utilization = totalBorrows
|
||||
.div(totalDeposits)
|
||||
.max(ZERO_I80F48())
|
||||
.min(ONE_I80F48());
|
||||
const scaling = I80F48.fromNumber(
|
||||
this.interestCurveScaling == 0.0 ? 1.0 : this.interestCurveScaling,
|
||||
);
|
||||
if (utilization.lt(this.util0)) {
|
||||
const slope = this.rate0.div(this.util0);
|
||||
return slope.mul(utilization).mul(scaling);
|
||||
const slope = this.rate0.sub(this.zeroUtilRate).div(this.util0);
|
||||
return this.zeroUtilRate.add(slope.mul(utilization)).mul(scaling);
|
||||
} else if (utilization.lt(this.util1)) {
|
||||
const extraUtil = utilization.sub(this.util0);
|
||||
const slope = this.rate1.sub(this.rate0).div(this.util1.sub(this.util0));
|
||||
|
|
|
@ -458,6 +458,7 @@ export class MangoClient {
|
|||
params.interestTargetUtilization,
|
||||
params.groupInsuranceFund,
|
||||
params.depositLimit,
|
||||
params.zeroUtilRate,
|
||||
)
|
||||
.accounts({
|
||||
group: group.publicKey,
|
||||
|
@ -542,6 +543,7 @@ export class MangoClient {
|
|||
params.maintWeightShiftAbort ?? false,
|
||||
params.setFallbackOracle ?? false,
|
||||
params.depositLimit,
|
||||
params.zeroUtilRate,
|
||||
)
|
||||
.accounts({
|
||||
group: group.publicKey,
|
||||
|
|
|
@ -28,6 +28,7 @@ export interface TokenRegisterParams {
|
|||
interestCurveScaling: number;
|
||||
interestTargetUtilization: number;
|
||||
depositLimit: BN;
|
||||
zeroUtilRate: number;
|
||||
}
|
||||
|
||||
export const DefaultTokenRegisterParams: TokenRegisterParams = {
|
||||
|
@ -66,6 +67,7 @@ export const DefaultTokenRegisterParams: TokenRegisterParams = {
|
|||
interestCurveScaling: 4.0,
|
||||
interestTargetUtilization: 0.5,
|
||||
depositLimit: new BN(0),
|
||||
zeroUtilRate: 0.0,
|
||||
};
|
||||
|
||||
export interface TokenEditParams {
|
||||
|
@ -105,6 +107,7 @@ export interface TokenEditParams {
|
|||
maintWeightShiftAbort: boolean | null;
|
||||
setFallbackOracle: boolean | null;
|
||||
depositLimit: BN | null;
|
||||
zeroUtilRate: number | null;
|
||||
}
|
||||
|
||||
export const NullTokenEditParams: TokenEditParams = {
|
||||
|
@ -144,6 +147,7 @@ export const NullTokenEditParams: TokenEditParams = {
|
|||
maintWeightShiftAbort: null,
|
||||
setFallbackOracle: null,
|
||||
depositLimit: null,
|
||||
zeroUtilRate: null,
|
||||
};
|
||||
|
||||
export interface PerpEditParams {
|
||||
|
|
|
@ -623,6 +623,10 @@ export type MangoV4 = {
|
|||
{
|
||||
"name": "depositLimit",
|
||||
"type": "u64"
|
||||
},
|
||||
{
|
||||
"name": "zeroUtilRate",
|
||||
"type": "f32"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1021,6 +1025,12 @@ export type MangoV4 = {
|
|||
"type": {
|
||||
"option": "u64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "zeroUtilRateOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -7137,6 +7147,16 @@ export type MangoV4 = {
|
|||
},
|
||||
{
|
||||
"name": "util0",
|
||||
"docs": [
|
||||
"The unscaled borrow interest curve is defined as continuous piecewise linear with the points:",
|
||||
"",
|
||||
"- 0% util: zero_util_rate",
|
||||
"- util0% util: rate0",
|
||||
"- util1% util: rate1",
|
||||
"- 100% util: max_rate",
|
||||
"",
|
||||
"The final rate is this unscaled curve multiplied by interest_curve_scaling."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -7161,6 +7181,12 @@ export type MangoV4 = {
|
|||
},
|
||||
{
|
||||
"name": "maxRate",
|
||||
"docs": [
|
||||
"the 100% utilization rate",
|
||||
"",
|
||||
"This isn't the max_rate, since this still gets scaled by interest_curve_scaling,",
|
||||
"which is >=1."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -7421,12 +7447,23 @@ export type MangoV4 = {
|
|||
],
|
||||
"type": "u64"
|
||||
},
|
||||
{
|
||||
"name": "zeroUtilRate",
|
||||
"docs": [
|
||||
"The unscaled borrow interest curve point for zero utilization.",
|
||||
"",
|
||||
"See util0, rate0, util1, rate1, max_rate"
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1968
|
||||
1952
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -14346,6 +14383,10 @@ export const IDL: MangoV4 = {
|
|||
{
|
||||
"name": "depositLimit",
|
||||
"type": "u64"
|
||||
},
|
||||
{
|
||||
"name": "zeroUtilRate",
|
||||
"type": "f32"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -14744,6 +14785,12 @@ export const IDL: MangoV4 = {
|
|||
"type": {
|
||||
"option": "u64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "zeroUtilRateOpt",
|
||||
"type": {
|
||||
"option": "f32"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -20860,6 +20907,16 @@ export const IDL: MangoV4 = {
|
|||
},
|
||||
{
|
||||
"name": "util0",
|
||||
"docs": [
|
||||
"The unscaled borrow interest curve is defined as continuous piecewise linear with the points:",
|
||||
"",
|
||||
"- 0% util: zero_util_rate",
|
||||
"- util0% util: rate0",
|
||||
"- util1% util: rate1",
|
||||
"- 100% util: max_rate",
|
||||
"",
|
||||
"The final rate is this unscaled curve multiplied by interest_curve_scaling."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -20884,6 +20941,12 @@ export const IDL: MangoV4 = {
|
|||
},
|
||||
{
|
||||
"name": "maxRate",
|
||||
"docs": [
|
||||
"the 100% utilization rate",
|
||||
"",
|
||||
"This isn't the max_rate, since this still gets scaled by interest_curve_scaling,",
|
||||
"which is >=1."
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
|
@ -21144,12 +21207,23 @@ export const IDL: MangoV4 = {
|
|||
],
|
||||
"type": "u64"
|
||||
},
|
||||
{
|
||||
"name": "zeroUtilRate",
|
||||
"docs": [
|
||||
"The unscaled borrow interest curve point for zero utilization.",
|
||||
"",
|
||||
"See util0, rate0, util1, rate1, max_rate"
|
||||
],
|
||||
"type": {
|
||||
"defined": "I80F48"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "reserved",
|
||||
"type": {
|
||||
"array": [
|
||||
"u8",
|
||||
1968
|
||||
1952
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue