From d78fe432b4120ccb9b21cfa33a59c3f29d9ce9e6 Mon Sep 17 00:00:00 2001 From: Juan Girini Date: Mon, 24 Feb 2025 13:37:17 +0100 Subject: [PATCH] feat: add fees and deposit management --- pallets/idn-manager/src/impls.rs | 65 ++++++++----- pallets/idn-manager/src/lib.rs | 85 +++++++++++++--- pallets/idn-manager/src/tests/fee_examples.rs | 96 ++++++++++--------- pallets/idn-manager/src/tests/pallet.rs | 11 ++- pallets/idn-manager/src/traits.rs | 30 +++--- 5 files changed, 187 insertions(+), 100 deletions(-) diff --git a/pallets/idn-manager/src/impls.rs b/pallets/idn-manager/src/impls.rs index 2f4673e..82c72a3 100644 --- a/pallets/idn-manager/src/impls.rs +++ b/pallets/idn-manager/src/impls.rs @@ -18,7 +18,7 @@ use crate::{ self as pallet_idn_manager, - traits::{DiffFees, FeesDirection, FeesError}, + traits::{BalanceDirection, DiffBalance, FeesError}, HoldReason, Subscription, SubscriptionTrait, }; use codec::Encode; @@ -63,7 +63,7 @@ impl< T: Get, B: Get, S: SubscriptionTrait, - BlockNumber: Saturating + Ord, + BlockNumber: Saturating + Ord + Clone, Balances: Mutate, > pallet_idn_manager::FeesManager for FeesManagerImpl @@ -71,38 +71,42 @@ where Balances::Balance: From, Balances::Reason: From, { - fn calculate_subscription_fees(amount: BlockNumber) -> Balances::Balance { + fn calculate_subscription_fees(amount: &BlockNumber) -> Balances::Balance { let base_fee = B::get(); - base_fee.saturating_mul(amount.into()) + base_fee.saturating_mul(amount.clone().into()) } fn calculate_diff_fees( - old_amount: BlockNumber, - new_amount: BlockNumber, - ) -> DiffFees { - let mut direction = FeesDirection::None; + old_amount: &BlockNumber, + new_amount: &BlockNumber, + ) -> DiffBalance { + let mut direction = BalanceDirection::None; let fees = match new_amount.cmp(&old_amount) { Ordering::Greater => { - direction = FeesDirection::Hold; - Self::calculate_subscription_fees(new_amount.saturating_sub(old_amount)) + direction = BalanceDirection::Hold; + Self::calculate_subscription_fees( + &new_amount.clone().saturating_sub(old_amount.clone()), + ) }, Ordering::Less => { - direction = FeesDirection::Release; - Self::calculate_subscription_fees(old_amount.saturating_sub(new_amount)) + direction = BalanceDirection::Release; + Self::calculate_subscription_fees( + &old_amount.clone().saturating_sub(new_amount.clone()), + ) }, Ordering::Equal => Zero::zero(), }; - DiffFees { fees, direction } + DiffBalance { balance: fees, direction } } fn collect_fees( - fees: Balances::Balance, - sub: S, + fees: &Balances::Balance, + sub: &S, ) -> Result> { // Collect the held fees from the subscriber let collected = Balances::transfer_on_hold( &HoldReason::Fees.into(), sub.subscriber(), &T::get(), - fees, + fees.clone(), Precision::BestEffort, Restriction::Free, Fortitude::Polite, @@ -111,29 +115,40 @@ where // Ensure the correct amount was collected. // TODO: error to bubble up and be handled by caller https://github.com/ideal-lab5/idn-sdk/issues/107 - if collected < fees { - return Err(FeesError::NotEnoughBalance { needed: fees, balance: collected }); + if collected < *fees { + return Err(FeesError::NotEnoughBalance { needed: *fees, balance: collected }); } Ok(collected) } } -pub struct DepositCalculatorImpl, Balance> { - pub _phantom: (PhantomData, PhantomData), +pub struct DepositCalculatorImpl, Deposit> { + pub _phantom: (PhantomData, PhantomData), } impl< S: SubscriptionTrait + Encode, - SDMultiplier: Get, - Balance: From + Saturating, - > pallet_idn_manager::DepositCalculator - for DepositCalculatorImpl + SDMultiplier: Get, + Deposit: From + Saturating + Ord, + > pallet_idn_manager::DepositCalculator + for DepositCalculatorImpl { - fn calculate_storage_deposit(sub: &S) -> Balance { + fn calculate_storage_deposit(sub: &S) -> Deposit { let storage_deposit_multiplier = SDMultiplier::get(); // calculate the size of scale encoded `sub` let encoded_size = sub.encode().len() as u32; storage_deposit_multiplier.saturating_mul(encoded_size.into()) } + + fn calculate_diff_deposit(old_sub: &S, new_sub: &S) -> DiffBalance { + let old_deposit = Self::calculate_storage_deposit(old_sub); + let new_deposit = Self::calculate_storage_deposit(new_sub); + let direction = match new_deposit.cmp(&old_deposit) { + Ordering::Greater => BalanceDirection::Hold, + Ordering::Less => BalanceDirection::Release, + Ordering::Equal => BalanceDirection::None, + }; + DiffBalance { balance: new_deposit.saturating_sub(old_deposit), direction } + } } diff --git a/pallets/idn-manager/src/lib.rs b/pallets/idn-manager/src/lib.rs index bb5fecc..7bac444 100644 --- a/pallets/idn-manager/src/lib.rs +++ b/pallets/idn-manager/src/lib.rs @@ -66,6 +66,7 @@ use frame_support::{ sp_runtime::traits::AccountIdConversion, traits::{ fungible::{hold::Mutate as HoldMutate, Inspect}, + tokens::Precision, Get, }, BoundedVec, @@ -79,7 +80,10 @@ use sp_arithmetic::traits::Unsigned; use sp_core::H256; use sp_io::hashing::blake2_256; use sp_std::fmt::Debug; -use traits::{DepositCalculator, FeesManager, Subscription as SubscriptionTrait}; +use traits::{ + BalanceDirection, DepositCalculator, DiffBalance, FeesManager, + Subscription as SubscriptionTrait, +}; use xcm::{ v5::{prelude::*, Location}, VersionedLocation, VersionedXcm, @@ -246,8 +250,8 @@ pub mod pallet { SubscriptionAlreadyPaused, /// The origin isn't the subscriber NotSubscriber, - /// Insufficient balance for subscription - InsufficientBalance, + // /// Insufficient balance for subscription + // InsufficientBalance, } /// A reason for the IDN Manager Pallet placing a hold on funds. @@ -352,11 +356,25 @@ pub mod pallet { Subscriptions::::try_mutate(sub_id, |maybe_sub| { let sub = maybe_sub.as_mut().ok_or(Error::::SubscriptionDoesNotExist)?; ensure!(sub.details.subscriber == subscriber, Error::::NotSubscriber); + + let fees_diff = T::FeesManager::calculate_diff_fees(&sub.details.amount, &amount); + let deposit_diff = T::DepositCalculator::calculate_diff_deposit( + &sub, + &Subscription { + state: sub.state.clone(), + credits_left: amount, + details: sub.details.clone(), + }, + ); + sub.details.amount = amount; sub.details.frequency = frequency; sub.details.updated_at = frame_system::Pallet::::block_number(); - // TODO implement a way to refund or take the difference in fees https://github.com/ideal-lab5/idn-sdk/issues/104 - // Self::manage_fees_and_deposit() + + // Hold or refund diff fees + Self::manage_diff_fees(&subscriber, &fees_diff)?; + // Hold or refund diff deposit + Self::manage_diff_deposit(&subscriber, &deposit_diff)?; Self::deposit_event(Event::SubscriptionUpdated { sub_id }); Ok(()) }) @@ -431,9 +449,9 @@ impl Pallet { metadata: Option>, ) -> DispatchResult { // Calculate and hold the subscription fees - let fees = T::FeesManager::calculate_subscription_fees(amount); - T::Currency::hold(&HoldReason::Fees.into(), &subscriber, fees) - .map_err(|_| Error::::InsufficientBalance)?; + let fees = T::FeesManager::calculate_subscription_fees(&amount); + + Self::hold_fees(&subscriber, fees)?; let current_block = frame_system::Pallet::::block_number(); let details = SubscriptionDetails { @@ -448,12 +466,10 @@ impl Pallet { let subscription = Subscription { state: SubscriptionState::Active, credits_left: amount, details }; - T::Currency::hold( - &HoldReason::StorageDeposit.into(), + Self::hold_deposit( &subscriber, T::DepositCalculator::calculate_storage_deposit(&subscription), - ) - .map_err(|_| Error::::InsufficientBalance)?; + )?; let sub_id = subscription.id(); @@ -466,6 +482,51 @@ impl Pallet { Ok(()) } + fn hold_fees(subscriber: &T::AccountId, fees: BalanceOf) -> DispatchResult { + T::Currency::hold(&HoldReason::Fees.into(), subscriber, fees) + } + + fn release_fees(subscriber: &T::AccountId, fees: BalanceOf) -> DispatchResult { + let _ = T::Currency::release(&HoldReason::Fees.into(), subscriber, fees, Precision::Exact)?; + Ok(()) + } + + fn manage_diff_fees( + subscriber: &T::AccountId, + diff: &DiffBalance>, + ) -> DispatchResult { + match diff.direction { + BalanceDirection::Hold => Self::hold_fees(subscriber, diff.balance), + BalanceDirection::Release => Self::release_fees(subscriber, diff.balance), + BalanceDirection::None => Ok(()), + } + } + + fn hold_deposit(subscriber: &T::AccountId, deposit: BalanceOf) -> DispatchResult { + T::Currency::hold(&HoldReason::StorageDeposit.into(), subscriber, deposit) + } + + fn release_deposit(subscriber: &T::AccountId, deposit: BalanceOf) -> DispatchResult { + let _ = T::Currency::release( + &HoldReason::StorageDeposit.into(), + subscriber, + deposit, + Precision::BestEffort, + )?; + Ok(()) + } + + fn manage_diff_deposit( + subscriber: &T::AccountId, + diff: &DiffBalance>, + ) -> DispatchResult { + match diff.direction { + BalanceDirection::Hold => Self::hold_deposit(subscriber, diff.balance), + BalanceDirection::Release => Self::release_deposit(subscriber, diff.balance), + BalanceDirection::None => Ok(()), + } + } + /// Helper function to construct XCM message for randomness distribution // TODO: finish this off as part of https://github.com/ideal-lab5/idn-sdk/issues/77 fn construct_randomness_xcm(target: Location, _rnd: &T::Rnd) -> Result, Error> { diff --git a/pallets/idn-manager/src/tests/fee_examples.rs b/pallets/idn-manager/src/tests/fee_examples.rs index 986aaf8..0b71358 100644 --- a/pallets/idn-manager/src/tests/fee_examples.rs +++ b/pallets/idn-manager/src/tests/fee_examples.rs @@ -18,7 +18,7 @@ //! //! This module contains examples of fee calculators that can be used in the IDN Manager pallet. -use crate::traits::{DiffFees, FeesDirection, FeesManager}; +use crate::traits::{BalanceDirection, DiffBalance, FeesManager}; use sp_runtime::traits::Zero; use sp_std::cmp::Ordering; @@ -28,27 +28,31 @@ pub struct LinearFeeCalculator; const BASE_FEE: u32 = 100; impl FeesManager for LinearFeeCalculator { - fn calculate_subscription_fees(amount: u32) -> u32 { - BASE_FEE.saturating_mul(amount.into()) + fn calculate_subscription_fees(amount: &u32) -> u32 { + BASE_FEE.saturating_mul(amount.clone().into()) } - fn calculate_diff_fees(old_amount: u32, new_amount: u32) -> DiffFees { - let mut direction = FeesDirection::None; + fn calculate_diff_fees(old_amount: &u32, new_amount: &u32) -> DiffBalance { + let mut direction = BalanceDirection::None; let fees = match new_amount.cmp(&old_amount) { Ordering::Greater => { - direction = FeesDirection::Hold; - Self::calculate_subscription_fees(new_amount.saturating_sub(old_amount)) + direction = BalanceDirection::Hold; + Self::calculate_subscription_fees( + &new_amount.clone().saturating_sub(old_amount.clone()), + ) }, Ordering::Less => { - direction = FeesDirection::Release; - Self::calculate_subscription_fees(old_amount.saturating_sub(new_amount)) + direction = BalanceDirection::Release; + Self::calculate_subscription_fees( + &old_amount.clone().saturating_sub(new_amount.clone()), + ) }, Ordering::Equal => Zero::zero(), }; - DiffFees { fees, direction } + DiffBalance { balance: fees, direction } } - fn collect_fees(fees: u32, _: ()) -> Result> { + fn collect_fees(fees: &u32, _: &()) -> Result> { // In this case, we don't need to do anything with the fees, so we just return them - Ok(fees) + Ok(*fees) } } @@ -56,7 +60,7 @@ impl FeesManager for LinearFeeCalculator { pub struct SteppedTieredFeeCalculator; impl FeesManager for SteppedTieredFeeCalculator { - fn calculate_subscription_fees(amount: u32) -> u32 { + fn calculate_subscription_fees(amount: &u32) -> u32 { // Define tier boundaries and their respective discount rates (in basis points) const TIERS: [(u32, u32); 5] = [ (1, 0), // 0-10: 0% discount @@ -67,17 +71,17 @@ impl FeesManager for SteppedTieredFeeCalculator { ]; let mut total_fee = 0u32; - let mut remaining_amount = amount; + let mut remaining_amount = *amount; for (i, &(current_tier_start, current_tier_discount)) in TIERS.iter().enumerate() { // If no remaining credits or the tier starts above the requested amount, exit loop. - if remaining_amount == 0 || amount < current_tier_start { + if remaining_amount == 0 || amount < ¤t_tier_start { break; } let next_tier_start = TIERS.get(i + 1).map(|&(start, _)| start).unwrap_or(u32::MAX); let credits_in_tier = - (amount.min(next_tier_start.saturating_sub(1)) - current_tier_start + 1) + (amount.min(&next_tier_start.saturating_sub(1)) - current_tier_start + 1) .min(remaining_amount); let tier_fee = BASE_FEE @@ -92,26 +96,26 @@ impl FeesManager for SteppedTieredFeeCalculator { total_fee } - fn calculate_diff_fees(old_amount: u32, new_amount: u32) -> DiffFees { + fn calculate_diff_fees(old_amount: &u32, new_amount: &u32) -> DiffBalance { let old_fees = Self::calculate_subscription_fees(old_amount); let new_fees = Self::calculate_subscription_fees(new_amount); - let mut direction = FeesDirection::None; + let mut direction = BalanceDirection::None; let fees = match new_fees.cmp(&old_fees) { Ordering::Greater => { - direction = FeesDirection::Hold; + direction = BalanceDirection::Hold; new_fees - old_fees }, Ordering::Less => { - direction = FeesDirection::Release; + direction = BalanceDirection::Release; old_fees - new_fees }, Ordering::Equal => Zero::zero(), }; - DiffFees { fees, direction } + DiffBalance { balance: fees, direction } } - fn collect_fees(fees: u32, _: ()) -> Result> { + fn collect_fees(fees: &u32, _: &()) -> Result> { // In this case, we don't need to do anything with the fees, so we just return them - Ok(fees) + Ok(*fees) } } @@ -121,9 +125,9 @@ mod tests { #[test] fn test_linear_fee_calculator() { - assert_eq!(LinearFeeCalculator::calculate_subscription_fees(1), 100); - assert_eq!(LinearFeeCalculator::calculate_subscription_fees(10), 1_000); - assert_eq!(LinearFeeCalculator::calculate_subscription_fees(100), 10_000); + assert_eq!(LinearFeeCalculator::calculate_subscription_fees(&1), 100); + assert_eq!(LinearFeeCalculator::calculate_subscription_fees(&10), 1_000); + assert_eq!(LinearFeeCalculator::calculate_subscription_fees(&100), 10_000); } /// Thest when a subscription is fully used before being killed or the update does not change @@ -132,12 +136,12 @@ mod tests { fn test_calculate_release_linear_fees_no_diff() { let old_amount: u32 = 50; let new_amount: u32 = 50; // no credits diff - let refund = LinearFeeCalculator::calculate_diff_fees(old_amount, new_amount); + let refund = LinearFeeCalculator::calculate_diff_fees(&old_amount, &new_amount); // there should be no refund as all credit has been used, or no difference in the update let expected = 0; assert_eq!( refund, - DiffFees { fees: expected, direction: FeesDirection::None }, + DiffBalance { balance: expected, direction: BalanceDirection::None }, "There should be no release when no diff in amount" ); } @@ -147,11 +151,11 @@ mod tests { fn test_calculate_release_linear_fees_lower_diff() { let old_amount: u32 = 50; let new_amount: u32 = 30; // 20 credits used - let refund = LinearFeeCalculator::calculate_diff_fees(old_amount, new_amount); + let refund = LinearFeeCalculator::calculate_diff_fees(&old_amount, &new_amount); let expected = 20 * BASE_FEE; assert_eq!( refund, - DiffFees { fees: expected, direction: FeesDirection::Release }, + DiffBalance { balance: expected, direction: BalanceDirection::Release }, "There should be a release when new amount is lower than old amount" ); } @@ -161,11 +165,11 @@ mod tests { fn test_calculate_hold_linear_fees_greater_diff() { let old_amount: u32 = 50; let new_amount: u32 = 60; // all credits used - let refund = LinearFeeCalculator::calculate_diff_fees(old_amount, new_amount); + let refund = LinearFeeCalculator::calculate_diff_fees(&old_amount, &new_amount); let expected = 10 * BASE_FEE; assert_eq!( refund, - DiffFees { fees: expected, direction: FeesDirection::Hold }, + DiffBalance { balance: expected, direction: BalanceDirection::Hold }, "There should be more held balance" ); } @@ -173,18 +177,18 @@ mod tests { #[test] fn test_stepped_tiered_calculator() { // Test first tier (no discount) - assert_eq!(SteppedTieredFeeCalculator::calculate_subscription_fees(10), 1_000); // 10 * 100 = 1,000 + assert_eq!(SteppedTieredFeeCalculator::calculate_subscription_fees(&10), 1_000); // 10 * 100 = 1,000 // Test crossing into second tier - let fee_11 = SteppedTieredFeeCalculator::calculate_subscription_fees(11); + let fee_11 = SteppedTieredFeeCalculator::calculate_subscription_fees(&11); assert_eq!(fee_11, 1_095); // (10 * 100) + (1 * 95) = 1,000 + 95 = 1,095 // Test middle of second tier - let fee_50 = SteppedTieredFeeCalculator::calculate_subscription_fees(50); + let fee_50 = SteppedTieredFeeCalculator::calculate_subscription_fees(&50); assert_eq!(fee_50, 4_800); // (10 * 100) + (40 * 95) = 1,000 + 3,800 = 4,800 // Test crossing multiple tiers - let fee_150 = SteppedTieredFeeCalculator::calculate_subscription_fees(150); + let fee_150 = SteppedTieredFeeCalculator::calculate_subscription_fees(&150); // First 10 at 100% = 1,000 // Next 90 at 95% = 8,550 // Next 50 at 90% = 4,500 @@ -195,13 +199,13 @@ mod tests { #[test] fn test_no_price_inversion() { // Test that buying more never costs less - let fee_10 = SteppedTieredFeeCalculator::calculate_subscription_fees(10); - let fee_11 = SteppedTieredFeeCalculator::calculate_subscription_fees(11); + let fee_10 = SteppedTieredFeeCalculator::calculate_subscription_fees(&10); + let fee_11 = SteppedTieredFeeCalculator::calculate_subscription_fees(&11); assert!(fee_11 > fee_10, "11 credits should cost more than 10 credits"); // Test around the 100 credit boundary - let fee_100 = SteppedTieredFeeCalculator::calculate_subscription_fees(100); - let fee_101 = SteppedTieredFeeCalculator::calculate_subscription_fees(101); + let fee_100 = SteppedTieredFeeCalculator::calculate_subscription_fees(&100); + let fee_101 = SteppedTieredFeeCalculator::calculate_subscription_fees(&101); assert!(fee_101 > fee_100, "101 credits should cost more than 100 credits"); } @@ -211,11 +215,11 @@ mod tests { fn test_calculate_release_stepped_fees_no_diff() { let old_amount: u32 = 50; let new_amount: u32 = 50; // no credits diff - let refund = SteppedTieredFeeCalculator::calculate_diff_fees(old_amount, new_amount); + let refund = SteppedTieredFeeCalculator::calculate_diff_fees(&old_amount, &new_amount); let expected = 0; assert_eq!( refund, - DiffFees { fees: expected, direction: FeesDirection::None }, + DiffBalance { balance: expected, direction: BalanceDirection::None }, "There should be no release when no diff in amount" ); } @@ -225,11 +229,11 @@ mod tests { fn test_calculate_release_stepped_fees_lower_diff() { let old_amount: u32 = 110; let new_amount: u32 = 100; // 1 value decrease - let refund = SteppedTieredFeeCalculator::calculate_diff_fees(old_amount, new_amount); + let refund = SteppedTieredFeeCalculator::calculate_diff_fees(&old_amount, &new_amount); let expected = 10 * BASE_FEE.saturating_mul(9_000).saturating_div(10_000); // 10% discount on the extra value assert_eq!( refund, - DiffFees { fees: expected, direction: FeesDirection::Release }, + DiffBalance { balance: expected, direction: BalanceDirection::Release }, "There should be a release when new amount is lower than old amount" ); } @@ -239,11 +243,11 @@ mod tests { fn test_calculate_hold_stepped_fees_greater_diff() { let old_amount: u32 = 100; let new_amount: u32 = 101; // 1 value increase - let refund = SteppedTieredFeeCalculator::calculate_diff_fees(old_amount, new_amount); + let refund = SteppedTieredFeeCalculator::calculate_diff_fees(&old_amount, &new_amount); let expected = 1 * BASE_FEE.saturating_mul(9_000).saturating_div(10_000); // 10% discount on the extra value assert_eq!( refund, - DiffFees { fees: expected, direction: FeesDirection::Hold }, + DiffBalance { balance: expected, direction: BalanceDirection::Hold }, "There should be more held balance" ); } diff --git a/pallets/idn-manager/src/tests/pallet.rs b/pallets/idn-manager/src/tests/pallet.rs index a0e700e..939ee6f 100644 --- a/pallets/idn-manager/src/tests/pallet.rs +++ b/pallets/idn-manager/src/tests/pallet.rs @@ -32,7 +32,7 @@ use frame_support::{ }; use idn_traits::rand::Dispatcher; use sp_core::H256; -use sp_runtime::AccountId32; +use sp_runtime::{AccountId32, TokenError}; use xcm::v5::{Junction, Location}; const ALICE: AccountId32 = AccountId32::new([1u8; 32]); @@ -75,7 +75,7 @@ fn create_subscription_works() { let (sub_id, subscription) = Subscriptions::::iter().next().unwrap(); // assert that the correct fees have been held - let fees = ::FeesManager::calculate_subscription_fees(amount); + let fees = ::FeesManager::calculate_subscription_fees(&amount); let deposit = ::DepositCalculator::calculate_storage_deposit(&subscription); assert_eq!(Balances::free_balance(&ALICE), initial_balance - fees - deposit); assert_eq!(Balances::balance_on_hold(&HoldReason::Fees.into(), &ALICE), fees); @@ -113,7 +113,7 @@ fn create_subscription_fails_if_insufficient_balance() { frequency, None ), - Error::::InsufficientBalance + TokenError::FundsUnavailable ); // Assert the SubscriptionCreated event was not emitted @@ -267,7 +267,7 @@ fn test_update_subscription() { let (sub_id, subscription) = Subscriptions::::iter().next().unwrap(); let original_fees = - ::FeesManager::calculate_subscription_fees(original_amount); + ::FeesManager::calculate_subscription_fees(&original_amount); let original_deposit = ::DepositCalculator::calculate_storage_deposit(&subscription); let balance_after_create = initial_balance - original_fees - original_deposit; @@ -287,11 +287,12 @@ fn test_update_subscription() { new_frequency )); - let new_fees = ::FeesManager::calculate_subscription_fees(new_amount); + let new_fees = ::FeesManager::calculate_subscription_fees(&new_amount); let new_deposit = ::DepositCalculator::calculate_storage_deposit(&subscription); let fees_diff = new_fees - original_fees; + // TODO: test a diff > 0 let deposit_diff = new_deposit - original_deposit; let balance_after_update = balance_after_create - fees_diff - deposit_diff; diff --git a/pallets/idn-manager/src/traits.rs b/pallets/idn-manager/src/traits.rs index 6a79a7d..f1deb0c 100644 --- a/pallets/idn-manager/src/traits.rs +++ b/pallets/idn-manager/src/traits.rs @@ -24,38 +24,38 @@ pub enum FeesError { Other(Context), } -/// Enum to represent the direction of fees movement. +/// Enum to represent the direction of balance movement. #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum FeesDirection { +pub enum BalanceDirection { Hold, Release, - // Fees aren't going anywhere. This is usually the case when diff is zero. + // Balance isn't going anywhere. This is usually the case when diff is zero. None, } -/// This struct represent movement of fees. +/// This struct represent movement of balance. /// -/// * `fees` - how much fees are being moved. -/// * `direction` - if the fees are being collected or released. +/// * `balance` - how much balance being moved. +/// * `direction` - if the balance are being collected or released. #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct DiffFees { - pub fees: Fees, - pub direction: FeesDirection, +pub struct DiffBalance { + pub balance: Balance, + pub direction: BalanceDirection, } /// Trait for fees managing pub trait FeesManager, Err, S> { /// Calculate the fees for a subscription based on the amount of random values required. - fn calculate_subscription_fees(amount: Amount) -> Fees; + fn calculate_subscription_fees(amount: &Amount) -> Fees; /// Calculate how much fees should be held or release when a subscription changes. /// /// * `old_amount` - the amount of random values required before the change. /// * `new_amount` - the amount of random values required after the change, this will represent /// the updated amount in an update operation. Or the amount actually consumed in a kill /// operation. - fn calculate_diff_fees(old_amount: Amount, new_amount: Amount) -> DiffFees; + fn calculate_diff_fees(old_amount: &Amount, new_amount: &Amount) -> DiffBalance; /// Distributes collected fees. Returns the fees that were effectively collected. - fn collect_fees(fees: Fees, sub: Sub) -> Result>; + fn collect_fees(fees: &Fees, sub: &Sub) -> Result>; } pub trait Subscription { @@ -66,5 +66,11 @@ pub trait Subscription { /// /// This trait is used to calculate the storage deposit required for a subscription based it. pub trait DepositCalculator { + /// Calculate the storage deposit required for a subscription. fn calculate_storage_deposit(sub: &Sub) -> Deposit; + /// Calculate the difference in storage deposit between two subscriptions. + /// + /// * `old_sub` - the old subscription. + /// * `new_sub` - the new subscription. + fn calculate_diff_deposit(old_sub: &Sub, new_sub: &Sub) -> DiffBalance; }