use borsh::BorshDeserialize;
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, msg,
program_error::ProgramError, pubkey::Pubkey, rent::Rent,
};
use crate::{
args::ValidatorClaimFeesArgs,
consts::PROTOCOL_FEES_PERCENTAGE,
error::DlpError,
processor::utils::loaders::{
load_initialized_protocol_fees_vault,
load_initialized_validator_fees_vault, load_signer,
},
};
pub fn process_validator_claim_fees(
_program_id: &Pubkey,
accounts: &[AccountInfo],
data: &[u8],
) -> ProgramResult {
let args = ValidatorClaimFeesArgs::try_from_slice(data)?;
let [validator, fees_vault, validator_fees_vault] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(validator, "validator")?;
load_initialized_protocol_fees_vault(fees_vault, true)?;
load_initialized_validator_fees_vault(
validator,
validator_fees_vault,
true,
)?;
let min_rent = Rent::default().minimum_balance(8);
let amount = args
.amount
.unwrap_or(validator_fees_vault.lamports() - min_rent);
if validator_fees_vault.lamports() - min_rent < amount {
msg!(
"Vault ({}) has insufficient funds: {} < {}",
validator_fees_vault.key,
validator_fees_vault.lamports() - min_rent,
amount
);
return Err(ProgramError::InsufficientFunds);
}
let protocol_fees = (amount * u64::from(PROTOCOL_FEES_PERCENTAGE)) / 100;
let remaining_amount = amount.saturating_sub(protocol_fees);
**fees_vault.try_borrow_mut_lamports()? = fees_vault
.lamports()
.checked_add(protocol_fees)
.ok_or(DlpError::Overflow)?;
**validator_fees_vault.try_borrow_mut_lamports()? = validator_fees_vault
.lamports()
.checked_sub(amount)
.ok_or(ProgramError::InsufficientFunds)?;
**validator.try_borrow_mut_lamports()? = validator
.lamports()
.checked_add(remaining_amount)
.ok_or(DlpError::Overflow)?;
Ok(())
}