Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod v1;
pub mod v2;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use generic_array_struct::generic_array_struct;

use crate::instructions::generic::DiscmOnlyIxData;

// Accounts

#[generic_array_struct(builder pub)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct WithdrawProtocolFeesV2IxAccs<T> {
/// The pool's state singleton PDA
pub pool_state: T,

/// The pool's protocol fee beneficiary
pub beneficiary: T,

/// INF token account to withdraw unclaimed protocol fees to
pub withdraw_to: T,

/// INF token mint
pub inf_mint: T,

/// INF token program
pub token_program: T,
}

impl<T: Copy> WithdrawProtocolFeesV2IxAccs<T> {
#[inline]
pub const fn memset(val: T) -> Self {
Self([val; WITHDRAW_PROTOCOL_FEES_V2_IX_ACCS_LEN])
}
}

pub type WithdrawProtocolFeesV2IxKeys<'a> = WithdrawProtocolFeesV2IxAccs<&'a [u8; 32]>;

pub type WithdrawProtocolFeesV2IxKeysOwned = WithdrawProtocolFeesV2IxAccs<[u8; 32]>;

pub type WithdrawProtocolFeesV2IxAccFlags = WithdrawProtocolFeesV2IxAccs<bool>;

pub const WITHDRAW_PROTOCOL_FEES_V2_IX_IS_WRITER: WithdrawProtocolFeesV2IxAccFlags =
WithdrawProtocolFeesV2IxAccFlags::memset(false)
.const_with_pool_state(true)
.const_with_withdraw_to(true)
.const_with_inf_mint(true);

pub const WITHDRAW_PROTOCOL_FEES_V2_IX_IS_SIGNER: WithdrawProtocolFeesV2IxAccFlags =
WithdrawProtocolFeesV2IxAccFlags::memset(false).const_with_beneficiary(true);

// Data

pub const WITHDRAW_PROTOCOL_FEES_V2_IX_DISCM: u8 = 25;

pub type WithdrawProtocolFeesV2IxData = DiscmOnlyIxData<WITHDRAW_PROTOCOL_FEES_V2_IX_DISCM>;

