Skip to content

Commit

Permalink
Merge pull request #202 from blockworks-foundation/pan/add-fee-tier
Browse files Browse the repository at this point in the history
Add second fee tier
  • Loading branch information
riordanp authored Sep 1, 2022
2 parents 8c9be7e + 51ec79b commit 387ca2b
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 13 deletions.
37 changes: 37 additions & 0 deletions program/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,20 @@ pub enum MangoInstruction {
/// 3. `[]` mango_cache_ai
/// 4. `[writable]` perp_market_ai
ForceSettlePerpPosition,

/// Set the `ref_surcharge_centibps`, `ref_share_centibps` for both tiers and `ref_mngo_required` on `MangoGroup`
///
/// Accounts expected by this instruction (2):
/// 0. `[writable]` mango_group_ai - MangoGroup that this mango account is for
/// 1. `[signer]` admin_ai - mango_group.admin
ChangeReferralFeeParams2 {
ref_surcharge_centibps_tier_1: u32,
ref_share_centibps_tier_1: u32,
ref_surcharge_centibps_tier_2: u16,
ref_share_centibps_tier_2: u16,
ref_mngo_required: u64,
ref_mngo_tier_2_factor: u8,
},
}

impl MangoInstruction {
Expand Down Expand Up @@ -1700,6 +1714,29 @@ impl MangoInstruction {
}
}
73 => MangoInstruction::ForceSettlePerpPosition,
74 => {
let data = array_ref![data, 0, 21];
let (
ref_surcharge_centibps_tier_1,
ref_share_centibps_tier_1,
ref_surcharge_centibps_tier_2,
ref_share_centibps_tier_2,
ref_mngo_required,
ref_mngo_tier_2_factor,
) = array_refs![data, 4, 4, 2, 2, 8, 1];
MangoInstruction::ChangeReferralFeeParams2 {
ref_surcharge_centibps_tier_1: u32::from_le_bytes(
*ref_surcharge_centibps_tier_1,
),
ref_share_centibps_tier_1: u32::from_le_bytes(*ref_share_centibps_tier_1),
ref_surcharge_centibps_tier_2: u16::from_le_bytes(
*ref_surcharge_centibps_tier_2,
),
ref_share_centibps_tier_2: u16::from_le_bytes(*ref_share_centibps_tier_2),
ref_mngo_required: u64::from_le_bytes(*ref_mngo_required),
ref_mngo_tier_2_factor: u8::from_le_bytes(*ref_mngo_tier_2_factor),
}
}
_ => {
return None;
}
Expand Down
30 changes: 27 additions & 3 deletions program/src/matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2069,13 +2069,24 @@ fn determine_ref_vars<'a>(
};

let mngo_cache = &mango_cache.root_bank_cache[mngo_index];
let tier_2_enabled = mango_group.ref_surcharge_centibps_tier_2 != 0
&& mango_group.ref_share_centibps_tier_2 != 0;

// If the user's MNGO deposit is non-zero then the rootbank cache will be checked already in `place_perp_order`.
// If it's zero then cache may be out of date, but it doesn't matter because 0 * index = 0
let mngo_deposits = mango_account.get_native_deposit(mngo_cache, mngo_index)?;
let ref_mngo_req = I80F48::from_num(mango_group.ref_mngo_required);
if mngo_deposits >= ref_mngo_req {
let ref_mngo_tier_2_factor = I80F48::from_num(mango_group.ref_mngo_tier_2_factor);

if tier_2_enabled && mngo_deposits >= ref_mngo_req * ref_mngo_tier_2_factor
|| !tier_2_enabled && mngo_deposits >= ref_mngo_req
{
return Ok((ZERO_I80F48, None));
} else if tier_2_enabled && mngo_deposits >= ref_mngo_req {
return Ok((
I80F48::from_num(mango_group.ref_surcharge_centibps_tier_1) / CENTIBPS_PER_UNIT,
None,
));
} else if let Some(referrer_mango_account_ai) = referrer_mango_account_ai {
// If referrer_mango_account is invalid, just treat it as if it doesn't exist
if let Ok(referrer_mango_account) =
Expand All @@ -2086,18 +2097,31 @@ fn determine_ref_vars<'a>(
let ref_mngo_deposits =
referrer_mango_account.get_native_deposit(mngo_cache, mngo_index)?;

let share =
if tier_2_enabled && ref_mngo_deposits >= ref_mngo_req * ref_mngo_tier_2_factor {
mango_group.ref_share_centibps_tier_2.into()
} else {
mango_group.ref_share_centibps_tier_1
};

if !referrer_mango_account.is_bankrupt
&& !referrer_mango_account.being_liquidated
&& ref_mngo_deposits >= ref_mngo_req
{
return Ok((
I80F48::from_num(mango_group.ref_share_centibps) / CENTIBPS_PER_UNIT,
I80F48::from_num(share) / CENTIBPS_PER_UNIT,
Some(referrer_mango_account),
));
}
}
}
Ok((I80F48::from_num(mango_group.ref_surcharge_centibps) / CENTIBPS_PER_UNIT, None))
let surcharge = if tier_2_enabled {
mango_group.ref_surcharge_centibps_tier_2.into()
} else {
mango_group.ref_surcharge_centibps_tier_1
};

