Skip to content

Commit

Permalink
Merge branch 'feat/improveVaultDepositTests'
Browse files Browse the repository at this point in the history
  • Loading branch information
esteblock committed Nov 6, 2024
2 parents 5663274 + 5f0b0de commit 003c8e0
Show file tree
Hide file tree
Showing 36 changed files with 814 additions and 475 deletions.
2 changes: 1 addition & 1 deletion apps/contracts/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["strategies/*", "defindex", "factory"]
members = ["strategies/*", "vault", "factory"]
exclude = [
"strategies/external_wasms",
]
Expand Down
2 changes: 1 addition & 1 deletion apps/contracts/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SUBDIRS = strategies defindex factory
SUBDIRS = strategies vault factory

default: build

Expand Down
2 changes: 0 additions & 2 deletions apps/contracts/defindex/src/constants.rs

This file was deleted.

43 changes: 0 additions & 43 deletions apps/contracts/defindex/src/investment.rs

This file was deleted.

File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use soroban_sdk::{contracttype, panic_with_error, Address, Env};
#[contracttype]
pub enum RolesDataKey {
EmergencyManager, // Role: Emergency Manager
FeeReceiver, // Role: Fee Receiver
VaultFeeReceiver, // Role: Fee Receiver
Manager, // Role: Manager
}

