Skip to content

Commit

Permalink
fix: use remaining collectable redemption amount
Browse files Browse the repository at this point in the history
  • Loading branch information
wischli committed Aug 17, 2023
1 parent 845c1b5 commit 2678851
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 96 deletions.
7 changes: 4 additions & 3 deletions libs/traits/src/investments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,23 +91,24 @@ pub trait Investment<AccountId> {
pub trait InvestmentCollector<AccountId> {
type Error: Debug;
type InvestmentId;
type Result: Debug;
type InvestResult: Debug;
type RedeemResult: Debug;

/// Collect the results of a user's invest orders for the given
/// investment. If any amounts are not fulfilled they are directly
/// appended to the next active order for this investment.
fn collect_investment(
who: AccountId,
investment_id: Self::InvestmentId,
) -> Result<Self::Result, Self::Error>;
) -> Result<Self::InvestResult, Self::Error>;

/// Collect the results of a users redeem orders for the given
/// investment. If any amounts are not fulfilled they are directly
/// appended to the next active order for this investment.
fn collect_redemption(
who: AccountId,
investment_id: Self::InvestmentId,
) -> Result<Self::Result, Self::Error>;
) -> Result<Self::RedeemResult, Self::Error>;
}

/// A trait, when implemented must take care of
Expand Down
29 changes: 20 additions & 9 deletions libs/types/src/investments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,21 +136,32 @@ impl<Balance: Zero + Copy> RedeemCollection<Balance> {
}
}

/// The collected investment/redemption amount for an account
/// The collected investment amounts for an account
#[derive(Encode, Default, Decode, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub struct CollectedAmount<Balance: Default + MaxEncodedLen> {
/// The amount which was was collected
/// * If investment: Tranche tokens
/// * If redemption: Payment currency
pub struct CollectedInvestment<Balance: Default + MaxEncodedLen> {
/// The amount of tranche tokens which was was collected
pub amount_collected: Balance,

/// The amount which invested and converted during processing based on the
/// fulfillment price(s)
/// * If investment: Payment currency
/// * If redemption: Tranche tokens
/// The previously invested amount of payment currency which was converted
/// during processing based on the fulfillment price(s)
pub amount_payment: Balance,
}

/// The collected redemption amounts for an account
#[derive(Encode, Default, Decode, Clone, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub struct CollectedRedemption<Balance: Default + MaxEncodedLen> {
/// The amount of payment currency which was was collected
pub amount_collected: Balance,

/// The previously invested amount of tranche tokens which was converted
/// during processing based on the fulfillment price(s)
pub amount_payment: Balance,

/// The remaining collectable amount which was already processed during
/// epoch execution
pub amount_remaining_collectable: Balance,
}

/// A representation of an investment identifier and the corresponding owner.
///
/// NOTE: Trimmed version of `InvestmentInfo` required for foreign investments.
Expand Down
32 changes: 18 additions & 14 deletions pallets/foreign-investments/src/impls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use cfg_traits::{
StatusNotificationHook, TokenSwaps,
};
use cfg_types::investments::{
CollectedAmount, ExecutedForeignCollectInvest, ExecutedForeignCollectRedeem,
CollectedInvestment, ExecutedForeignCollectInvest, ExecutedForeignCollectRedeem,
ExecutedForeignDecrease, Swap,
};
use frame_support::{traits::Get, transactional};
Expand All @@ -30,7 +30,7 @@ use crate::{
InnerRedeemState, InvestState, InvestTransition, RedeemState, RedeemTransition,
TokenSwapReason,
},
CollectedRedemption, Config, Error, Event, ForeignInvestmentInfo, ForeignInvestmentInfoOf,
CollectedRedemptions, Config, Error, Event, ForeignInvestmentInfo, ForeignInvestmentInfoOf,
InvestmentState, Pallet, RedemptionState, SwapOf, TokenSwapOrderIds, TokenSwapReasons,
};