Ok((I80F48::from_num(surcharge) / CENTIBPS_PER_UNIT, None))
}

/// Apply taker fees to the taker account and update the markets' fees_accrued for
Expand Down
94 changes: 91 additions & 3 deletions program/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6146,18 +6146,86 @@ impl Processor {
let mut mango_group = MangoGroup::load_mut_checked(mango_group_ai, program_id)?;
check_eq!(admin_ai.key, &mango_group.admin, MangoErrorCode::InvalidAdminKey)?;
check!(admin_ai.is_signer, MangoErrorCode::SignerNecessary)?;
msg!("old referral fee params: ref_surcharge_centibps: {} ref_share_centibps: {} ref_mngo_required: {}", mango_group.ref_surcharge_centibps, mango_group.ref_share_centibps, mango_group.ref_mngo_required);
msg!("old referral fee params: ref_surcharge_centibps: {} ref_share_centibps: {} ref_mngo_required: {}", mango_group.ref_surcharge_centibps_tier_1, mango_group.ref_share_centibps_tier_1, mango_group.ref_mngo_required);

// TODO - when this goes out, if there are any events on the EventQueue fee logging will be messed up

mango_group.ref_surcharge_centibps = ref_surcharge_centibps;
mango_group.ref_share_centibps = ref_share_centibps;
mango_group.ref_surcharge_centibps_tier_1 = ref_surcharge_centibps;
mango_group.ref_share_centibps_tier_1 = ref_share_centibps;
mango_group.ref_mngo_required = ref_mngo_required;

msg!("new referral fee params: ref_surcharge_centibps: {} ref_share_centibps: {} ref_mngo_required: {}", ref_surcharge_centibps, ref_share_centibps, ref_mngo_required);
Ok(())
}

/// Set the `ref_surcharge_centibps`, `ref_share_centibps` for both tiers and `ref_mngo_required` on `MangoGroup`
#[inline(never)]
fn change_referral_fee_params2(
program_id: &Pubkey,
accounts: &[AccountInfo],
ref_surcharge_centibps_tier_1: u32,
ref_share_centibps_tier_1: u32,
ref_surcharge_centibps_tier_2: u16,
ref_share_centibps_tier_2: u16,
ref_mngo_required: u64,
ref_mngo_tier_2_factor: u8,
) -> MangoResult {
let tier_2_enabled = ref_surcharge_centibps_tier_2 != 0 && ref_share_centibps_tier_2 != 0;
if tier_2_enabled {
// tier 1 surcharge must be <= tier 2 surcharge so tier 1 holders don't pay more than base fee
check!(
ref_surcharge_centibps_tier_1 <= u32::from(ref_surcharge_centibps_tier_2),
MangoErrorCode::InvalidParam
)?;
// tier 1 share must be >= tier 1 surcharge so tier 1 referees don't pay less than their referrer
check!(
ref_share_centibps_tier_1 >= ref_surcharge_centibps_tier_1,
MangoErrorCode::InvalidParam
)?;
// tier 1 share must be <= tier 2 share so tier 2 referrers don't earn less fees than tier 1 referrers
check!(
ref_share_centibps_tier_1 <= u32::from(ref_share_centibps_tier_2),
MangoErrorCode::InvalidParam
)?;
// tier 2 share must be <= tier 2 surcharge so tier 2 referees don't pay more than base fee
check!(
ref_share_centibps_tier_2 <= ref_surcharge_centibps_tier_2,
MangoErrorCode::InvalidParam
)?;
check!(ref_mngo_tier_2_factor >= 1, MangoErrorCode::InvalidParam)?;
} else {
check!(
ref_surcharge_centibps_tier_1 >= ref_share_centibps_tier_1,
MangoErrorCode::InvalidParam
)?;
}

const NUM_FIXED: usize = 2;
let accounts = array_ref![accounts, 0, NUM_FIXED];

let [
mango_group_ai, // write
admin_ai // read, signer
] = accounts;

let mut mango_group = MangoGroup::load_mut_checked(mango_group_ai, program_id)?;
check_eq!(admin_ai.key, &mango_group.admin, MangoErrorCode::InvalidAdminKey)?;
check!(admin_ai.is_signer, MangoErrorCode::SignerNecessary)?;
msg!("old referral fee params: ref_surcharge_centibps_tier_1: {} ref_share_centibps_tier_1: {} ref_surcharge_centibps_tier_2: {} ref_share_centibps_tier_2: {} ref_mngo_required: {} ref_mngo_tier_2_factor {}", mango_group.ref_surcharge_centibps_tier_1, mango_group.ref_share_centibps_tier_1, mango_group.ref_surcharge_centibps_tier_2, mango_group.ref_share_centibps_tier_2, mango_group.ref_mngo_required, mango_group.ref_mngo_tier_2_factor);

// TODO - when this goes out, if there are any events on the EventQueue fee logging will be messed up

mango_group.ref_surcharge_centibps_tier_1 = ref_surcharge_centibps_tier_1;
mango_group.ref_share_centibps_tier_1 = ref_share_centibps_tier_1;
mango_group.ref_surcharge_centibps_tier_2 = ref_surcharge_centibps_tier_2;
mango_group.ref_share_centibps_tier_2 = ref_share_centibps_tier_2;
mango_group.ref_mngo_required = ref_mngo_required;
mango_group.ref_mngo_tier_2_factor = ref_mngo_tier_2_factor;

msg!("new referral fee params: ref_surcharge_centibps_tier_1: {} ref_share_centibps_tier_1: {} ref_surcharge_centibps_tier_2: {} ref_share_centibps_tier_2: {} ref_mngo_required: {} ref_mngo_tier_2_factor {}", ref_surcharge_centibps_tier_1, ref_share_centibps_tier_1, ref_surcharge_centibps_tier_2, ref_share_centibps_tier_2, ref_mngo_required, ref_mngo_tier_2_factor);
Ok(())
}