Expand Down Expand Up @@ -82,13 +82,16 @@ impl AccessControlTrait for AccessControl {

// Role-specific setters and getters
impl AccessControl {
pub fn set_fee_receiver(&self, caller: &Address, fee_receiver: &Address) {
self.require_any_role(&[RolesDataKey::Manager, RolesDataKey::FeeReceiver], caller);
self.set_role(&RolesDataKey::FeeReceiver, fee_receiver);
pub fn set_fee_receiver(&self, caller: &Address, vault_fee_receiver: &Address) {
self.require_any_role(
&[RolesDataKey::Manager, RolesDataKey::VaultFeeReceiver],
caller,
);
self.set_role(&RolesDataKey::VaultFeeReceiver, vault_fee_receiver);
}

pub fn get_fee_receiver(&self) -> Result<Address, ContractError> {
self.check_role(&RolesDataKey::FeeReceiver)
self.check_role(&RolesDataKey::VaultFeeReceiver)
}

pub fn set_manager(&self, manager: &Address) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
use soroban_sdk::{vec, Address, Env, IntoVal, Symbol, Val, Vec};

use crate::{models::DexDistribution, storage::{get_assets, get_factory}, ContractError};
use crate::{
models::DexDistribution,
storage::{get_assets, get_factory},
ContractError,
};

fn fetch_aggregator_address(e: &Env) -> Address {
let factory_address = get_factory(e);

e.invoke_contract(
&factory_address,
&Symbol::new(&e, "aggregator"),
Vec::new(&e)
&factory_address,
&Symbol::new(&e, "aggregator"),
Vec::new(&e),
)
}

fn is_supported_asset(e: &Env, token: &Address) -> bool {
let assets = get_assets(e);
assets.iter().any(|asset| &asset.address == token)
}

pub fn internal_swap_exact_tokens_for_tokens(e: &Env, token_in: &Address, token_out: &Address, amount_in: &i128, amount_out_min: &i128, distribution: &Vec<DexDistribution>, deadline: &u64) -> Result<(), ContractError> {

pub fn internal_swap_exact_tokens_for_tokens(
e: &Env,
token_in: &Address,
token_out: &Address,
amount_in: &i128,
amount_out_min: &i128,
distribution: &Vec<DexDistribution>,
deadline: &u64,
) -> Result<(), ContractError> {
let aggregator_address = fetch_aggregator_address(e);

// Check if both tokens are supported by the vault
Expand All @@ -35,13 +47,21 @@ pub fn internal_swap_exact_tokens_for_tokens(e: &Env, token_in: &Address, token_
init_args.push_back(deadline.into_val(e));

e.invoke_contract(
&aggregator_address,
&Symbol::new(&e, "swap_exact_tokens_for_tokens"),
Vec::new(&e)
&aggregator_address,
&Symbol::new(&e, "swap_exact_tokens_for_tokens"),
Vec::new(&e),
)
}

pub fn internal_swap_tokens_for_exact_tokens(e: &Env, token_in: &Address, token_out: &Address, amount_out: &i128, amount_in_max: &i128, distribution: &Vec<DexDistribution>, deadline: &u64) -> Result<(), ContractError> {
pub fn internal_swap_tokens_for_exact_tokens(
e: &Env,
token_in: &Address,
token_out: &Address,
amount_out: &i128,
amount_in_max: &i128,
distribution: &Vec<DexDistribution>,
deadline: &u64,
) -> Result<(), ContractError> {
let aggregator_address = fetch_aggregator_address(e);

// Check if both tokens are supported by the vault
Expand All @@ -59,8 +79,8 @@ pub fn internal_swap_tokens_for_exact_tokens(e: &Env, token_in: &Address, token_
init_args.push_back(deadline.into_val(e));

e.invoke_contract(
&aggregator_address,
&Symbol::new(&e, "swap_tokens_for_exact_tokens"),
Vec::new(&e)
&aggregator_address,
&Symbol::new(&e, "swap_tokens_for_exact_tokens"),
Vec::new(&e),
)
}
}
2 changes: 2 additions & 0 deletions apps/contracts/vault/src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub(crate) const MAX_BPS: i128 = 10_000;
pub(crate) const SECONDS_PER_YEAR: i128 = 31_536_000;
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ pub enum ContractError {
NotInitialized = 100,
AlreadyInitialized = 101,
InvalidRatio = 102,
StrategyDoesNotSupportAsset=103,
StrategyDoesNotSupportAsset = 103,

// Validation Errors (11x)
NegativeNotAllowed = 110,
InsufficientBalance = 111,
WrongAmuntsLength = 112,
WrongAmountsLength = 112,
NotEnoughIdleFunds = 113,
InsufficientManagedFunds = 114,
MissingInstructionData = 115,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
//! Definition of the Events used in the DeFindex Vault contract
use soroban_sdk::{contracttype, symbol_short, Address, Env, Vec};
use crate::models::AssetAllocation;
use soroban_sdk::{contracttype, symbol_short, Address, Env, Vec};

// INITIALIZED VAULT EVENT
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InitializedVaultEvent {
pub emergency_manager: Address,
pub fee_receiver: Address,
pub vault_fee_receiver: Address,
pub manager: Address,
pub defindex_receiver: Address,
pub defindex_protocol_receiver: Address,
pub assets: Vec<AssetAllocation>,
}

/// Publishes an `InitializedVaultEvent` to the event stream.
pub(crate) fn emit_initialized_vault(
e: &Env,
emergency_manager: Address,
fee_receiver: Address,
vault_fee_receiver: Address,
manager: Address,
defindex_receiver: Address,
defindex_protocol_receiver: Address,
assets: Vec<AssetAllocation>,
) {
let event = InitializedVaultEvent {
emergency_manager,
fee_receiver,
vault_fee_receiver,
manager,
defindex_receiver,
defindex_protocol_receiver,
assets,
};

Expand Down Expand Up @@ -178,9 +178,7 @@ pub struct ManagerChangedEvent {

/// Publishes a `ManagerChangedEvent` to the event stream.
pub(crate) fn emit_manager_changed_event(e: &Env, new_manager: Address) {
let event = ManagerChangedEvent {
new_manager,
};
let event = ManagerChangedEvent { new_manager };

e.events()
.publish(("DeFindexVault", symbol_short!("nmanager")), event);
Expand All @@ -194,10 +192,7 @@ pub struct EmergencyManagerChangedEvent {
}

/// Publishes an `EmergencyManagerChangedEvent` to the event stream.
pub(crate) fn emit_emergency_manager_changed_event(
e: &Env,
new_emergency_manager: Address,
) {
pub(crate) fn emit_emergency_manager_changed_event(e: &Env, new_emergency_manager: Address) {
let event = EmergencyManagerChangedEvent {
new_emergency_manager,
};
Expand All @@ -210,7 +205,7 @@ pub(crate) fn emit_emergency_manager_changed_event(
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FeesMintedEvent {
pub defindex_receiver: Address,
pub defindex_protocol_receiver: Address,
pub defindex_shares: i128,
pub vault_receiver: Address,
pub vault_shares: i128,
Expand All @@ -219,18 +214,18 @@ pub struct FeesMintedEvent {
/// Publishes an `EmergencyManagerChangedEvent` to the event stream.
pub(crate) fn emit_fees_minted_event(
e: &Env,
defindex_receiver: Address,
defindex_protocol_receiver: Address,
defindex_shares: i128,
vault_receiver: Address,
vault_shares: i128,
) {
let event = FeesMintedEvent {
defindex_receiver,
defindex_protocol_receiver,
defindex_shares,
vault_receiver,
vault_shares,
};

e.events()
.publish(("DeFindexVault", symbol_short!("mfees")), event);
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
use soroban_sdk::{Address, Env, Map, Symbol, Vec};

use crate::{access::AccessControl, constants::{MAX_BPS, SECONDS_PER_YEAR}, events, funds::fetch_total_managed_funds, storage::{get_defindex_receiver, get_factory, get_last_fee_assesment, get_vault_share, set_last_fee_assesment}, token::internal_mint, utils::calculate_dftokens_from_asset_amounts, ContractError};
use crate::{
access::AccessControl,
constants::{MAX_BPS, SECONDS_PER_YEAR},
events,
funds::fetch_total_managed_funds,
storage::{
get_defindex_protocol_fee_receiver, get_factory, get_last_fee_assesment, get_vault_share,
set_last_fee_assesment,
},
token::internal_mint,
utils::calculate_dftokens_from_asset_amounts,
ContractError,
};

/// 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 {
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)
)
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))
}

fn calculate_fees(e: &Env, time_elapsed: u64, fee_rate: u32) -> Result<i128, ContractError> {

let total_managed_funds = fetch_total_managed_funds(e); // Get total managed funds per asset

let seconds_per_year = SECONDS_PER_YEAR; // 365 days in seconds

let mut total_fees_per_asset: Map<Address, i128> = Map::new(&e);
Expand All @@ -28,10 +35,10 @@ fn calculate_fees(e: &Env, time_elapsed: u64, fee_rate: u32) -> Result<i128, Con
let current_asset_value = amount;

// Calculate the fee for this asset based on the fee rate and time elapsed
let asset_fee = (current_asset_value * fee_rate as i128 * time_elapsed as i128) / (seconds_per_year * MAX_BPS);
let asset_fee = (current_asset_value * fee_rate as i128 * time_elapsed as i128)
/ (seconds_per_year * MAX_BPS);

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)?;
Expand All @@ -41,7 +48,7 @@ fn calculate_fees(e: &Env, time_elapsed: u64, fee_rate: u32) -> Result<i128, Con

pub fn collect_fees(e: &Env) -> Result<(), ContractError> {
let current_timestamp = e.ledger().timestamp();
let last_fee_assessment = get_last_fee_assesment(e);
let last_fee_assessment = get_last_fee_assesment(e);

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

Expand All @@ -64,19 +71,29 @@ pub fn collect_fees(e: &Env) -> Result<(), ContractError> {

fn mint_fees(e: &Env, total_fees: i128) -> Result<(), ContractError> {
let access_control = AccessControl::new(&e);

let vault_fee_receiver = access_control.get_fee_receiver()?;
let defindex_receiver = get_defindex_receiver(e);
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;

internal_mint(e.clone(), vault_fee_receiver.clone(), vault_shares);
internal_mint(e.clone(), defindex_receiver.clone(), defindex_shares);

events::emit_fees_minted_event(e, defindex_receiver, defindex_shares, vault_fee_receiver, vault_shares);
internal_mint(
e.clone(),
defindex_protocol_receiver.clone(),
defindex_shares,
);

events::emit_fees_minted_event(
e,
defindex_protocol_receiver,
defindex_shares,
vault_fee_receiver,
vault_shares,
);
Ok(())
}
}
Loading

0 comments on commit 003c8e0

Please sign in to comment.