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

Feat: Decouple epoch_close from epoch_execute #1921

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
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
8 changes: 8 additions & 0 deletions libs/mocks/src/pools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,14 @@ pub mod pallet {
execute_call!((a, b))
}

fn debit(a: Self::InvestmentId, b: &T::AccountId, c: Self::Amount) -> DispatchResult {
execute_call!((a, b, c))
}

fn credit(a: Self::InvestmentId, b: &T::AccountId, c: Self::Amount) -> DispatchResult {
execute_call!((a, b, c))
}

fn transfer(
a: Self::InvestmentId,
b: &T::AccountId,
Expand Down
7 changes: 7 additions & 0 deletions libs/traits/src/investments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,13 @@ pub trait InvestmentAccountant<AccountId> {
amount: Self::Amount,
) -> Result<(), Self::Error>;

/// Debit a given amount from the account to the given accountant account
fn debit(id: Self::InvestmentId, from: &AccountId, amount: Self::Amount) -> DispatchResult;

/// Credit a given amount from the accountant account to the given to
/// account
fn credit(id: Self::InvestmentId, to: &AccountId, amount: Self::Amount) -> DispatchResult;

/// Increases the existence of
fn deposit(
buyer: &AccountId,
Expand Down
10 changes: 9 additions & 1 deletion libs/traits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,14 @@ pub trait StatusNotificationHook {
fn notify_status_change(id: Self::Id, status: Self::Status) -> Result<(), Self::Error>;
}

pub trait Reserve<Balance> {
fn deposit(&mut self, amount: Balance) -> DispatchResult;

fn withdraw(&mut self, amount: Balance) -> DispatchResult;

fn total(&self) -> Balance;
}

/// Trait to signal an epoch transition.
pub trait EpochTransitionHook {
type Balance;
Expand All @@ -333,7 +341,7 @@ pub trait EpochTransitionHook {
fn on_closing_mutate_reserve(
pool_id: Self::PoolId,
assets_under_management: Self::Balance,
reserve: &mut Self::Balance,
reserve: &mut impl Reserve<Self::Balance>,
) -> Result<(), Self::Error>;

/// Hook into the execution of an epoch before any investment and
Expand Down
25 changes: 10 additions & 15 deletions pallets/investments/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,13 @@ impl<T: Config> OrderManager for Pallet<T> {
},
)?;

// NOTE: The accountant already receives the current amount of investments
T::Accountant::debit(
investment_id,
&InvestmentAccount { investment_id }.into_account_truncating(),
total_orders.amount,
)?;

let order_id = InvestOrderId::<T>::try_mutate(
investment_id,
|order_id| -> Result<OrderId, DispatchError> {
Expand Down Expand Up @@ -1264,13 +1271,8 @@ impl<T: Config> OrderManager for Pallet<T> {
InvestmentAccount { investment_id }.into_account_truncating();
let info = T::Accountant::info(investment_id)?;

T::Tokens::transfer(
info.payment_currency,
&investment_account,
&info.owner,
invest_amount,
Preservation::Expendable,
)?;
// NOTE: The accountant gives back what he did not used for the investment
T::Accountant::credit(investment_id, &investment_account, remaining_invest_amount)?;

// The amount of investments the accountant needs to
// note newly in his books is the invest amount divide through
Expand Down Expand Up @@ -1356,14 +1358,7 @@ impl<T: Config> OrderManager for Pallet<T> {
InvestmentAccount { investment_id }.into_account_truncating();
let info = T::Accountant::info(investment_id)?;

T::Tokens::transfer(
info.payment_currency,
&info.owner,
&investment_account,
redeem_amount_payment,
Preservation::Expendable,
)?;

T::Accountant::credit(investment_id, &investment_account, redeem_amount_payment)?;
T::Accountant::withdraw(&investment_account, info.id, redeem_amount)?;

// The previous OrderId is always 1 away
Expand Down
21 changes: 11 additions & 10 deletions pallets/pool-fees/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ pub mod pallet {
use cfg_traits::{
changes::ChangeGuard,
fee::{FeeAmountProration, PoolFeeBucket, PoolFeesInspect, PoolFeesMutate},
EpochTransitionHook, PoolInspect, PoolNAV, PoolReserve, PreConditions, Seconds, TimeAsSecs,
EpochTransitionHook, PoolInspect, PoolNAV, PoolReserve, PreConditions, Reserve, Seconds,
TimeAsSecs,
};
use cfg_types::{
pools::{
Expand Down Expand Up @@ -615,10 +616,10 @@ pub mod pallet {
pub(crate) fn update_active_fees(
pool_id: T::PoolId,
bucket: PoolFeeBucket,
reserve: &mut T::Balance,
reserve: &mut impl Reserve<T::Balance>,
assets_under_management: T::Balance,
epoch_duration: Seconds,
) -> Result<T::Balance, DispatchError> {
) -> Result<impl Reserve<T::Balance>, DispatchError> {
ActiveFees::<T>::mutate(pool_id, bucket, |fees| {
for fee in fees.iter_mut() {
let limit = fee.amounts.limit();
Expand Down Expand Up @@ -648,8 +649,8 @@ pub mod pallet {
.map_err(|e: DispatchError| e)?;

// Disbursement amount is limited by reserve
let disbursement = fee_amount.min(*reserve);
reserve.ensure_sub_assign(disbursement)?;
let disbursement = fee_amount.min(reserve.total());
reserve.withdraw(disbursement)?;

// Update fee amounts
fee.amounts.pending.ensure_sub_assign(disbursement)?;
Expand All @@ -672,7 +673,7 @@ pub mod pallet {
Ok::<(), DispatchError>(())
})?;

Ok(*reserve)
Ok(reserve)
}

/// Entirely remove a stored fee from the given pair of pool id and fee
Expand Down Expand Up @@ -738,7 +739,7 @@ pub mod pallet {
/// ```
pub fn update_portfolio_valuation_for_pool(
pool_id: T::PoolId,
reserve: &mut T::Balance,
reserve: &mut impl Reserve<T::Balance>,
) -> Result<(T::Balance, u32), DispatchError> {
let fee_nav = PortfolioValuation::<T>::get(pool_id);
let aum = AssetsUnderManagement::<T>::get(pool_id);
Expand Down Expand Up @@ -859,17 +860,17 @@ pub mod pallet {
fn on_closing_mutate_reserve(
pool_id: Self::PoolId,
assets_under_management: Self::Balance,
reserve: &mut Self::Balance,
reserve: &mut impl Reserve<Self::Balance>,
) -> Result<(), Self::Error> {
// Determine pending fees and NAV based on last epoch's AUM
let res_pre_fees = *reserve;
let res_pre_fees = reserve.total();
Self::update_portfolio_valuation_for_pool(pool_id, reserve)?;

// Set current AUM for next epoch's closing
AssetsUnderManagement::<T>::insert(pool_id, assets_under_management);

// Transfer disbursement amount from pool account to pallet sovereign account
let total_fee_amount = res_pre_fees.saturating_sub(*reserve);
let total_fee_amount = res_pre_fees.saturating_sub(reserve.total());
if !total_fee_amount.is_zero() {
let pool_currency =
T::PoolReserve::currency_for(pool_id).ok_or(Error::<T>::PoolNotFound)?;
Expand Down
16 changes: 16 additions & 0 deletions pallets/pool-system/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,22 @@ impl<T: Config> InvestmentAccountant<T::AccountId> for Pallet<T> {
T::Tokens::transfer(id.into(), source, dest, amount, Preservation::Expendable).map(|_| ())
}

fn debit(
id: Self::InvestmentId,
from: &T::AccountId,
amount: Self::Amount,
) -> sp_runtime::DispatchResult {
Self::do_debit(id.of_pool(), from, amount)
}

fn credit(
id: Self::InvestmentId,
to: &T::AccountId,
amount: Self::Amount,
) -> sp_runtime::DispatchResult {
Self::do_credit(id.of_pool(), to, amount)
}

fn deposit(
buyer: &T::AccountId,
id: Self::InvestmentId,
Expand Down
Loading