#[inline(never)]
/// Store the referrer's MangoAccount pubkey on the Referrer account
/// It will create the Referrer account as a PDA of user's MangoAccount if it doesn't exist
Expand Down Expand Up @@ -7866,6 +7934,26 @@ impl Processor {
msg!("Mango: ForceSettlePerpPosition");
Self::force_settle_perp_position(program_id, accounts)
}
MangoInstruction::ChangeReferralFeeParams2 {
ref_surcharge_centibps_tier_1,
ref_share_centibps_tier_1,
ref_surcharge_centibps_tier_2,
ref_share_centibps_tier_2,
ref_mngo_required,
ref_mngo_tier_2_factor,
} => {
msg!("Mango: ChangeReferralFeeParams2");
Self::change_referral_fee_params2(
program_id,
accounts,
ref_surcharge_centibps_tier_1,
ref_share_centibps_tier_1,
ref_surcharge_centibps_tier_2,
ref_share_centibps_tier_2,
ref_mngo_required,
ref_mngo_tier_2_factor,
)
}
}
}
}
Expand Down
26 changes: 19 additions & 7 deletions program/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,11 +259,14 @@ pub struct MangoGroup {
pub max_mango_accounts: u32, // limits maximum number of MangoAccounts.v1 (closeable) accounts
pub num_mango_accounts: u32, // number of MangoAccounts.v1

pub ref_surcharge_centibps: u32, // 100
pub ref_share_centibps: u32, // 80 (must be less than surcharge)
pub ref_surcharge_centibps_tier_1: u32, // 100
pub ref_share_centibps_tier_1: u32, // 80 (must be less than surcharge)
pub ref_mngo_required: u64,
pub ref_surcharge_centibps_tier_2: u16,
pub ref_share_centibps_tier_2: u16,
pub ref_mngo_tier_2_factor: u8,

pub padding: [u8; 8], // padding used for future expansions
pub padding: [u8; 3],
}

impl MangoGroup {
Expand Down Expand Up @@ -1198,10 +1201,19 @@ impl HealthCache {
let mngo_cache = &mango_cache.root_bank_cache[mngo_index];
let mngo_deposits = mango_account.get_native_deposit(mngo_cache, mngo_index)?;
let ref_mngo_req = I80F48::from_num(mango_group.ref_mngo_required);
if mngo_deposits < ref_mngo_req {
market_fees += (I80F48::from_num(mango_group.ref_surcharge_centibps)
/ CENTIBPS_PER_UNIT)
* taker_quote_native;
let ref_mngo_tier_2_factor = I80F48::from_num(mango_group.ref_mngo_tier_2_factor);
let tier_2_enabled = mango_group.ref_surcharge_centibps_tier_2 != 0
&& mango_group.ref_share_centibps_tier_2 != 0;

if mngo_deposits < ref_mngo_req * ref_mngo_tier_2_factor {
let surcharge = if tier_2_enabled && mngo_deposits < ref_mngo_req {
mango_group.ref_surcharge_centibps_tier_2.into()
} else {
mango_group.ref_surcharge_centibps_tier_1
};

market_fees +=
(I80F48::from_num(surcharge) / CENTIBPS_PER_UNIT) * taker_quote_native;
}
}
market_fees
Expand Down

0 comments on commit 387ca2b

Please sign in to comment.