Skip to content

Commit

Permalink
Merge branch 'dev' into deposit_limit
Browse files Browse the repository at this point in the history
# Conflicts:
#	programs/tokenized_vault/src/instructions/deposit.rs
#	programs/tokenized_vault/src/instructions/direct_deposit.rs
#	programs/tokenized_vault/src/instructions/withdraw.rs
  • Loading branch information
vito-kovalione committed Dec 18, 2024
2 parents 2500321 + 01c13ba commit 9e6aebc
Show file tree
Hide file tree
Showing 22 changed files with 6,271 additions and 3,386 deletions.
3 changes: 3 additions & 0 deletions programs/accountant/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ pub enum ErrorCode {

#[msg("Serialization error")]
SerializationError,

#[msg("Fee is invalid")]
InvalidFee,
}
19 changes: 19 additions & 0 deletions programs/accountant/src/events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use anchor_lang::prelude::*;

#[event]
pub struct PerformanceFeeUpdatedEvent {
pub accountant_key: Pubkey,
pub performance_fee: u64,
}

#[event]
pub struct EntryFeeUpdatedEvent {
pub accountant_key: Pubkey,
pub entry_fee: u64,
}

#[event]
pub struct RedemptionFeeUpdatedEvent {
pub accountant_key: Pubkey,
pub redemption_fee: u64,
}
4 changes: 2 additions & 2 deletions programs/accountant/src/instructions/init_token_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ pub struct InitTokenAccount<'info> {
#[account(
init_if_needed,
payer = signer,
associated_token::mint = underlying_mint,
associated_token::mint = mint,
associated_token::authority = accountant,
)]
pub token_account: Box<InterfaceAccount<'info, TokenAccount>>,

#[account(mut)]
pub underlying_mint: Box<InterfaceAccount<'info, Mint>>,
pub mint: Box<InterfaceAccount<'info, Mint>>,

/// CHECK: We want to hadle all accountant types here
#[account(mut)]
Expand Down
52 changes: 48 additions & 4 deletions programs/accountant/src/instructions/set_fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use access_control::{
state::{UserRole, Role}
};

use crate::events::{EntryFeeUpdatedEvent, PerformanceFeeUpdatedEvent, RedemptionFeeUpdatedEvent};
use crate::utils::unchecked_accountant::UncheckedAccountant;

#[derive(Accounts)]
Expand All @@ -30,12 +31,55 @@ pub struct SetFee<'info> {
pub access_control: Program<'info, AccessControl>
}

pub fn handle_set_fee(
pub fn handle_set_performance_fee(
ctx: Context<SetFee>,
fee: u64,
) -> Result<()> {
let accountant = &mut ctx.accounts.accountant.from_unchecked()?;

accountant.set_fee(fee)?;
accountant.save_changes(&mut &mut ctx.accounts.accountant.try_borrow_mut_data()?[8..])
}
accountant.set_performance_fee(fee)?;
accountant.save_changes(&mut &mut ctx.accounts.accountant.try_borrow_mut_data()?[8..])?;

emit!(PerformanceFeeUpdatedEvent {
accountant_key: ctx.accounts.accountant.key(),
performance_fee: fee,
});

Ok(())
}


pub fn handle_set_entry_fee(
ctx: Context<SetFee>,
fee: u64,
) -> Result<()> {
let accountant = &mut ctx.accounts.accountant.from_unchecked()?;

accountant.set_entry_fee(fee)?;
accountant.save_changes(&mut &mut ctx.accounts.accountant.try_borrow_mut_data()?[8..])?;

emit!(EntryFeeUpdatedEvent {
accountant_key: ctx.accounts.accountant.key(),
entry_fee: fee,
});

Ok(())
}

pub fn handle_set_redemption_fee(
ctx: Context<SetFee>,
fee: u64,
) -> Result<()> {
let accountant = &mut ctx.accounts.accountant.from_unchecked()?;

accountant.set_redemption_fee(fee)?;
accountant.save_changes(&mut &mut ctx.accounts.accountant.try_borrow_mut_data()?[8..])?;

emit!(RedemptionFeeUpdatedEvent {
accountant_key: ctx.accounts.accountant.key(),
redemption_fee: fee,
});

Ok(())
}