Expand Down Expand Up @@ -153,7 +153,7 @@ impl<T: Config> ForeignInvestment<T::AccountId> for Pallet<T> {
) -> Result<ExecutedForeignCollectInvest<T::Balance>, DispatchError> {
// No need to transition or update state as collection of tranche tokens is
// independent of the current `InvestState`
let CollectedAmount::<T::Balance> {
let CollectedInvestment::<T::Balance> {
amount_collected,
amount_payment,
} = T::Investment::collect_investment(who.clone(), investment_id)?;
Expand All @@ -173,10 +173,11 @@ impl<T: Config> ForeignInvestment<T::AccountId> for Pallet<T> {
pool_currency: T::CurrencyId,
) -> Result<(), DispatchError> {
let collected = T::Investment::collect_redemption(who.clone(), investment_id)?;
CollectedRedemption::<T>::try_mutate(who, investment_id, |collected_redemption| {
CollectedRedemptions::<T>::try_mutate(who, investment_id, |collected_redemption| {
collected_redemption
.amount_collected
.ensure_add_assign(collected.amount_collected)?;
// TODO: We only need this at a later stage
collected_redemption
.amount_payment
.ensure_add_assign(collected.amount_payment)?;
Expand All @@ -186,11 +187,14 @@ impl<T: Config> ForeignInvestment<T::AccountId> for Pallet<T> {

// Transition state to initiate swap from pool to return currency
let pre_state = RedemptionState::<T>::get(who, investment_id.clone()).unwrap_or_default();
let post_state = pre_state.transition(RedeemTransition::Collect(SwapOf::<T> {
amount: collected.amount_collected,
currency_in: return_currency,
currency_out: pool_currency,
}))?;
let post_state = pre_state.transition(RedeemTransition::Collect(
SwapOf::<T> {
amount: collected.amount_collected,
currency_in: return_currency,
currency_out: pool_currency,
},
collected.amount_remaining_collectable,
))?;

Pallet::<T>::apply_redeem_state_transition(who, investment_id, post_state)?;

Expand Down Expand Up @@ -537,9 +541,9 @@ impl<T: Config> Pallet<T> {
inner_redeem_state: InnerRedeemState<T::Balance, T::CurrencyId>,
) -> Result<Option<RedeemState<T::Balance, T::CurrencyId>>, DispatchError> {
// TODO: Should just be amount and maybe factor in the remaining amount as well
let collected_redemption = CollectedRedemption::<T>::get(who, investment_id);
let collected_redemption = CollectedRedemptions::<T>::get(who, investment_id);

// Send notification and kill `CollectedRedemption` iff the state includes
// Send notification and kill `CollectedRedemptions` iff the state includes
// `SwapIntoReturnDone` without `ActiveSwapIntoReturnCurrency`
match inner_redeem_state {
InnerRedeemState::SwapIntoReturnDone { done_swap, .. }
Expand All @@ -553,12 +557,12 @@ impl<T: Config> Pallet<T> {
who,
investment_id,
done_swap.currency_in,
CollectedAmount {
CollectedInvestment {
amount_collected: done_swap.amount,
amount_payment: collected_redemption.amount_payment,
},
)?;
CollectedRedemption::<T>::remove(who, investment_id);
CollectedRedemptions::<T>::remove(who, investment_id);
Ok(())
}
_ => Ok(()),
Expand Down Expand Up @@ -949,7 +953,7 @@ impl<T: Config> Pallet<T> {
who: &T::AccountId,
investment_id: T::InvestmentId,
currency: T::CurrencyId,
collected: CollectedAmount<T::Balance>,
collected: CollectedInvestment<T::Balance>,
) -> DispatchResult {
T::ExecutedCollectRedeemHook::notify_status_change(
ForeignInvestmentInfoOf::<T> {
Expand Down
Loading

0 comments on commit 2678851

Please sign in to comment.