pub const WITHDRAW_PROTOCOL_FEES_V2_IX_DATA_LEN: usize = WithdrawProtocolFeesV2IxData::DATA_LEN;
2 changes: 1 addition & 1 deletion controller/program/src/instructions/protocol_fee/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub mod set_protocol_fee;
pub mod set_protocol_fee_beneficiary;
pub mod withdraw_protocol_fee;
pub mod withdraw_protocol_fees;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod v1;
pub mod v2;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use inf1_ctl_jiminy::{
account_utils::pool_state_v2_checked,
err::Inf1CtlErr,
instructions::protocol_fee::withdraw_protocol_fees::{
instructions::protocol_fee::withdraw_protocol_fees::v1::{
NewWithdrawProtocolFeesIxAccsBuilder, WithdrawProtocolFeesIxAccs,
WithdrawProtocolFeesIxData, WITHDRAW_PROTOCOL_FEES_IX_IS_SIGNER,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use inf1_ctl_jiminy::{
account_utils::{pool_state_v2_checked, pool_state_v2_checked_mut},
err::Inf1CtlErr,
instructions::protocol_fee::withdraw_protocol_fees::v2::{
NewWithdrawProtocolFeesV2IxAccsBuilder, WithdrawProtocolFeesV2IxAccs,
WITHDRAW_PROTOCOL_FEES_V2_IX_IS_SIGNER,
},
keys::POOL_STATE_ID,
pda_onchain::POOL_STATE_SIGNER,
program_err::Inf1CtlCustomProgErr,
svc::InfCalc,
typedefs::pool_sv::PoolSvLamports,
};
use jiminy_cpi::{
account::{Abr, AccountHandle},
program_error::{ProgramError, NOT_ENOUGH_ACCOUNT_KEYS},
Cpi,
};
use jiminy_sysvar_clock::Clock;
use sanctum_spl_token_jiminy::{
instructions::mint_to::mint_to_ix_account_handle_perms,
sanctum_spl_token_core::instructions::mint_to::{MintToIxData, NewMintToIxAccsBuilder},
};

use crate::{
token::checked_mint_of,
verify::{verify_not_rebalancing_and_not_disabled, verify_pks, verify_signers},
};

type WithdrawProtocolFeesV2IxAccounts<'acc> = WithdrawProtocolFeesV2IxAccs<AccountHandle<'acc>>;

#[inline]
pub fn withdraw_protocol_fees_v2_checked<'acc>(
abr: &Abr,
accs: &[AccountHandle<'acc>],
) -> Result<WithdrawProtocolFeesV2IxAccounts<'acc>, ProgramError> {
let accs = accs.first_chunk().ok_or(NOT_ENOUGH_ACCOUNT_KEYS)?;
let accs = WithdrawProtocolFeesV2IxAccs(*accs);

let pool = pool_state_v2_checked(abr.get(*accs.pool_state()))?;
let mint_acc = abr.get(*accs.inf_mint());

let expected_pks = NewWithdrawProtocolFeesV2IxAccsBuilder::start()
.with_pool_state(&POOL_STATE_ID)
.with_beneficiary(&pool.protocol_fee_beneficiary)
.with_inf_mint(&pool.lp_token_mint)
.with_token_program(mint_acc.owner())
// Free: the beneficiary is free to specify whatever INF token account to withdraw to
// In the case of an invalid INF token acc, token prog mint_to CPI will fail
.with_withdraw_to(abr.get(*accs.withdraw_to()).key())
.build();
verify_pks(abr, &accs.0, &expected_pks.0)?;

verify_signers(abr, &accs.0, &WITHDRAW_PROTOCOL_FEES_V2_IX_IS_SIGNER.0)?;

verify_not_rebalancing_and_not_disabled(pool)?;

Ok(accs)
}

#[inline]
pub fn process_withdraw_protocol_fees_v2(
abr: &mut Abr,
cpi: &mut Cpi,
accs: WithdrawProtocolFeesV2IxAccounts,
clock: &Clock,
) -> Result<(), ProgramError> {
let pool = pool_state_v2_checked_mut(abr.get_mut(*accs.pool_state()))?;
pool.release_yield(clock.slot)
.map_err(Inf1CtlCustomProgErr)?;

let protocol_fee_lamports = pool.protocol_fee_lamports;

if protocol_fee_lamports == 0 {
return Ok(());
}

let pool_lamports = PoolSvLamports::from_pool_state_v2(pool);
let inf_token_supply = checked_mint_of(abr.get(*accs.inf_mint()))?.supply();

let inf_calc = InfCalc {
pool_lamports,
mint_supply: inf_token_supply,
};

let inf_to_mint = inf_calc
.sol_to_inf(protocol_fee_lamports)
.ok_or(Inf1CtlCustomProgErr(Inf1CtlErr::MathError))?;

if inf_to_mint == 0 {
return Ok(());
}

cpi.invoke_signed_handle(
abr,
*accs.token_program(),
MintToIxData::new(inf_to_mint).as_buf(),
mint_to_ix_account_handle_perms(
NewMintToIxAccsBuilder::start()
.with_auth(*accs.pool_state())
.with_mint(*accs.inf_mint())
.with_to(*accs.withdraw_to())
.build(),
),
&[POOL_STATE_SIGNER],
)?;

let pool = pool_state_v2_checked_mut(abr.get_mut(*accs.pool_state()))?;
pool.protocol_fee_lamports = 0;

Ok(())
}
16 changes: 13 additions & 3 deletions controller/program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ use inf1_ctl_jiminy::instructions::{
protocol_fee::{
set_protocol_fee::SET_PROTOCOL_FEE_IX_DISCM,
set_protocol_fee_beneficiary::SET_PROTOCOL_FEE_BENEFICIARY_IX_DISCM,
withdraw_protocol_fees::WITHDRAW_PROTOCOL_FEES_IX_DISCM,
withdraw_protocol_fees::{
v1::WITHDRAW_PROTOCOL_FEES_IX_DISCM, v2::WITHDRAW_PROTOCOL_FEES_V2_IX_DISCM,
},
},
rebalance::{
end::END_REBALANCE_IX_DISCM,
Expand Down Expand Up @@ -80,8 +82,9 @@ use crate::{
set_protocol_fee_beneficiary::{
process_set_protocol_fee_beneficiary, set_protocol_fee_beneficiary_accs_checked,
},
withdraw_protocol_fee::{
process_withdraw_protocol_fees, withdraw_protocol_fees_checked,
withdraw_protocol_fees::{
v1::{process_withdraw_protocol_fees, withdraw_protocol_fees_checked},
v2::{process_withdraw_protocol_fees_v2, withdraw_protocol_fees_v2_checked},
},
},
rebalance::{
Expand Down Expand Up @@ -268,6 +271,13 @@ fn process_ix(
let accs = set_rebal_auth_accs_checked(abr, accounts)?;
process_set_rebal_auth(abr, accs)
}
// v2 withdraw protocol fees
(&WITHDRAW_PROTOCOL_FEES_V2_IX_DISCM, _) => {
sol_log("WithdrawProtocolFeesV2");
let accs = withdraw_protocol_fees_v2_checked(abr, accounts)?;
let clock = Clock::write_to(&mut clock)?;
process_withdraw_protocol_fees_v2(abr, cpi, accs, clock)
}
// v2 swap
(&SWAP_EXACT_IN_V2_IX_DISCM, data) => {
sol_log("SwapExactInV2");
Expand Down
6 changes: 3 additions & 3 deletions controller/program/tests/tests/protocol_fee/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
mod set_protocol_fee;
mod set_protocol_fee_beneficiary;
mod withdraw_protocol_fees;
pub mod set_protocol_fee;
pub mod set_protocol_fee_beneficiary;
pub mod withdraw_protocol_fees;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod v1;
pub mod v2;
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use generic_array_struct::generic_array_struct;
use inf1_ctl_jiminy::{
accounts::pool_state::{PoolStateV2, PoolStateV2Addrs, PoolStateV2FtaVals},
err::Inf1CtlErr,
instructions::protocol_fee::withdraw_protocol_fees::{
instructions::protocol_fee::withdraw_protocol_fees::v1::{
NewWithdrawProtocolFeesIxAccsBuilder, WithdrawProtocolFeesIxAccsBuilder,
WithdrawProtocolFeesIxData, WithdrawProtocolFeesIxKeysOwned,
WITHDRAW_PROTOCOL_FEES_IX_ACCS_IDX_BENEFICIARY,
Expand Down
Loading