dpp/fee/epoch/
distribution.rs

1// MIT LICENSE
2//
3// Copyright (c) 2021 Dash Core Group
4//
5// Permission is hereby granted, free of charge, to any
6// person obtaining a copy of this software and associated
7// documentation files (the "Software"), to deal in the
8// Software without restriction, including without
9// limitation the rights to use, copy, modify, merge,
10// publish, distribute, sublicense, and/or sell copies of
11// the Software, and to permit persons to whom the Software
12// is furnished to do so, subject to the following
13// conditions:
14//
15// The above copyright notice and this permission notice
16// shall be included in all copies or substantial portions
17// of the Software.
18//
19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
20// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
21// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
22// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
23// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
26// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27// DEALINGS IN THE SOFTWARE.
28//
29
30//! Storage fee distribution into epochs
31//!
32//! Data is stored in Platform "forever" currently, which is 50 eras (50 years by default).
33//! To incentivise masternodes to continue store and serve this data,
34//! payments are distributed for entire period split into epochs.
35//! Every epoch, new aggregated storage fees are distributed among epochs
36//! and masternodes receive payouts for previous epoch.
37//!
38
39use crate::fee::epoch::{EpochIndex, SignedCreditsPerEpoch, PERPETUAL_STORAGE_ERAS};
40use rust_decimal::prelude::*;
41use rust_decimal::Decimal;
42use rust_decimal_macros::dec;
43use std::cmp::Ordering;
44
45use crate::balances::credits::Credits;
46use crate::ProtocolError;
47use std::ops::Mul;
48
49// TODO: Should be updated from the doc
50
51/// The amount of the perpetual storage fee to be paid out to masternodes per era. Adds up to 1.
52#[rustfmt::skip]
53pub const FEE_DISTRIBUTION_TABLE: [Decimal; PERPETUAL_STORAGE_ERAS as usize] = [
54    dec!(0.05000), dec!(0.04800), dec!(0.04600), dec!(0.04400), dec!(0.04200),
55    dec!(0.04000), dec!(0.03850), dec!(0.03700), dec!(0.03550), dec!(0.03400),
56    dec!(0.03250), dec!(0.03100), dec!(0.02950), dec!(0.02850), dec!(0.02750),
57    dec!(0.02650), dec!(0.02550), dec!(0.02450), dec!(0.02350), dec!(0.02250),
58    dec!(0.02150), dec!(0.02050), dec!(0.01950), dec!(0.01875), dec!(0.01800),
59    dec!(0.01725), dec!(0.01650), dec!(0.01575), dec!(0.01500), dec!(0.01425),
60    dec!(0.01350), dec!(0.01275), dec!(0.01200), dec!(0.01125), dec!(0.01050),
61    dec!(0.00975), dec!(0.00900), dec!(0.00825), dec!(0.00750), dec!(0.00675),
62    dec!(0.00600), dec!(0.00525), dec!(0.00475), dec!(0.00425), dec!(0.00375),
63    dec!(0.00325), dec!(0.00275), dec!(0.00225), dec!(0.00175), dec!(0.00125),
64];
65
66type DistributionAmount = Credits;
67type DistributionLeftovers = Credits;
68
69/// Distributes storage fees to epochs into `SignedCreditsPerEpoch` and returns leftovers
70pub fn distribute_storage_fee_to_epochs_collection(
71    credits_per_epochs: &mut SignedCreditsPerEpoch,
72    storage_fee: Credits,
73    start_epoch_index: EpochIndex,
74    epochs_per_era: u16,
75) -> Result<DistributionLeftovers, ProtocolError> {
76    distribution_storage_fee_to_epochs_map(
77        storage_fee,
78        start_epoch_index,
79        |epoch_index, epoch_fee_share| {
80            let epoch_credits = credits_per_epochs.entry(epoch_index).or_default();
81
82            *epoch_credits = epoch_credits
83                .checked_add_unsigned(epoch_fee_share)
84                .ok_or_else(|| {
85                    ProtocolError::Overflow(
86                        "updated epoch credits are not fitting to credits max size",
87                    )
88                })?;
89
90            Ok(())
91        },
92        epochs_per_era,
93    )
94}
95
96/// Distributes refunds to epochs into `SignedCreditsPerEpoch` and returns leftovers
97/// It skips epochs up to specified `skip_until_epoch_index`
98pub fn subtract_refunds_from_epoch_credits_collection(
99    credits_per_epochs: &mut SignedCreditsPerEpoch,
100    storage_fee: Credits,
101    start_epoch_index: EpochIndex,
102    current_epoch_index: EpochIndex,
103    epochs_per_era: u16,
104) -> Result<(), ProtocolError> {
105    let leftovers = refund_storage_fee_to_epochs_map(
106        storage_fee,
107        start_epoch_index,
108        current_epoch_index + 1,
109        |epoch_index, epoch_fee_share| {
110            let epoch_credits = credits_per_epochs.entry(epoch_index).or_default();
111
112            *epoch_credits = epoch_credits
113                .checked_sub_unsigned(epoch_fee_share)
114                .ok_or_else(|| {
115                    ProtocolError::Overflow(
116                        "updated epoch credits are not fitting to credits min size",
117                    )
118                })?;
119
120            Ok(())
121        },
122        epochs_per_era,
123    )?;
124
125    // We need to remove the leftovers from the current epoch
126    if leftovers > 0 {
127        let epoch_credits = credits_per_epochs.entry(current_epoch_index).or_default();
128
129        *epoch_credits = epoch_credits
130            .checked_sub_unsigned(leftovers)
131            .ok_or_else(|| {
132                ProtocolError::Overflow("updated epoch credits are not fitting to credits min size")
133            })?;
134    }
135
136    Ok(())
137}
138
139/// Calculates leftovers and amount of credits by distributing storage fees to epochs
140pub fn calculate_storage_fee_refund_amount_and_leftovers(
141    storage_fee: Credits,
142    start_epoch_index: EpochIndex,
143    current_epoch_index: EpochIndex,
144    epochs_per_era: u16,
145) -> Result<(DistributionAmount, DistributionLeftovers), ProtocolError> {
146    let mut skipped_amount = 0;
147
148    let leftovers = distribution_storage_fee_to_epochs_map(
149        storage_fee,
150        start_epoch_index,
151        |epoch_index, epoch_fee_share| {
152            if epoch_index < current_epoch_index + 1 {
153                skipped_amount += epoch_fee_share;
154            }
155
156            Ok(())
157        },
158        epochs_per_era,
159    )?;
160
161    Ok((storage_fee - skipped_amount - leftovers, leftovers))
162}
163
164fn original_removed_credits_multiplier_from(
165    start_epoch_index: EpochIndex,
166    start_repayment_from_epoch_index: EpochIndex,
167    epochs_per_era: u16,
168) -> Decimal {
169    let paid_epochs = start_repayment_from_epoch_index - start_epoch_index;
170
171    let current_era = (paid_epochs / epochs_per_era) as usize;
172
173    let ratio_used: Decimal =
174        FEE_DISTRIBUTION_TABLE
175            .iter()
176            .enumerate()
177            .filter_map(|(era, epoch_multiplier)| match era.cmp(&current_era) {
178                Ordering::Less => None,
179                Ordering::Equal => {
180                    let amount_epochs_left_in_era = epochs_per_era - paid_epochs % epochs_per_era;
181                    Some(epoch_multiplier.mul(
182                        Decimal::from(amount_epochs_left_in_era) / Decimal::from(epochs_per_era),
183                    ))
184                }
185                Ordering::Greater => Some(*epoch_multiplier),
186            })
187            .sum();
188
189    dec!(1) / ratio_used
190}
191
192/// Let's imagine that we are refunding something from epoch 5
193/// We are at Epoch 12
194/// The refund amount is from Epoch 13 (current + 1) to Epoch 1005 (5 + 1000)
195/// We need to figure out the amount extra those 8 costed
196fn restore_original_removed_credits_amount(
197    refund_amount: Decimal,
198    start_epoch_index: EpochIndex,
199    start_repayment_from_epoch_index: EpochIndex,
200    epochs_per_era: u16,
201) -> Result<Decimal, ProtocolError> {
202    let multiplier = original_removed_credits_multiplier_from(
203        start_epoch_index,
204        start_repayment_from_epoch_index,
205        epochs_per_era,
206    );
207
208    refund_amount
209        .checked_mul(multiplier)
210        .ok_or(ProtocolError::Overflow(
211            "overflow when multiplying with the multiplier (this should be impossible)",
212        ))
213}
214
215/// Distributes storage fees to epochs and call function for each epoch.
216/// Returns leftovers
217fn distribution_storage_fee_to_epochs_map<F>(
218    storage_fee: Credits,
219    start_epoch_index: EpochIndex,
220    mut map_function: F,
221    epochs_per_era: u16,
222) -> Result<DistributionLeftovers, ProtocolError>
223where
224    F: FnMut(EpochIndex, Credits) -> Result<(), ProtocolError>,
225{
226    if storage_fee == 0 {
227        return Ok(0);
228    }
229
230    let storage_fee_dec: Decimal = storage_fee.into();
231
232    let mut distribution_leftover_credits = storage_fee;
233
234    let epochs_per_era_dec = Decimal::from(epochs_per_era);
235
236    for era in 0..PERPETUAL_STORAGE_ERAS {
237        let distribution_for_that_era_ratio = FEE_DISTRIBUTION_TABLE[era as usize];
238
239        let era_fee_share = storage_fee_dec * distribution_for_that_era_ratio;
240
241        let epoch_fee_share_dec = era_fee_share / epochs_per_era_dec;
242
243        let epoch_fee_share: Credits = epoch_fee_share_dec
244            .floor()
245            .to_u64()
246            .ok_or_else(|| ProtocolError::Overflow("storage fees are not fitting in a u64"))?;
247
248        let era_start_epoch_index = start_epoch_index + epochs_per_era * era;
249
250        for epoch_index in era_start_epoch_index..era_start_epoch_index + epochs_per_era {
251            //todo: this can lead to many many calls once we are further along in epochs
252            map_function(epoch_index, epoch_fee_share)?;
253
254            distribution_leftover_credits = distribution_leftover_credits
255                .checked_sub(epoch_fee_share)
256                .ok_or(ProtocolError::Overflow(
257                    "leftovers bigger than initial value",
258                ))?;
259        }
260    }
261
262    Ok(distribution_leftover_credits)
263}
264
265/// Distributes recovered by multiplier original removed
266/// credits to epochs and call function for each epoch.
267/// Leftovers are added to current epoch
268fn refund_storage_fee_to_epochs_map<F>(
269    storage_fee: Credits,
270    start_epoch_index: EpochIndex,
271    skip_until_epoch_index: EpochIndex,
272    mut map_function: F,
273    epochs_per_era: u16,
274) -> Result<DistributionLeftovers, ProtocolError>
275where
276    F: FnMut(EpochIndex, Credits) -> Result<(), ProtocolError>,
277{
278    if storage_fee == 0 {
279        return Ok(0);
280    }
281
282    let storage_fee_dec: Decimal = storage_fee.into();
283
284    let mut distribution_leftover_credits = storage_fee;
285
286    let epochs_per_era_dec = Decimal::from(epochs_per_era);
287
288    let start_era: u16 = (skip_until_epoch_index - start_epoch_index) / epochs_per_era;
289
290    // Let's imagine that we are refunding something from epoch 5
291    // We are at Epoch 12
292    // The refund amount is from Epoch 13 (current + 1) to Epoch 1005 (5 + 1000)
293    // We need to figure out the amount extra those 8 costed
294    let estimated_storage_fee_dec = restore_original_removed_credits_amount(
295        storage_fee_dec,
296        start_epoch_index,
297        skip_until_epoch_index,
298        epochs_per_era,
299    )?;
300
301    for era in start_era..PERPETUAL_STORAGE_ERAS {
302        let distribution_for_that_era_ratio = FEE_DISTRIBUTION_TABLE[era as usize];
303
304        let estimated_era_fee_share = estimated_storage_fee_dec * distribution_for_that_era_ratio;
305
306        let estimated_epoch_fee_share_dec = estimated_era_fee_share / epochs_per_era_dec;
307
308        let estimated_epoch_fee_share: Credits = estimated_epoch_fee_share_dec
309            .floor()
310            .to_u64()
311            .ok_or_else(|| ProtocolError::Overflow("storage fees are not fitting in a u64"))?;
312
313        let era_start_epoch_index = if era == start_era {
314            skip_until_epoch_index
315        } else {
316            start_epoch_index + epochs_per_era * era
317        };
318
319        let era_end_epoch_index = start_epoch_index + ((era + 1) * epochs_per_era);
320
321        for epoch_index in era_start_epoch_index..era_end_epoch_index {
322            map_function(epoch_index, estimated_epoch_fee_share)?;
323
324            distribution_leftover_credits = distribution_leftover_credits
325                .checked_sub(estimated_epoch_fee_share)
326                .ok_or(ProtocolError::Overflow(
327                    "leftovers bigger than initial value",
328                ))?;
329        }
330    }
331    Ok(distribution_leftover_credits)
332}
333
334#[cfg(test)]
335mod tests {
336    use super::*;
337    use crate::fee::epoch::GENESIS_EPOCH_INDEX;
338    use rust_decimal::Decimal;
339    use rust_decimal_macros::dec;
340
341    mod original_removed_credits_multiplier_from {
342        use super::*;
343
344        #[test]
345        fn should_create_multiplier_for_epochs_since_the_beginning() {
346            // the multiplier should be
347            let epoch_0_cost = dec!(0.05000) / dec!(20.0);
348            let multiplier_should_be = dec!(1.0) / (dec!(1.0) - epoch_0_cost);
349
350            let multiplier = original_removed_credits_multiplier_from(0, 1, 20);
351
352            assert_eq!(multiplier_should_be, multiplier);
353        }
354
355        #[test]
356        fn should_create_multiplier_for_epochs_since_24_and_repaid_since_43() {
357            // there were 19 epochs
358            let epoch_0_cost = dec!(19.0) * dec!(0.05000) / dec!(20.0);
359
360            let multiplier_should_be = dec!(1.0) / (dec!(1.0) - epoch_0_cost);
361
362            let multiplier = original_removed_credits_multiplier_from(24, 43, 20);
363
364            assert_eq!(multiplier_should_be, multiplier);
365        }
366    }
367
368    mod fee_distribution_table {
369        use super::*;
370
371        #[test]
372        fn should_have_sum_of_1() {
373            assert_eq!(FEE_DISTRIBUTION_TABLE.iter().sum::<Decimal>(), dec!(1.0),);
374        }
375
376        #[test]
377        fn should_distribute_value() {
378            let value = Decimal::from(i64::MAX);
379
380            let calculated_value: Decimal = FEE_DISTRIBUTION_TABLE
381                .into_iter()
382                .map(|ratio| value * ratio)
383                .sum();
384
385            assert_eq!(calculated_value, value);
386        }
387    }
388
389    mod distribution_storage_fee_to_epochs_map {
390        use super::*;
391
392        #[test]
393        fn should_distribute_nothing_if_storage_fees_are_zero() {
394            let mut calls = 0;
395
396            let leftovers = distribution_storage_fee_to_epochs_map(
397                0,
398                GENESIS_EPOCH_INDEX,
399                |_, _| {
400                    calls += 1;
401
402                    Ok(())
403                },
404                20,
405            )
406            .expect("should distribute storage fee");
407
408            assert_eq!(calls, 0);
409            assert_eq!(leftovers, 0);
410        }
411
412        #[test]
413        fn should_call_function_for_each_epoch_for_50_eras_sequentially() {
414            let mut calls = 0;
415
416            let mut previous_epoch_index = -1;
417
418            let leftovers = distribution_storage_fee_to_epochs_map(
419                100000,
420                GENESIS_EPOCH_INDEX,
421                |epoch_index, _| {
422                    assert_eq!(epoch_index as i32, previous_epoch_index + 1);
423                    previous_epoch_index = epoch_index as i32;
424
425                    calls += 1;
426
427                    Ok(())
428                },
429                20,
430            )
431            .expect("should distribute storage fee");
432
433            assert_eq!(calls, 1000); //20*50
434            assert_eq!(leftovers, 360);
435        }
436    }
437
438    mod distribute_storage_fee_to_epochs_collection {
439        use super::*;
440        use crate::balances::credits::{Creditable, MAX_CREDITS};
441        use crate::fee::SignedCredits;
442
443        #[test]
444        fn should_distribute_max_credits_value_without_overflow() {
445            let storage_fee = MAX_CREDITS;
446
447            let mut credits_per_epochs = SignedCreditsPerEpoch::default();
448
449            let leftovers = distribute_storage_fee_to_epochs_collection(
450                &mut credits_per_epochs,
451                storage_fee,
452                GENESIS_EPOCH_INDEX,
453                20,
454            )
455            .expect("should distribute storage fee");
456
457            // check leftover
458            assert_eq!(leftovers, 507);
459        }
460
461        #[test]
462        fn should_deterministically_distribute_fees() {
463            let storage_fee = 1000000;
464            let current_epoch_index = 42;
465
466            let mut credits_per_epochs = SignedCreditsPerEpoch::default();
467
468            let leftovers = distribute_storage_fee_to_epochs_collection(
469                &mut credits_per_epochs,
470                storage_fee,
471                current_epoch_index,
472                20,
473            )
474            .expect("should distribute storage fee");
475
476            // check leftover
477            assert_eq!(leftovers, 180);
478
479            // compare them with reference table for 20 epochs per era (1000)
480            #[rustfmt::skip]
481                let reference_fees: [SignedCredits; 1000] = [
482                2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500,
483                2500, 2500, 2500, 2500, 2500, 2500, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400,
484                2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2400, 2300, 2300,
485                2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300, 2300,
486                2300, 2300, 2300, 2300, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200,
487                2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2100, 2100, 2100, 2100,
488                2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100,
489                2100, 2100, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000,
490                2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 1925, 1925, 1925, 1925, 1925, 1925,
491                1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925, 1925,
492                1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850,
493                1850, 1850, 1850, 1850, 1850, 1850, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775,
494                1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1775, 1700, 1700,
495                1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700,
496                1700, 1700, 1700, 1700, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625,
497                1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1550, 1550, 1550, 1550,
498                1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550,
499                1550, 1550, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475,
500                1475, 1475, 1475, 1475, 1475, 1475, 1475, 1475, 1425, 1425, 1425, 1425, 1425, 1425,
501                1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425, 1425,
502                1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375, 1375,
503                1375, 1375, 1375, 1375, 1375, 1375, 1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325,
504                1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325, 1275, 1275,
505                1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
506                1275, 1275, 1275, 1275, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225,
507                1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1175, 1175, 1175, 1175,
508                1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
509                1175, 1175, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125,
510                1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1075, 1075, 1075, 1075, 1075, 1075,
511                1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1075,
512                1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025,
513                1025, 1025, 1025, 1025, 1025, 1025, 975, 975, 975, 975, 975, 975, 975, 975, 975,
514                975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 975, 937, 937, 937, 937, 937,
515                937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 937, 900,
516                900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900,
517                900, 900, 900, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862,
518                862, 862, 862, 862, 862, 862, 862, 825, 825, 825, 825, 825, 825, 825, 825, 825,
519                825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 825, 787, 787, 787, 787, 787,
520                787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 750,
521                750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750,
522                750, 750, 750, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712, 712,
523                712, 712, 712, 712, 712, 712, 712, 675, 675, 675, 675, 675, 675, 675, 675, 675,
524                675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 675, 637, 637, 637, 637, 637,
525                637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 637, 600,
526                600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600,
527                600, 600, 600, 562, 562, 562, 562, 562, 562, 562, 562, 562, 562, 562, 562, 562,
528                562, 562, 562, 562, 562, 562, 562, 525, 525, 525, 525, 525, 525, 525, 525, 525,
529                525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 487, 487, 487, 487, 487,
530                487, 487, 487, 487, 487, 487, 487, 487, 487, 487, 487, 487, 487, 487, 487, 450,
531                450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450,
532                450, 450, 450, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412,
533                412, 412, 412, 412, 412, 412, 412, 375, 375, 375, 375, 375, 375, 375, 375, 375,
534                375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 337, 337, 337, 337, 337,
535                337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 300,
536                300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
537                300, 300, 300, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262,
538                262, 262, 262, 262, 262, 262, 262, 237, 237, 237, 237, 237, 237, 237, 237, 237,
539                237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 212, 212, 212, 212, 212,
540                212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 187,
541                187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187,
542                187, 187, 187, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
543                162, 162, 162, 162, 162, 162, 162, 137, 137, 137, 137, 137, 137, 137, 137, 137,
544                137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 112, 112, 112, 112, 112,
545                112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 87,
546                87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 62,
547                62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62
548            ];
549
550            assert_eq!(
551                credits_per_epochs.clone().into_values().collect::<Vec<_>>(),
552                reference_fees
553            );
554
555            let total_distributed: SignedCredits = credits_per_epochs.values().sum();
556
557            assert_eq!(total_distributed.to_unsigned() + leftovers, storage_fee);
558
559            /*
560
561            Repeat distribution to ensure deterministic results
562
563             */
564
565            let leftovers = distribute_storage_fee_to_epochs_collection(
566                &mut credits_per_epochs,
567                storage_fee,
568                current_epoch_index,
569                20,
570            )
571            .expect("should distribute storage fee");
572
573            // assert that all the values doubled meaning that distribution is reproducible
574            assert_eq!(
575                credits_per_epochs.into_values().collect::<Vec<_>>(),
576                reference_fees
577                    .into_iter()
578                    .map(|val| val * 2)
579                    .collect::<Vec<_>>()
580            );
581
582            assert_eq!(leftovers, 180);
583        }
584    }
585
586    mod subtract_refunds_from_epoch_credits_collection {
587        use super::*;
588        use crate::balances::credits::Creditable;
589        use crate::fee::SignedCredits;
590
591        #[test]
592        fn should_deduct_refunds_from_collection_since_specific_epoch_start_at_genesis() {
593            // Example: Bob inserted an element into the tree
594            // He paid slightly more than 1.2 Million credits for this operation that happened at epoch 0.
595            // At epoch 42 we are asking for a refund.
596            // The refund is 1.07 Million credits that were left from the 1.2.
597
598            let start_epoch_index: EpochIndex = GENESIS_EPOCH_INDEX;
599            const REFUNDED_EPOCH_INDEX: EpochIndex = 42;
600            let original_storage_fee = 1200005;
601
602            let (refund_amount, leftovers) = calculate_storage_fee_refund_amount_and_leftovers(
603                original_storage_fee,
604                start_epoch_index,
605                REFUNDED_EPOCH_INDEX,
606                20,
607            )
608            .expect("should distribute storage fee");
609
610            assert_eq!(refund_amount, 1074120);
611            assert_eq!(leftovers, 5);
612
613            let mut credits_per_epochs = SignedCreditsPerEpoch::default();
614
615            subtract_refunds_from_epoch_credits_collection(
616                &mut credits_per_epochs,
617                refund_amount,
618                start_epoch_index,
619                REFUNDED_EPOCH_INDEX,
620                20,
621            )
622            .expect("should distribute storage fee");
623
624            // compare them with reference table
625            // we expect to get 0 for the change of the current epochs balance
626            // this is because there was only 1 refund so leftovers wouldn't have any effect
627            #[rustfmt::skip]
628            let reference_fees: [SignedCredits;
629                (1000 - REFUNDED_EPOCH_INDEX - 1) as usize] = [-2760, -2760, -2760,
630                -2760, -2760, -2760, -2760, -2760, -2760, -2760, -2760, -2760, -2760, -2760, -2760,
631                -2760, -2760, -2640, -2640, -2640, -2640, -2640, -2640, -2640, -2640, -2640, -2640,
632                -2640, -2640, -2640, -2640, -2640, -2640, -2640, -2640, -2640, -2640, -2520, -2520,
633                -2520, -2520, -2520, -2520, -2520, -2520, -2520, -2520, -2520, -2520, -2520, -2520,
634                -2520, -2520, -2520, -2520, -2520, -2520, -2400, -2400, -2400, -2400, -2400, -2400,
635                -2400, -2400, -2400, -2400, -2400, -2400, -2400, -2400, -2400, -2400, -2400, -2400,
636                -2400, -2400, -2310, -2310, -2310, -2310, -2310, -2310, -2310, -2310, -2310, -2310,
637                -2310, -2310, -2310, -2310, -2310, -2310, -2310, -2310, -2310, -2310, -2220, -2220,
638                -2220, -2220, -2220, -2220, -2220, -2220, -2220, -2220, -2220, -2220, -2220, -2220,
639                -2220, -2220, -2220, -2220, -2220, -2220, -2130, -2130, -2130, -2130, -2130, -2130,
640                -2130, -2130, -2130, -2130, -2130, -2130, -2130, -2130, -2130, -2130, -2130, -2130,
641                -2130, -2130, -2040, -2040, -2040, -2040, -2040, -2040, -2040, -2040, -2040, -2040,
642                -2040, -2040, -2040, -2040, -2040, -2040, -2040, -2040, -2040, -2040, -1950, -1950,
643                -1950, -1950, -1950, -1950, -1950, -1950, -1950, -1950, -1950, -1950, -1950, -1950,
644                -1950, -1950, -1950, -1950, -1950, -1950, -1860, -1860, -1860, -1860, -1860, -1860,
645                -1860, -1860, -1860, -1860, -1860, -1860, -1860, -1860, -1860, -1860, -1860, -1860,
646                -1860, -1860, -1770, -1770, -1770, -1770, -1770, -1770, -1770, -1770, -1770, -1770,
647                -1770, -1770, -1770, -1770, -1770, -1770, -1770, -1770, -1770, -1770, -1710, -1710,
648                -1710, -1710, -1710, -1710, -1710, -1710, -1710, -1710, -1710, -1710, -1710, -1710,
649                -1710, -1710, -1710, -1710, -1710, -1710, -1650, -1650, -1650, -1650, -1650, -1650,
650                -1650, -1650, -1650, -1650, -1650, -1650, -1650, -1650, -1650, -1650, -1650, -1650,
651                -1650, -1650, -1590, -1590, -1590, -1590, -1590, -1590, -1590, -1590, -1590, -1590,
652                -1590, -1590, -1590, -1590, -1590, -1590, -1590, -1590, -1590, -1590, -1530, -1530,
653                -1530, -1530, -1530, -1530, -1530, -1530, -1530, -1530, -1530, -1530, -1530, -1530,
654                -1530, -1530, -1530, -1530, -1530, -1530, -1470, -1470, -1470, -1470, -1470, -1470,
655                -1470, -1470, -1470, -1470, -1470, -1470, -1470, -1470, -1470, -1470, -1470, -1470,
656                -1470, -1470, -1410, -1410, -1410, -1410, -1410, -1410, -1410, -1410, -1410, -1410,
657                -1410, -1410, -1410, -1410, -1410, -1410, -1410, -1410, -1410, -1410, -1350, -1350,
658                -1350, -1350, -1350, -1350, -1350, -1350, -1350, -1350, -1350, -1350, -1350, -1350,
659                -1350, -1350, -1350, -1350, -1350, -1350, -1290, -1290, -1290, -1290, -1290, -1290,
660                -1290, -1290, -1290, -1290, -1290, -1290, -1290, -1290, -1290, -1290, -1290, -1290,
661                -1290, -1290, -1230, -1230, -1230, -1230, -1230, -1230, -1230, -1230, -1230, -1230,
662                -1230, -1230, -1230, -1230, -1230, -1230, -1230, -1230, -1230, -1230, -1170, -1170,
663                -1170, -1170, -1170, -1170, -1170, -1170, -1170, -1170, -1170, -1170, -1170, -1170,
664                -1170, -1170, -1170, -1170, -1170, -1170, -1125, -1125, -1125, -1125, -1125, -1125,
665                -1125, -1125, -1125, -1125, -1125, -1125, -1125, -1125, -1125, -1125, -1125, -1125,
666                -1125, -1125, -1080, -1080, -1080, -1080, -1080, -1080, -1080, -1080, -1080, -1080,
667                -1080, -1080, -1080, -1080, -1080, -1080, -1080, -1080, -1080, -1080, -1035, -1035,
668                -1035, -1035, -1035, -1035, -1035, -1035, -1035, -1035, -1035, -1035, -1035, -1035,
669                -1035, -1035, -1035, -1035, -1035, -1035, -990, -990, -990, -990, -990, -990, -990,
670                -990, -990, -990, -990, -990, -990, -990, -990, -990, -990, -990, -990, -990, -945,
671                -945, -945, -945, -945, -945, -945, -945, -945, -945, -945, -945, -945, -945, -945,
672                -945, -945, -945, -945, -945, -900, -900, -900, -900, -900, -900, -900, -900, -900,
673                -900, -900, -900, -900, -900, -900, -900, -900, -900, -900, -900, -855, -855, -855,
674                -855, -855, -855, -855, -855, -855, -855, -855, -855, -855, -855, -855, -855, -855,
675                -855, -855, -855, -810, -810, -810, -810, -810, -810, -810, -810, -810, -810, -810,
676                -810, -810, -810, -810, -810, -810, -810, -810, -810, -765, -765, -765, -765, -765,
677                -765, -765, -765, -765, -765, -765, -765, -765, -765, -765, -765, -765, -765, -765,
678                -765, -720, -720, -720, -720, -720, -720, -720, -720, -720, -720, -720, -720, -720,
679                -720, -720, -720, -720, -720, -720, -720, -675, -675, -675, -675, -675, -675, -675,
680                -675, -675, -675, -675, -675, -675, -675, -675, -675, -675, -675, -675, -675, -630,
681                -630, -630, -630, -630, -630, -630, -630, -630, -630, -630, -630, -630, -630, -630,
682                -630, -630, -630, -630, -630, -585, -585, -585, -585, -585, -585, -585, -585, -585,
683                -585, -585, -585, -585, -585, -585, -585, -585, -585, -585, -585, -540, -540, -540,
684                -540, -540, -540, -540, -540, -540, -540, -540, -540, -540, -540, -540, -540, -540,
685                -540, -540, -540, -495, -495, -495, -495, -495, -495, -495, -495, -495, -495, -495,
686                -495, -495, -495, -495, -495, -495, -495, -495, -495, -450, -450, -450, -450, -450,
687                -450, -450, -450, -450, -450, -450, -450, -450, -450, -450, -450, -450, -450, -450,
688                -450, -405, -405, -405, -405, -405, -405, -405, -405, -405, -405, -405, -405, -405,
689                -405, -405, -405, -405, -405, -405, -405, -360, -360, -360, -360, -360, -360, -360,
690                -360, -360, -360, -360, -360, -360, -360, -360, -360, -360, -360, -360, -360, -315,
691                -315, -315, -315, -315, -315, -315, -315, -315, -315, -315, -315, -315, -315, -315,
692                -315, -315, -315, -315, -315, -285, -285, -285, -285, -285, -285, -285, -285, -285,
693                -285, -285, -285, -285, -285, -285, -285, -285, -285, -285, -285, -255, -255, -255,
694                -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255,
695                -255, -255, -255, -225, -225, -225, -225, -225, -225, -225, -225, -225, -225, -225,
696                -225, -225, -225, -225, -225, -225, -225, -225, -225, -195, -195, -195, -195, -195,
697                -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195, -195,
698                -195, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165, -165,
699                -165, -165, -165, -165, -165, -165, -165, -135, -135, -135, -135, -135, -135, -135,
700                -135, -135, -135, -135, -135, -135, -135, -135, -135, -135, -135, -135, -135, -105,
701                -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
702                -105, -105, -105, -105, -105, -75, -75, -75, -75, -75, -75, -75, -75, -75, -75, -75,
703                -75, -75, -75, -75, -75, -75, -75, -75, -75];
704
705            assert_eq!(
706                credits_per_epochs.clone().into_values().collect::<Vec<_>>(),
707                reference_fees
708            );
709
710            let total_distributed: SignedCredits = credits_per_epochs.values().sum();
711
712            assert_eq!(total_distributed.to_unsigned(), refund_amount);
713        }
714
715        #[test]
716        fn should_deduct_refunds_from_collection_start_epoch_doesnt_matter_check() {
717            for start_epoch_index in 0..150 {
718                let current_epoch_index_where_refund_occurred: EpochIndex = start_epoch_index + 14;
719
720                let original_storage_fee = 3405507;
721                let (refund_amount, leftovers) = calculate_storage_fee_refund_amount_and_leftovers(
722                    original_storage_fee,
723                    start_epoch_index,
724                    current_epoch_index_where_refund_occurred,
725                    20,
726                )
727                .expect("should distribute storage fee");
728
729                assert_eq!(refund_amount, 3277305);
730                assert_eq!(leftovers, 507);
731
732                let multiplier = original_removed_credits_multiplier_from(
733                    start_epoch_index,
734                    current_epoch_index_where_refund_occurred + 1,
735                    20,
736                );
737
738                // it's not going to be completely perfect but it's good enough
739                // there were 24 epochs, on average we would be 12 off
740                // while we could incorporate this offset into the multiplier it would
741                // be overkill for such low credit amounts
742                assert!(
743                    (Decimal::from(refund_amount) * multiplier)
744                        .abs_sub(&Decimal::from(original_storage_fee - leftovers))
745                        < dec!(100)
746                );
747
748                // we do however want to make sure the multiplier makes things smaller
749                assert!(
750                    (Decimal::from(refund_amount) * multiplier)
751                        < Decimal::from(original_storage_fee - leftovers)
752                );
753
754                let mut credits_per_epochs = SignedCreditsPerEpoch::default();
755
756                subtract_refunds_from_epoch_credits_collection(
757                    &mut credits_per_epochs,
758                    refund_amount,
759                    start_epoch_index,
760                    current_epoch_index_where_refund_occurred,
761                    20,
762                )
763                .expect("should distribute storage fee");
764                // compare them with reference table
765                // we expect to get 0 for the change of the current epochs balance
766                // this is because there was only 1 refund so leftovers wouldn't have any effect
767                #[rustfmt::skip]
768                    let reference_fees: Vec<SignedCredits> =
769                    vec![-525, -8512, -8512, -8512, -8512, -8512, -8171, -8171, -8171, -8171, -8171, -8171,
770                        -8171, -8171, -8171, -8171, -8171, -8171, -8171, -8171, -8171, -8171, -8171,
771                        -8171, -8171, -8171, -7831, -7831, -7831, -7831, -7831, -7831, -7831, -7831,
772                        -7831, -7831, -7831, -7831, -7831, -7831, -7831, -7831, -7831, -7831, -7831,
773                        -7831, -7490, -7490, -7490, -7490, -7490, -7490, -7490, -7490, -7490, -7490,
774                        -7490, -7490, -7490, -7490, -7490, -7490, -7490, -7490, -7490, -7490, -7150,
775                        -7150, -7150, -7150, -7150, -7150, -7150, -7150, -7150, -7150, -7150, -7150,
776                        -7150, -7150, -7150, -7150, -7150, -7150, -7150, -7150, -6809, -6809, -6809,
777                        -6809, -6809, -6809, -6809, -6809, -6809, -6809, -6809, -6809, -6809, -6809,
778                        -6809, -6809, -6809, -6809, -6809, -6809, -6554, -6554, -6554, -6554, -6554,
779                        -6554, -6554, -6554, -6554, -6554, -6554, -6554, -6554, -6554, -6554, -6554,
780                        -6554, -6554, -6554, -6554, -6299, -6299, -6299, -6299, -6299, -6299, -6299,
781                        -6299, -6299, -6299, -6299, -6299, -6299, -6299, -6299, -6299, -6299, -6299,
782                        -6299, -6299, -6043, -6043, -6043, -6043, -6043, -6043, -6043, -6043, -6043,
783                        -6043, -6043, -6043, -6043, -6043, -6043, -6043, -6043, -6043, -6043, -6043,
784                        -5788, -5788, -5788, -5788, -5788, -5788, -5788, -5788, -5788, -5788, -5788,
785                        -5788, -5788, -5788, -5788, -5788, -5788, -5788, -5788, -5788, -5533, -5533,
786                        -5533, -5533, -5533, -5533, -5533, -5533, -5533, -5533, -5533, -5533, -5533,
787                        -5533, -5533, -5533, -5533, -5533, -5533, -5533, -5277, -5277, -5277, -5277,
788                        -5277, -5277, -5277, -5277, -5277, -5277, -5277, -5277, -5277, -5277, -5277,
789                        -5277, -5277, -5277, -5277, -5277, -5022, -5022, -5022, -5022, -5022, -5022,
790                        -5022, -5022, -5022, -5022, -5022, -5022, -5022, -5022, -5022, -5022, -5022,
791                        -5022, -5022, -5022, -4852, -4852, -4852, -4852, -4852, -4852, -4852, -4852,
792                        -4852, -4852, -4852, -4852, -4852, -4852, -4852, -4852, -4852, -4852, -4852,
793                        -4852, -4681, -4681, -4681, -4681, -4681, -4681, -4681, -4681, -4681, -4681,
794                        -4681, -4681, -4681, -4681, -4681, -4681, -4681, -4681, -4681, -4681, -4511,
795                        -4511, -4511, -4511, -4511, -4511, -4511, -4511, -4511, -4511, -4511, -4511,
796                        -4511, -4511, -4511, -4511, -4511, -4511, -4511, -4511, -4341, -4341, -4341,
797                        -4341, -4341, -4341, -4341, -4341, -4341, -4341, -4341, -4341, -4341, -4341,
798                        -4341, -4341, -4341, -4341, -4341, -4341, -4171, -4171, -4171, -4171, -4171,
799                        -4171, -4171, -4171, -4171, -4171, -4171, -4171, -4171, -4171, -4171, -4171,
800                        -4171, -4171, -4171, -4171, -4000, -4000, -4000, -4000, -4000, -4000, -4000,
801                        -4000, -4000, -4000, -4000, -4000, -4000, -4000, -4000, -4000, -4000, -4000,
802                        -4000, -4000, -3830, -3830, -3830, -3830, -3830, -3830, -3830, -3830, -3830,
803                        -3830, -3830, -3830, -3830, -3830, -3830, -3830, -3830, -3830, -3830, -3830,
804                        -3660, -3660, -3660, -3660, -3660, -3660, -3660, -3660, -3660, -3660, -3660,
805                        -3660, -3660, -3660, -3660, -3660, -3660, -3660, -3660, -3660, -3490, -3490,
806                        -3490, -3490, -3490, -3490, -3490, -3490, -3490, -3490, -3490, -3490, -3490,
807                        -3490, -3490, -3490, -3490, -3490, -3490, -3490, -3319, -3319, -3319, -3319,
808                        -3319, -3319, -3319, -3319, -3319, -3319, -3319, -3319, -3319, -3319, -3319,
809                        -3319, -3319, -3319, -3319, -3319, -3192, -3192, -3192, -3192, -3192, -3192,
810                        -3192, -3192, -3192, -3192, -3192, -3192, -3192, -3192, -3192, -3192, -3192,
811                        -3192, -3192, -3192, -3064, -3064, -3064, -3064, -3064, -3064, -3064, -3064,
812                        -3064, -3064, -3064, -3064, -3064, -3064, -3064, -3064, -3064, -3064, -3064,
813                        -3064, -2936, -2936, -2936, -2936, -2936, -2936, -2936, -2936, -2936, -2936,
814                        -2936, -2936, -2936, -2936, -2936, -2936, -2936, -2936, -2936, -2936, -2809,
815                        -2809, -2809, -2809, -2809, -2809, -2809, -2809, -2809, -2809, -2809, -2809,
816                        -2809, -2809, -2809, -2809, -2809, -2809, -2809, -2809, -2681, -2681, -2681,
817                        -2681, -2681, -2681, -2681, -2681, -2681, -2681, -2681, -2681, -2681, -2681,
818                        -2681, -2681, -2681, -2681, -2681, -2681, -2553, -2553, -2553, -2553, -2553,
819                        -2553, -2553, -2553, -2553, -2553, -2553, -2553, -2553, -2553, -2553, -2553,
820                        -2553, -2553, -2553, -2553, -2426, -2426, -2426, -2426, -2426, -2426, -2426,
821                        -2426, -2426, -2426, -2426, -2426, -2426, -2426, -2426, -2426, -2426, -2426,
822                        -2426, -2426, -2298, -2298, -2298, -2298, -2298, -2298, -2298, -2298, -2298,
823                        -2298, -2298, -2298, -2298, -2298, -2298, -2298, -2298, -2298, -2298, -2298,
824                        -2170, -2170, -2170, -2170, -2170, -2170, -2170, -2170, -2170, -2170, -2170,
825                        -2170, -2170, -2170, -2170, -2170, -2170, -2170, -2170, -2170, -2042, -2042,
826                        -2042, -2042, -2042, -2042, -2042, -2042, -2042, -2042, -2042, -2042, -2042,
827                        -2042, -2042, -2042, -2042, -2042, -2042, -2042, -1915, -1915, -1915, -1915,
828                        -1915, -1915, -1915, -1915, -1915, -1915, -1915, -1915, -1915, -1915, -1915,
829                        -1915, -1915, -1915, -1915, -1915, -1787, -1787, -1787, -1787, -1787, -1787,
830                        -1787, -1787, -1787, -1787, -1787, -1787, -1787, -1787, -1787, -1787, -1787,
831                        -1787, -1787, -1787, -1659, -1659, -1659, -1659, -1659, -1659, -1659, -1659,
832                        -1659, -1659, -1659, -1659, -1659, -1659, -1659, -1659, -1659, -1659, -1659,
833                        -1659, -1532, -1532, -1532, -1532, -1532, -1532, -1532, -1532, -1532, -1532,
834                        -1532, -1532, -1532, -1532, -1532, -1532, -1532, -1532, -1532, -1532, -1404,
835                        -1404, -1404, -1404, -1404, -1404, -1404, -1404, -1404, -1404, -1404, -1404,
836                        -1404, -1404, -1404, -1404, -1404, -1404, -1404, -1404, -1276, -1276, -1276,
837                        -1276, -1276, -1276, -1276, -1276, -1276, -1276, -1276, -1276, -1276, -1276,
838                        -1276, -1276, -1276, -1276, -1276, -1276, -1149, -1149, -1149, -1149, -1149,
839                        -1149, -1149, -1149, -1149, -1149, -1149, -1149, -1149, -1149, -1149, -1149,
840                        -1149, -1149, -1149, -1149, -1021, -1021, -1021, -1021, -1021, -1021, -1021,
841                        -1021, -1021, -1021, -1021, -1021, -1021, -1021, -1021, -1021, -1021, -1021,
842                        -1021, -1021, -893, -893, -893, -893, -893, -893, -893, -893, -893, -893,
843                        -893, -893, -893, -893, -893, -893, -893, -893, -893, -893, -808, -808, -808,
844                        -808, -808, -808, -808, -808, -808, -808, -808, -808, -808, -808, -808, -808,
845                        -808, -808, -808, -808, -723, -723, -723, -723, -723, -723, -723, -723, -723,
846                        -723, -723, -723, -723, -723, -723, -723, -723, -723, -723, -723, -638, -638,
847                        -638, -638, -638, -638, -638, -638, -638, -638, -638, -638, -638, -638, -638,
848                        -638, -638, -638, -638, -638, -553, -553, -553, -553, -553, -553, -553, -553,
849                        -553, -553, -553, -553, -553, -553, -553, -553, -553, -553, -553, -553, -468,
850                        -468, -468, -468, -468, -468, -468, -468, -468, -468, -468, -468, -468, -468,
851                        -468, -468, -468, -468, -468, -468, -383, -383, -383, -383, -383, -383, -383,
852                        -383, -383, -383, -383, -383, -383, -383, -383, -383, -383, -383, -383, -383,
853                        -297, -297, -297, -297, -297, -297, -297, -297, -297, -297, -297, -297, -297,
854                        -297, -297, -297, -297, -297, -297, -297, -212, -212, -212, -212, -212, -212,
855                        -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
856                        -212];
857
858                assert_eq!(
859                    credits_per_epochs.clone().into_values().collect::<Vec<_>>(),
860                    reference_fees
861                );
862
863                let total_distributed: SignedCredits = credits_per_epochs.values().sum();
864
865                assert_eq!(total_distributed.to_unsigned(), refund_amount);
866            }
867        }
868
869        #[test]
870        fn should_deduct_refunds_from_two_collection_since_specific_epoch() {
871            const CURRENT_EPOCH_INDEX_WHERE_REFUND_OCCURRED: EpochIndex = 42;
872            let mut credits_per_epochs = SignedCreditsPerEpoch::default();
873
874            // First_refund
875
876            // Example: Bob inserted an element into the tree
877            // He paid slightly more than 1.2 Million credits for this operation that happened at epoch 0.
878            // At epoch 42 we are asking for a refund.
879            // The refund is 1.07 Million credits that were left from the 1.2.
880
881            let first_start_epoch_index: EpochIndex = GENESIS_EPOCH_INDEX;
882
883            let first_original_storage_fee = 1200005;
884            let (first_refund_amount, leftovers) =
885                calculate_storage_fee_refund_amount_and_leftovers(
886                    first_original_storage_fee,
887                    first_start_epoch_index,
888                    CURRENT_EPOCH_INDEX_WHERE_REFUND_OCCURRED,
889                    20,
890                )
891                .expect("should distribute storage fee");
892
893            assert_eq!(first_refund_amount, 1074120);
894            assert_eq!(leftovers, 5);
895
896            subtract_refunds_from_epoch_credits_collection(
897                &mut credits_per_epochs,
898                first_refund_amount,
899                first_start_epoch_index,
900                CURRENT_EPOCH_INDEX_WHERE_REFUND_OCCURRED,
901                20,
902            )
903            .expect("should distribute storage fee");
904
905            // Second_refund
906
907            // Example: Bob inserted an element into the tree
908            // He paid slightly more than 3.4 Million credits for this operation that happened at epoch 0.
909            // At epoch 42 we are asking for a refund.
910
911            const SECOND_START_EPOCH_INDEX: EpochIndex = 28;
912
913            let second_original_storage_fee = 3405507;
914            let (second_refund_amount, leftovers) =
915                calculate_storage_fee_refund_amount_and_leftovers(
916                    second_original_storage_fee,
917                    SECOND_START_EPOCH_INDEX,
918                    CURRENT_EPOCH_INDEX_WHERE_REFUND_OCCURRED,
919                    20,
920                )
921                .expect("should distribute storage fee");
922
923            assert_eq!(second_refund_amount, 3277305);
924            assert_eq!(leftovers, 507);
925
926            let multiplier = original_removed_credits_multiplier_from(
927                SECOND_START_EPOCH_INDEX,
928                CURRENT_EPOCH_INDEX_WHERE_REFUND_OCCURRED + 1,
929                20,
930            );
931
932            // it's not going to be completely perfect but it's good enough
933            // there were 24 epochs, on average we would be 12 off
934            // while we could incorporate this offset into the multiplier it would
935            // be overkill for such low credit amounts
936            assert!(
937                (Decimal::from(second_refund_amount) * multiplier)
938                    .abs_sub(&Decimal::from(second_original_storage_fee - leftovers))
939                    < dec!(100)
940            );
941
942            // we do however want to make sure the multiplier makes things smaller
943            assert!(
944                (Decimal::from(second_refund_amount) * multiplier)
945                    < Decimal::from(second_original_storage_fee - leftovers)
946            );
947
948            subtract_refunds_from_epoch_credits_collection(
949                &mut credits_per_epochs,
950                second_refund_amount,
951                SECOND_START_EPOCH_INDEX,
952                CURRENT_EPOCH_INDEX_WHERE_REFUND_OCCURRED,
953                20,
954            )
955            .expect("should distribute storage fee");
956            // compare them with reference table
957            // we expect to get 0 for the change of the current epochs balance
958            // this is because there was only 1 refund so leftovers wouldn't have any effect
959            #[rustfmt::skip]
960                let reference_fees: [SignedCredits;
961                (SECOND_START_EPOCH_INDEX + 1000 - CURRENT_EPOCH_INDEX_WHERE_REFUND_OCCURRED) as usize] =
962                [-525, -11272, -11272, -11272, -11272, -11272, -10931, -10931, -10931, -10931,
963                    -10931, -10931, -10931, -10931, -10931, -10931, -10931, -10931, -10811, -10811,
964                    -10811, -10811, -10811, -10811, -10811, -10811, -10471, -10471, -10471, -10471,
965                    -10471, -10471, -10471, -10471, -10471, -10471, -10471, -10471, -10351, -10351,
966                    -10351, -10351, -10351, -10351, -10351, -10351, -10010, -10010, -10010, -10010,
967                    -10010, -10010, -10010, -10010, -10010, -10010, -10010, -10010, -9890, -9890,
968                    -9890, -9890, -9890, -9890, -9890, -9890, -9550, -9550, -9550, -9550, -9550,
969                    -9550, -9550, -9550, -9550, -9550, -9550, -9550, -9460, -9460, -9460, -9460,
970                    -9460, -9460, -9460, -9460, -9119, -9119, -9119, -9119, -9119, -9119, -9119,
971                    -9119, -9119, -9119, -9119, -9119, -9029, -9029, -9029, -9029, -9029, -9029,
972                    -9029, -9029, -8774, -8774, -8774, -8774, -8774, -8774, -8774, -8774, -8774,
973                    -8774, -8774, -8774, -8684, -8684, -8684, -8684, -8684, -8684, -8684, -8684,
974                    -8429, -8429, -8429, -8429, -8429, -8429, -8429, -8429, -8429, -8429, -8429,
975                    -8429, -8339, -8339, -8339, -8339, -8339, -8339, -8339, -8339, -8083, -8083,
976                    -8083, -8083, -8083, -8083, -8083, -8083, -8083, -8083, -8083, -8083, -7993,
977                    -7993, -7993, -7993, -7993, -7993, -7993, -7993, -7738, -7738, -7738, -7738,
978                    -7738, -7738, -7738, -7738, -7738, -7738, -7738, -7738, -7648, -7648, -7648,
979                    -7648, -7648, -7648, -7648, -7648, -7393, -7393, -7393, -7393, -7393, -7393,
980                    -7393, -7393, -7393, -7393, -7393, -7393, -7303, -7303, -7303, -7303, -7303,
981                    -7303, -7303, -7303, -7047, -7047, -7047, -7047, -7047, -7047, -7047, -7047,
982                    -7047, -7047, -7047, -7047, -6987, -6987, -6987, -6987, -6987, -6987, -6987,
983                    -6987, -6732, -6732, -6732, -6732, -6732, -6732, -6732, -6732, -6732, -6732,
984                    -6732, -6732, -6672, -6672, -6672, -6672, -6672, -6672, -6672, -6672, -6502,
985                    -6502, -6502, -6502, -6502, -6502, -6502, -6502, -6502, -6502, -6502, -6502,
986                    -6442, -6442, -6442, -6442, -6442, -6442, -6442, -6442, -6271, -6271, -6271,
987                    -6271, -6271, -6271, -6271, -6271, -6271, -6271, -6271, -6271, -6211, -6211,
988                    -6211, -6211, -6211, -6211, -6211, -6211, -6041, -6041, -6041, -6041, -6041,
989                    -6041, -6041, -6041, -6041, -6041, -6041, -6041, -5981, -5981, -5981, -5981,
990                    -5981, -5981, -5981, -5981, -5811, -5811, -5811, -5811, -5811, -5811, -5811,
991                    -5811, -5811, -5811, -5811, -5811, -5751, -5751, -5751, -5751, -5751, -5751,
992                    -5751, -5751, -5581, -5581, -5581, -5581, -5581, -5581, -5581, -5581, -5581,
993                    -5581, -5581, -5581, -5521, -5521, -5521, -5521, -5521, -5521, -5521, -5521,
994                    -5350, -5350, -5350, -5350, -5350, -5350, -5350, -5350, -5350, -5350, -5350,
995                    -5350, -5290, -5290, -5290, -5290, -5290, -5290, -5290, -5290, -5120, -5120,
996                    -5120, -5120, -5120, -5120, -5120, -5120, -5120, -5120, -5120, -5120, -5060,
997                    -5060, -5060, -5060, -5060, -5060, -5060, -5060, -4890, -4890, -4890, -4890,
998                    -4890, -4890, -4890, -4890, -4890, -4890, -4890, -4890, -4830, -4830, -4830,
999                    -4830, -4830, -4830, -4830, -4830, -4660, -4660, -4660, -4660, -4660, -4660,
1000                    -4660, -4660, -4660, -4660, -4660, -4660, -4615, -4615, -4615, -4615, -4615,
1001                    -4615, -4615, -4615, -4444, -4444, -4444, -4444, -4444, -4444, -4444, -4444,
1002                    -4444, -4444, -4444, -4444, -4399, -4399, -4399, -4399, -4399, -4399, -4399,
1003                    -4399, -4272, -4272, -4272, -4272, -4272, -4272, -4272, -4272, -4272, -4272,
1004                    -4272, -4272, -4227, -4227, -4227, -4227, -4227, -4227, -4227, -4227, -4099,
1005                    -4099, -4099, -4099, -4099, -4099, -4099, -4099, -4099, -4099, -4099, -4099,
1006                    -4054, -4054, -4054, -4054, -4054, -4054, -4054, -4054, -3926, -3926, -3926,
1007                    -3926, -3926, -3926, -3926, -3926, -3926, -3926, -3926, -3926, -3881, -3881,
1008                    -3881, -3881, -3881, -3881, -3881, -3881, -3754, -3754, -3754, -3754, -3754,
1009                    -3754, -3754, -3754, -3754, -3754, -3754, -3754, -3709, -3709, -3709, -3709,
1010                    -3709, -3709, -3709, -3709, -3581, -3581, -3581, -3581, -3581, -3581, -3581,
1011                    -3581, -3581, -3581, -3581, -3581, -3536, -3536, -3536, -3536, -3536, -3536,
1012                    -3536, -3536, -3408, -3408, -3408, -3408, -3408, -3408, -3408, -3408, -3408,
1013                    -3408, -3408, -3408, -3363, -3363, -3363, -3363, -3363, -3363, -3363, -3363,
1014                    -3236, -3236, -3236, -3236, -3236, -3236, -3236, -3236, -3236, -3236, -3236,
1015                    -3236, -3191, -3191, -3191, -3191, -3191, -3191, -3191, -3191, -3063, -3063,
1016                    -3063, -3063, -3063, -3063, -3063, -3063, -3063, -3063, -3063, -3063, -3018,
1017                    -3018, -3018, -3018, -3018, -3018, -3018, -3018, -2890, -2890, -2890, -2890,
1018                    -2890, -2890, -2890, -2890, -2890, -2890, -2890, -2890, -2845, -2845, -2845,
1019                    -2845, -2845, -2845, -2845, -2845, -2717, -2717, -2717, -2717, -2717, -2717,
1020                    -2717, -2717, -2717, -2717, -2717, -2717, -2672, -2672, -2672, -2672, -2672,
1021                    -2672, -2672, -2672, -2545, -2545, -2545, -2545, -2545, -2545, -2545, -2545,
1022                    -2545, -2545, -2545, -2545, -2500, -2500, -2500, -2500, -2500, -2500, -2500,
1023                    -2500, -2372, -2372, -2372, -2372, -2372, -2372, -2372, -2372, -2372, -2372,
1024                    -2372, -2372, -2327, -2327, -2327, -2327, -2327, -2327, -2327, -2327, -2199,
1025                    -2199, -2199, -2199, -2199, -2199, -2199, -2199, -2199, -2199, -2199, -2199,
1026                    -2154, -2154, -2154, -2154, -2154, -2154, -2154, -2154, -2027, -2027, -2027,
1027                    -2027, -2027, -2027, -2027, -2027, -2027, -2027, -2027, -2027, -1982, -1982,
1028                    -1982, -1982, -1982, -1982, -1982, -1982, -1854, -1854, -1854, -1854, -1854,
1029                    -1854, -1854, -1854, -1854, -1854, -1854, -1854, -1809, -1809, -1809, -1809,
1030                    -1809, -1809, -1809, -1809, -1681, -1681, -1681, -1681, -1681, -1681, -1681,
1031                    -1681, -1681, -1681, -1681, -1681, -1636, -1636, -1636, -1636, -1636, -1636,
1032                    -1636, -1636, -1509, -1509, -1509, -1509, -1509, -1509, -1509, -1509, -1509,
1033                    -1509, -1509, -1509, -1464, -1464, -1464, -1464, -1464, -1464, -1464, -1464,
1034                    -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336, -1336,
1035                    -1336, -1306, -1306, -1306, -1306, -1306, -1306, -1306, -1306, -1178, -1178,
1036                    -1178, -1178, -1178, -1178, -1178, -1178, -1178, -1178, -1178, -1178, -1148,
1037                    -1148, -1148, -1148, -1148, -1148, -1148, -1148, -1063, -1063, -1063, -1063,
1038                    -1063, -1063, -1063, -1063, -1063, -1063, -1063, -1063, -1033, -1033, -1033,
1039                    -1033, -1033, -1033, -1033, -1033, -948, -948, -948, -948, -948, -948, -948,
1040                    -948, -948, -948, -948, -948, -918, -918, -918, -918, -918, -918, -918, -918,
1041                    -833, -833, -833, -833, -833, -833, -833, -833, -833, -833, -833, -833, -803,
1042                    -803, -803, -803, -803, -803, -803, -803, -718, -718, -718, -718, -718, -718,
1043                    -718, -718, -718, -718, -718, -718, -688, -688, -688, -688, -688, -688, -688,
1044                    -688, -603, -603, -603, -603, -603, -603, -603, -603, -603, -603, -603, -603,
1045                    -573, -573, -573, -573, -573, -573, -573, -573, -488, -488, -488, -488, -488,
1046                    -488, -488, -488, -488, -488, -488, -488, -458, -458, -458, -458, -458, -458,
1047                    -458, -458, -372, -372, -372, -372, -372, -372, -372, -372, -372, -372, -372,
1048                    -372, -297, -297, -297, -297, -297, -297, -297, -297, -212, -212, -212, -212,
1049                    -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212, -212,
1050                    -212, -212, -212];
1051
1052            assert_eq!(
1053                credits_per_epochs.clone().into_values().collect::<Vec<_>>(),
1054                reference_fees
1055            );
1056
1057            let total_distributed: SignedCredits = credits_per_epochs.values().sum();
1058
1059            assert_eq!(
1060                total_distributed.to_unsigned(),
1061                first_refund_amount + second_refund_amount
1062            );
1063        }
1064    }
1065
1066    mod calculate_storage_fee_refund_amount_and_leftovers {
1067        use super::*;
1068
1069        #[test]
1070        fn should_calculate_amount_and_leftovers() {
1071            let storage_fee = 10000;
1072
1073            let (amount, leftovers) = calculate_storage_fee_refund_amount_and_leftovers(
1074                storage_fee,
1075                GENESIS_EPOCH_INDEX + 1,
1076                2,
1077                20,
1078            )
1079            .expect("should distribute storage fee");
1080
1081            let first_two_epochs_amount = 50;
1082
1083            assert_eq!(leftovers, 400);
1084            assert_eq!(amount, storage_fee - leftovers - first_two_epochs_amount);
1085        }
1086    }
1087}