Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/defindex fees #167

Merged
merged 8 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
22 changes: 11 additions & 11 deletions apps/contracts/factory/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ use crate::defindex::AssetAllocation;
pub struct InitializedEvent {
pub admin: Address,
pub defindex_receiver: Address,
pub fee_rate: u32,
pub defindex_fee: u32,
}

pub(crate) fn emit_initialized(e: &Env, admin: Address, defindex_receiver: Address, fee_rate: u32) {
pub(crate) fn emit_initialized(e: &Env, admin: Address, defindex_receiver: Address, defindex_fee: u32) {
let event: InitializedEvent = InitializedEvent {
admin,
defindex_receiver,
fee_rate,
defindex_fee,
};
e.events()
.publish(("DeFindexFactory", symbol_short!("init")), event);
Expand All @@ -28,7 +28,7 @@ pub struct CreateDeFindexEvent {
pub emergency_manager: Address,
pub fee_receiver: Address,
pub manager: Address,
pub vault_share: u32,
pub vault_fee: u32,
pub assets: Vec<AssetAllocation>
}

Expand All @@ -38,14 +38,14 @@ pub(crate) fn emit_create_defindex_vault(
emergency_manager: Address,
fee_receiver: Address,
manager: Address,
vault_share: u32,
vault_fee: u32,
assets: Vec<AssetAllocation>,
) {
let event = CreateDeFindexEvent {
emergency_manager,
fee_receiver,
manager,
vault_share,
vault_fee,
assets,
};

Expand Down Expand Up @@ -81,16 +81,16 @@ pub(crate) fn emit_new_defindex_receiver(e: &Env, new_defindex_receiver: Address
.publish(("DeFindexFactory", symbol_short!("nreceiver")), event);
}

// NEW FEE RATE EVENT
// NEW DEFINDEX FEE EVENT
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct NewFeeRateEvent {
pub new_fee_rate: u32,
pub new_defindex_fee: u32,
}

pub(crate) fn emit_new_fee_rate(e: &Env, new_fee_rate: u32) {
let event = NewFeeRateEvent { new_fee_rate };
pub(crate) fn emit_new_defindex_fee(e: &Env, new_defindex_fee: u32) {
let event = NewFeeRateEvent { new_defindex_fee };

e.events()
.publish(("DeFindexFactory", symbol_short!("nfee_rate")), event);
.publish(("DeFindexFactory", symbol_short!("n_fee")), event);
}
50 changes: 25 additions & 25 deletions apps/contracts/factory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use soroban_sdk::{
};
use error::FactoryError;
use defindex::{create_contract, AssetAllocation};
use storage::{ add_new_defindex, extend_instance_ttl, get_admin, get_defi_wasm_hash, get_defindex_receiver, get_deployed_defindexes, get_fee_rate, has_admin, put_admin, put_defi_wasm_hash, put_defindex_receiver, put_fee_rate };
use storage::{ add_new_defindex, extend_instance_ttl, get_admin, get_defi_wasm_hash, get_defindex_receiver, get_deployed_defindexes, get_fee_rate, has_admin, put_admin, put_defi_wasm_hash, put_defindex_receiver, put_defindex_fee };

fn check_initialized(e: &Env) -> Result<(), FactoryError> {
if !has_admin(e) {
Expand All @@ -26,7 +26,7 @@ pub trait FactoryTrait {
/// * `e` - The environment in which the contract is running.
/// * `admin` - The address of the contract administrator, who can manage settings.
/// * `defindex_receiver` - The default address designated to receive a portion of fees.
/// * `fee_rate` - The initial annual fee rate (in basis points).
/// * `defindex_fee` - The initial annual fee rate (in basis points).
/// * `defindex_wasm_hash` - The hash of the DeFindex Vault's WASM file for deploying new vaults.
///
/// # Returns
Expand All @@ -35,7 +35,7 @@ pub trait FactoryTrait {
e: Env,
admin: Address,
defindex_receiver: Address,
fee_rate: u32,
defindex_fee: u32,
defindex_wasm_hash: BytesN<32>
) -> Result<(), FactoryError>;

Expand All @@ -45,7 +45,7 @@ pub trait FactoryTrait {
/// * `e` - The environment in which the contract is running.
/// * `emergency_manager` - The address assigned emergency control over the vault.
/// * `fee_receiver` - The address designated to receive fees from the vault.
/// * `vault_share` - The percentage share of fees allocated to the vault's fee receiver.
/// * `vault_fee` - The percentage share of fees allocated to the vault's fee receiver.
/// * `vault_name` - The name of the vault.
/// * `vault_symbol` - The symbol of the vault.
/// * `manager` - The address assigned as the vault manager.
Expand All @@ -58,7 +58,7 @@ pub trait FactoryTrait {
e: Env,
emergency_manager: Address,
fee_receiver: Address,
vault_share: u32,
vault_fee: u32,
vault_name: String,
vault_symbol: String,
manager: Address,
Expand All @@ -72,7 +72,7 @@ pub trait FactoryTrait {
/// * `e` - The environment in which the contract is running.
/// * `emergency_manager` - The address assigned emergency control over the vault.
/// * `fee_receiver` - The address designated to receive fees from the vault.
/// * `vault_share` - The percentage share of fees allocated to the vault's fee receiver.
/// * `vault_fee` - The percentage share of fees allocated to the vault's fee receiver.
/// * `vault_name` - The name of the vault.
/// * `vault_symbol` - The symbol of the vault.
/// * `manager` - The address assigned as the vault manager.
Expand All @@ -87,7 +87,7 @@ pub trait FactoryTrait {
caller: Address,
emergency_manager: Address,
fee_receiver: Address,
vault_share: u32,
vault_fee: u32,
vault_name: String,
vault_symbol: String,
manager: Address,
Expand Down Expand Up @@ -126,7 +126,7 @@ pub trait FactoryTrait {
///
/// # Returns
/// * `Result<(), FactoryError>` - Returns Ok(()) if successful, or an error if not authorized.
fn set_fee_rate(e: Env, new_fee_rate: u32) -> Result<(), FactoryError>;
fn set_defindex_fee(e: Env, new_fee_rate: u32) -> Result<(), FactoryError>;

// --- Read Methods ---

Expand Down Expand Up @@ -164,7 +164,7 @@ pub trait FactoryTrait {
///
/// # Returns
/// * `Result<u32, FactoryError>` - Returns the fee rate in basis points or an error if not found.
fn fee_rate(e: Env) -> Result<u32, FactoryError>;
fn defindex_fee(e: Env) -> Result<u32, FactoryError>;
}

#[contract]
Expand All @@ -179,7 +179,7 @@ impl FactoryTrait for DeFindexFactory {
/// * `e` - The environment in which the contract is running.
/// * `admin` - The address of the contract administrator, who can manage settings.
/// * `defindex_receiver` - The default address designated to receive a portion of fees.
/// * `fee_rate` - The initial annual fee rate (in basis points).
/// * `defindex_fee` - The initial annual fee rate (in basis points).
/// * `defindex_wasm_hash` - The hash of the DeFindex Vault's WASM file for deploying new vaults.
///
/// # Returns
Expand All @@ -188,7 +188,7 @@ impl FactoryTrait for DeFindexFactory {
e: Env,
admin: Address,
defindex_receiver: Address,
fee_rate: u32,
defindex_fee: u32,
defi_wasm_hash: BytesN<32>
) -> Result<(), FactoryError> {
if has_admin(&e) {
Expand All @@ -198,9 +198,9 @@ impl FactoryTrait for DeFindexFactory {
put_admin(&e, &admin);
put_defindex_receiver(&e, &defindex_receiver);
put_defi_wasm_hash(&e, defi_wasm_hash);
put_fee_rate(&e, &fee_rate);
put_defindex_fee(&e, &defindex_fee);

events::emit_initialized(&e, admin, defindex_receiver, fee_rate);
events::emit_initialized(&e, admin, defindex_receiver, defindex_fee);
extend_instance_ttl(&e);
Ok(())
}
Expand All @@ -211,7 +211,7 @@ impl FactoryTrait for DeFindexFactory {
/// * `e` - The environment in which the contract is running.
/// * `emergency_manager` - The address assigned emergency control over the vault.
/// * `fee_receiver` - The address designated to receive fees from the vault.
/// * `vault_share` - The percentage share of fees allocated to the vault's fee receiver.
/// * `vault_fee` - The percentage share of fees allocated to the vault's fee receiver.
/// * `manager` - The address assigned as the vault manager.
/// * `assets` - A vector of `AssetAllocation` structs that define the assets managed by the vault.
/// * `salt` - A salt used for ensuring unique addresses for each deployed vault.
Expand All @@ -222,7 +222,7 @@ impl FactoryTrait for DeFindexFactory {
e: Env,
emergency_manager: Address,
fee_receiver: Address,
vault_share: u32,
vault_fee: u32,
vault_name: String,
vault_symbol: String,
manager: Address,
Expand All @@ -243,15 +243,15 @@ impl FactoryTrait for DeFindexFactory {
&manager,
&emergency_manager,
&fee_receiver,
&vault_share,
&vault_fee,
&defindex_receiver,
&current_contract,
&vault_name,
&vault_symbol,
);

add_new_defindex(&e, defindex_address.clone());
events::emit_create_defindex_vault(&e, emergency_manager, fee_receiver, manager, vault_share, assets);
events::emit_create_defindex_vault(&e, emergency_manager, fee_receiver, manager, vault_fee, assets);
Ok(defindex_address)
}

Expand All @@ -261,7 +261,7 @@ impl FactoryTrait for DeFindexFactory {
/// * `e` - The environment in which the contract is running.
/// * `emergency_manager` - The address assigned emergency control over the vault.
/// * `fee_receiver` - The address designated to receive fees from the vault.
/// * `vault_share` - The percentage share of fees allocated to the vault's fee receiver.
/// * `vault_fee` - The percentage share of fees allocated to the vault's fee receiver.
/// * `vault_name` - The name of the vault.
/// * `vault_symbol` - The symbol of the vault.
/// * `manager` - The address assigned as the vault manager.
Expand All @@ -276,7 +276,7 @@ impl FactoryTrait for DeFindexFactory {
caller: Address,
emergency_manager: Address,
fee_receiver: Address,
vault_share: u32,
vault_fee: u32,
vault_name: String,
vault_symbol: String,
manager: Address,
Expand Down Expand Up @@ -305,7 +305,7 @@ impl FactoryTrait for DeFindexFactory {
&manager,
&emergency_manager,
&fee_receiver,
&vault_share,
&vault_fee,
&defindex_receiver,
&current_contract,
&vault_name,
Expand All @@ -324,7 +324,7 @@ impl FactoryTrait for DeFindexFactory {
);

add_new_defindex(&e, defindex_address.clone());
events::emit_create_defindex_vault(&e, emergency_manager, fee_receiver, manager, vault_share, assets);
events::emit_create_defindex_vault(&e, emergency_manager, fee_receiver, manager, vault_fee, assets);
Ok(defindex_address)
}

Expand Down Expand Up @@ -376,14 +376,14 @@ impl FactoryTrait for DeFindexFactory {
///
/// # Returns
/// * `Result<(), FactoryError>` - Returns Ok(()) if successful, or an error if not authorized.
fn set_fee_rate(e: Env, fee_rate: u32) -> Result<(), FactoryError> {
fn set_defindex_fee(e: Env, defindex_fee: u32) -> Result<(), FactoryError> {
check_initialized(&e)?;
extend_instance_ttl(&e);
let admin = get_admin(&e);
admin.require_auth();

put_fee_rate(&e, &fee_rate);
events::emit_new_fee_rate(&e, fee_rate);
put_defindex_fee(&e, &defindex_fee);
events::emit_new_defindex_fee(&e, defindex_fee);
Ok(())
}

Expand Down Expand Up @@ -435,7 +435,7 @@ impl FactoryTrait for DeFindexFactory {
///
/// # Returns
/// * `Result<u32, FactoryError>` - Returns the fee rate in basis points or an error if not found.
fn fee_rate(e: Env) -> Result<u32, FactoryError> {
fn defindex_fee(e: Env) -> Result<u32, FactoryError> {
check_initialized(&e)?;
extend_instance_ttl(&e);
Ok(get_fee_rate(&e))
Expand Down
2 changes: 1 addition & 1 deletion apps/contracts/factory/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub fn get_defindex_receiver(e: &Env) -> Address {
}

// Fee Rate BPS (MAX BPS = 10000)
pub fn put_fee_rate(e: &Env, value: &u32) {
pub fn put_defindex_fee(e: &Env, value: &u32) {
e.storage().instance().set(&DataKey::FeeRate, value);
}

Expand Down
2 changes: 1 addition & 1 deletion apps/contracts/src/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export async function test_factory(addressBook: AddressBook) {
const createDeFindexParams: xdr.ScVal[] = [
new Address(emergencyManager.publicKey()).toScVal(),
new Address(feeReceiver.publicKey()).toScVal(),
nativeToScVal(100, { type: "u32" }), // Setting vault_share as 100 bps for demonstration
nativeToScVal(100, { type: "u32" }), // Setting vault_fee as 100 bps for demonstration
nativeToScVal("Test Vault", { type: "string" }),
nativeToScVal("DFT-Test-Vault", { type: "string" }),
new Address(manager.publicKey()).toScVal(),
Expand Down
40 changes: 26 additions & 14 deletions apps/contracts/vault/src/fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
events,
funds::fetch_total_managed_funds,
storage::{
get_defindex_protocol_fee_receiver, get_factory, get_last_fee_assesment, get_vault_share,
get_defindex_protocol_fee_receiver, get_factory, get_last_fee_assesment, get_vault_fee,
set_last_fee_assesment,
},
token::internal_mint,
Expand All @@ -16,12 +16,17 @@ use crate::{

/// Fetches the current fee rate from the factory contract.
/// The fee rate is expressed in basis points (BPS).
fn fetch_fee_rate(e: &Env) -> u32 {
fn fetch_defindex_fee(e: &Env) -> u32 {
let factory_address = get_factory(e);
// Interacts with the factory contract to get the fee rate.
e.invoke_contract(&factory_address, &Symbol::new(&e, "fee_rate"), Vec::new(&e))
e.invoke_contract(
&factory_address,
&Symbol::new(&e, "defindex_fee"),
Vec::new(&e)
)
}

/// Calculates the required fees in dfTokens based on the current APR fee rate.
fn calculate_fees(e: &Env, time_elapsed: u64, fee_rate: u32) -> Result<i128, ContractError> {
chopan123 marked this conversation as resolved.
Show resolved Hide resolved
let total_managed_funds = fetch_total_managed_funds(e); // Get total managed funds per asset

Expand All @@ -41,46 +46,53 @@ fn calculate_fees(e: &Env, time_elapsed: u64, fee_rate: u32) -> Result<i128, Con
total_fees_per_asset.set(asset_address.clone(), asset_fee);
}

let total_fees_in_dftokens = calculate_dftokens_from_asset_amounts(e, total_fees_per_asset)?;
let total_fees_in_dftokens = calculate_dftokens_from_asset_amounts(e, total_fees_per_asset, total_managed_funds)?;

Ok(total_fees_in_dftokens)
}

/// Collects and mints fees in dfTokens, distributing them to the appropriate fee receivers.
pub fn collect_fees(e: &Env) -> Result<(), ContractError> {
let current_timestamp = e.ledger().timestamp();
let last_fee_assessment = get_last_fee_assesment(e);

let time_elapsed = current_timestamp.checked_sub(last_fee_assessment).unwrap();

// If no time has passed since the last fee assessment, no fees are collected
if time_elapsed == 0 {
return Ok(());
}

let fee_rate = fetch_fee_rate(e);
// Fetch the individual fees for DeFindex and Vault, then calculate the total rate
let defindex_fee = fetch_defindex_fee(e);
let vault_fee = get_vault_fee(e);
let total_fee_rate = defindex_fee.checked_add(vault_fee).unwrap();

let total_fees = calculate_fees(e, time_elapsed, fee_rate)?;
// Calculate the total fees in dfTokens based on the combined fee rate
let total_fees = calculate_fees(e, time_elapsed, total_fee_rate)?;

// Mint the total fees as dfTokens
mint_fees(e, total_fees)?;
// Mint and distribute the fees proportionally
mint_fees(e, total_fees, defindex_fee, vault_fee)?;

// Update the last fee assessment timestamp
set_last_fee_assesment(e, &current_timestamp);

Ok(())
}

fn mint_fees(e: &Env, total_fees: i128) -> Result<(), ContractError> {
/// Mints dfTokens for fees and distributes them to the vault fee receiver and DeFindex receiver.
fn mint_fees(e: &Env, total_fees: i128, defindex_fee: u32, vault_fee: u32) -> Result<(), ContractError> {
let access_control = AccessControl::new(&e);

let vault_fee_receiver = access_control.get_fee_receiver()?;
let defindex_protocol_receiver = get_defindex_protocol_fee_receiver(e);

let vault_share_bps = get_vault_share(e);

let vault_shares = (total_fees * vault_share_bps as i128) / MAX_BPS;

let defindex_shares = total_fees - vault_shares;
// Calculate shares for each receiver based on their fee proportion
let total_fee_bps = defindex_fee as i128 + vault_fee as i128;
let defindex_shares = (total_fees * defindex_fee as i128) / total_fee_bps;
let vault_shares = total_fees - defindex_shares;

// Mint shares for both receivers
internal_mint(e.clone(), vault_fee_receiver.clone(), vault_shares);
internal_mint(
e.clone(),
Expand Down
Loading