13 changes: 11 additions & 2 deletions programs/accountant/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use anchor_lang::prelude::*;

pub mod constants;
pub mod error;
pub mod events;
pub mod instructions;
pub mod state;
pub mod utils;
Expand Down Expand Up @@ -45,7 +46,15 @@ pub mod accountant {
handle_distribute(ctx)
}

pub fn set_fee(ctx: Context<SetFee>, fee: u64) -> Result<()> {
handle_set_fee(ctx, fee)
pub fn set_performance_fee(ctx: Context<SetFee>, fee: u64) -> Result<()> {
handle_set_performance_fee(ctx, fee)
}

pub fn set_redemption_fee(ctx: Context<SetFee>, fee: u64) -> Result<()> {
handle_set_redemption_fee(ctx, fee)
}

pub fn set_entry_fee(ctx: Context<SetFee>, fee: u64) -> Result<()> {
handle_set_entry_fee(ctx, fee)
}
}
12 changes: 9 additions & 3 deletions programs/accountant/src/state/base_accountant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ pub trait Accountant {
fn init(&mut self, index: u64, bump: u8) -> Result<()>;

fn report(&self, profit: u64, loss: u64) -> Result<(u64,u64)>;
fn enter(&self, amount: u64) -> Result<u64>;
fn redeem(&self, amount: u64) -> Result<u64>;

fn distribute(&mut self, accounts: &Distribute) -> Result<()>;
fn set_fee_recipient(&mut self, recipient: Pubkey) -> Result<()>;
fn set_fee(&mut self, fee: u64) -> Result<()>;

fn set_performance_fee(&mut self, fee: u64) -> Result<()>;
fn set_redemption_fee(&mut self, fee: u64) -> Result<()>;
fn set_entry_fee(&mut self, fee: u64) -> Result<()>;

fn entry_fee(&self) -> u64;
fn redemption_fee(&self) -> u64;
fn performance_fee(&self) -> u64;
fn fee_recipient(&self) -> Pubkey;

fn seeds(&self) -> [&[u8]; 2];
fn save_changes(&self, writer: &mut dyn std::io::Write) -> Result<()>;
Expand Down
44 changes: 38 additions & 6 deletions programs/accountant/src/state/generic_accountant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ pub struct GenericAccountant {
pub index_buffer: [u8; 8],
pub bump: [u8; 1],

pub entry_fee: u64,
pub redemption_fee: u64,
pub performance_fee: u64,
pub fee_recipient: Pubkey,
}

impl Accountant for GenericAccountant {
Expand All @@ -36,6 +37,16 @@ impl Accountant for GenericAccountant {
Ok((total_fees, total_refunds))
}

fn enter(&self, amount: u64) -> Result<u64> {
let fee = self.entry_fee * amount / FEE_BPS;
Ok(fee)
}

fn redeem(&self, amount: u64) -> Result<u64> {
let fee = self.redemption_fee * amount / FEE_BPS;
Ok(fee)
}

fn distribute(&mut self, accounts: &Distribute) -> Result<()> {
let total = accounts.token_account.amount;

Expand All @@ -53,22 +64,43 @@ impl Accountant for GenericAccountant {
)
}

fn set_fee(&mut self, fee: u64) -> Result<()> {
fn set_performance_fee(&mut self, fee: u64) -> Result<()> {
if fee > FEE_BPS {
return Err(ErrorCode::InvalidFee.into());
}

self.performance_fee = fee;
Ok(())
}

fn set_fee_recipient(&mut self, recipient: Pubkey) -> Result<()> {
self.fee_recipient = recipient;
fn set_redemption_fee(&mut self, fee: u64) -> Result<()> {
if fee > FEE_BPS {
return Err(ErrorCode::InvalidFee.into());
}

self.redemption_fee = fee;
Ok(())
}

fn set_entry_fee(&mut self, fee: u64) -> Result<()> {
if fee > FEE_BPS {
return Err(ErrorCode::InvalidFee.into());
}

self.entry_fee = fee;
Ok(())
}

fn performance_fee(&self) -> u64 {
self.performance_fee
}

fn fee_recipient(&self) -> Pubkey {
self.fee_recipient
fn entry_fee(&self) -> u64 {
self.entry_fee
}

fn redemption_fee(&self) -> u64 {
self.redemption_fee
}

fn save_changes(&self, writer: &mut dyn std::io::Write) -> Result<()> {
Expand Down
25 changes: 1 addition & 24 deletions programs/accountant/src/utils/unchecked_accountant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,4 @@ impl<'a> UncheckedAccountant for UncheckedAccount<'a> {
Ok(())
}

}

// pub fn from_unchecked(strategy_acc: &UncheckedAccount) -> Result<Box<dyn Accountant>> {
// let strategy_data = strategy_acc.try_borrow_data()?;
// let discriminator = get_discriminator(strategy_acc)?;

// match discriminator {
// GenericAccountant::DISCRIMINATOR => {
// let strategy = GenericAccountant::try_from_slice(&strategy_data[8..])
// .map_err(|_| ErrorCode::InvalidData)?;
// Ok(Box::new(strategy))
// }
// _ => {
// msg!("Invalid discriminator");
// Err(ErrorCode::InvalidDiscriminator.into())
// }
// }
// }

// fn get_discriminator(acc_info: &UncheckedAccount) -> Result<[u8; 8]> {
// let data = acc_info.try_borrow_data()?;
// let discriminator = data[0..8].try_into().map_err(|_| ErrorCode::InvalidData)?;
// Ok(discriminator)
// }
}
33 changes: 30 additions & 3 deletions programs/tokenized_vault/src/instructions/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,24 @@ use crate::constants::{SHARES_SEED, UNDERLYING_SEED, USER_DATA_SEED};

use crate::events::VaultDepositEvent;
use crate::state::{UserData, Vault};
use crate::utils::{token, vault};
use crate::utils::{accountant, token, vault};

#[derive(Accounts)]
pub struct Deposit<'info> {
#[account(mut)]
pub vault: AccountLoader<'info, Vault>,

/// CHECK:
#[account(mut, address = vault.load()?.accountant)]
pub accountant: UncheckedAccount<'info>,

#[account(
mut,
associated_token::mint = shares_mint,
associated_token::authority = accountant,
)]
pub accountant_recipient: Box<InterfaceAccount<'info, TokenAccount>>,

#[account(mut)]
pub user_token_account: InterfaceAccount<'info, TokenAccount>,

Expand Down Expand Up @@ -71,15 +82,18 @@ pub struct Deposit<'info> {
}

pub fn handle_deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
let enter_fee = accountant::enter(&ctx.accounts.accountant, amount)?;
let amount_to_deposit = amount - enter_fee;

vault::validate_deposit(
&ctx.accounts.vault,
&ctx.accounts.kyc_verified,
&ctx.accounts.user_data,
false,
amount
amount_to_deposit
)?;

let shares = ctx.accounts.vault.load()?.convert_to_shares(amount);
let mut shares = ctx.accounts.vault.load()?.convert_to_shares(amount_to_deposit);

token::transfer(
ctx.accounts.token_program.to_account_info(),
Expand All @@ -99,6 +113,19 @@ pub fn handle_deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
&ctx.accounts.vault.load()?.seeds_shares(),
)?;

if enter_fee > 0 {
let fee_shares = ctx.accounts.vault.load()?.convert_to_shares(enter_fee);
shares += fee_shares;
token::mint_to(
ctx.accounts.shares_token_program.to_account_info(),
ctx.accounts.shares_mint.to_account_info(),
ctx.accounts.accountant_recipient.to_account_info(),
ctx.accounts.shares_mint.to_account_info(),
fee_shares,
&ctx.accounts.vault.load()?.seeds_shares(),
)?;
}

ctx.accounts.user_data.deposited += amount;

let mut vault = ctx.accounts.vault.load_mut()?;
Expand Down
Loading

0 comments on commit 9e6aebc

Please sign in to comment.