diff --git a/pallets/ddc-clusters/src/cluster.rs b/pallets/ddc-clusters/src/cluster.rs index 4be19d73f..ff55e49bf 100644 --- a/pallets/ddc-clusters/src/cluster.rs +++ b/pallets/ddc-clusters/src/cluster.rs @@ -3,7 +3,7 @@ use codec::{Decode, Encode}; use ddc_primitives::ClusterId; use frame_support::{pallet_prelude::*, parameter_types}; use scale_info::TypeInfo; -use sp_runtime::Perbill; +use sp_runtime::Perquintill; parameter_types! { pub MaxClusterParamsLen: u16 = 2048; @@ -32,9 +32,9 @@ pub struct ClusterParams { #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo, PartialEq)] #[scale_info(skip_type_params(Balance, BlockNumber, T))] pub struct ClusterGovParams { - pub treasury_share: Perbill, - pub validators_share: Perbill, - pub cluster_reserve_share: Perbill, + pub treasury_share: Perquintill, + pub validators_share: Perquintill, + pub cluster_reserve_share: Perquintill, pub cdn_bond_size: Balance, pub cdn_chill_delay: BlockNumber, pub cdn_unbonding_delay: BlockNumber, diff --git a/pallets/ddc-clusters/src/tests.rs b/pallets/ddc-clusters/src/tests.rs index 922ad7a7a..9e87b2e49 100644 --- a/pallets/ddc-clusters/src/tests.rs +++ b/pallets/ddc-clusters/src/tests.rs @@ -6,7 +6,7 @@ use frame_support::{assert_noop, assert_ok, error::BadOrigin}; use frame_system::Config; use hex_literal::hex; use pallet_ddc_nodes::{CDNNodeParams, NodeParams}; -use sp_runtime::{traits::Hash, AccountId32, Perbill}; +use sp_runtime::{traits::Hash, AccountId32, Perquintill}; #[test] fn create_cluster_works() { @@ -14,9 +14,9 @@ fn create_cluster_works() { System::set_block_number(1); let cluster_gov_params = ClusterGovParams { - treasury_share: Perbill::from_float(0.05), - validators_share: Perbill::from_float(0.01), - cluster_reserve_share: Perbill::from_float(0.02), + treasury_share: Perquintill::from_float(0.05), + validators_share: Perquintill::from_float(0.01), + cluster_reserve_share: Perquintill::from_float(0.02), cdn_bond_size: 100, cdn_chill_delay: 50, cdn_unbonding_delay: 50, @@ -98,9 +98,9 @@ fn add_and_delete_node_works() { AccountId::from([2; 32]), ClusterParams { node_provider_auth_contract: AccountId::from([1; 32]) }, ClusterGovParams { - treasury_share: Perbill::from_float(0.05), - validators_share: Perbill::from_float(0.01), - cluster_reserve_share: Perbill::from_float(0.02), + treasury_share: Perquintill::from_float(0.05), + validators_share: Perquintill::from_float(0.01), + cluster_reserve_share: Perquintill::from_float(0.02), cdn_bond_size: 100, cdn_chill_delay: 50, cdn_unbonding_delay: 50, @@ -309,9 +309,9 @@ fn set_cluster_params_works() { AccountId::from([2; 32]), ClusterParams { node_provider_auth_contract: AccountId::from([1; 32]) }, ClusterGovParams { - treasury_share: Perbill::from_float(0.05), - validators_share: Perbill::from_float(0.01), - cluster_reserve_share: Perbill::from_float(0.02), + treasury_share: Perquintill::from_float(0.05), + validators_share: Perquintill::from_float(0.01), + cluster_reserve_share: Perquintill::from_float(0.02), cdn_bond_size: 100, cdn_chill_delay: 50, cdn_unbonding_delay: 50, @@ -354,9 +354,9 @@ fn set_cluster_gov_params_works() { System::set_block_number(1); let cluster_gov_params = ClusterGovParams { - treasury_share: Perbill::from_float(0.05), - validators_share: Perbill::from_float(0.01), - cluster_reserve_share: Perbill::from_float(0.02), + treasury_share: Perquintill::from_float(0.05), + validators_share: Perquintill::from_float(0.01), + cluster_reserve_share: Perquintill::from_float(0.02), cdn_bond_size: 100, cdn_chill_delay: 50, cdn_unbonding_delay: 50, diff --git a/pallets/ddc-customers/src/mock.rs b/pallets/ddc-customers/src/mock.rs index 5912347eb..43db67e76 100644 --- a/pallets/ddc-customers/src/mock.rs +++ b/pallets/ddc-customers/src/mock.rs @@ -15,7 +15,7 @@ use sp_io::TestExternalities; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, - Perbill, + Perquintill, }; /// The AccountId alias in this test module. @@ -143,9 +143,9 @@ impl ClusterVisitor for TestClusterVisitor { fn get_fees_params(_cluster_id: &ClusterId) -> Result { Ok(ClusterFeesParams { - treasury_share: Perbill::from_percent(1), - validators_share: Perbill::from_percent(10), - cluster_reserve_share: Perbill::from_percent(2), + treasury_share: Perquintill::from_percent(1), + validators_share: Perquintill::from_percent(10), + cluster_reserve_share: Perquintill::from_percent(2), }) } diff --git a/pallets/ddc-payouts/src/lib.rs b/pallets/ddc-payouts/src/lib.rs index af50c033b..d17052f6c 100644 --- a/pallets/ddc-payouts/src/lib.rs +++ b/pallets/ddc-payouts/src/lib.rs @@ -34,7 +34,7 @@ use frame_support::{ }; use frame_system::pallet_prelude::*; pub use pallet::*; -use sp_runtime::{PerThing, Perbill}; +use sp_runtime::{PerThing, Perquintill}; use sp_std::prelude::*; type BatchIndex = u16; @@ -89,6 +89,7 @@ pub type BalanceOf = parameter_types! { pub MaxBatchesCount: u16 = 1000; + pub MaxDust: u16 = 20000; } #[frame_support::pallet] @@ -378,12 +379,12 @@ pub mod pallet { .ok_or(Error::::ArithmeticOverflow)?; let customer_id = payer.0.clone(); - let amount_actually_charged = T::CustomerCharger::charge_content_owner( + /*let amount_actually_charged = T::CustomerCharger::charge_content_owner( customer_id.clone(), updated_billing_report.vault.clone(), total_customer_charge, - )?; - /* + )?;*/ + let amount_actually_charged = match T::CustomerCharger::charge_content_owner( customer_id.clone(), updated_billing_report.vault.clone(), @@ -391,7 +392,7 @@ pub mod pallet { ) { Ok(actually_charged) => actually_charged, Err(_e) => 0, - }; */ + }; if amount_actually_charged < total_customer_charge { // debt @@ -427,8 +428,10 @@ pub mod pallet { if amount_actually_charged > 0 { // something was charged and should be added // calculate ratio - let ratio = - Perbill::from_rational(amount_actually_charged, total_customer_charge); + let ratio = Perquintill::from_rational( + amount_actually_charged, + total_customer_charge, + ); customer_charge.storage = ratio * customer_charge.storage; customer_charge.transfer = ratio * customer_charge.transfer; @@ -654,19 +657,21 @@ pub mod pallet { .ok_or(Error::::ArithmeticOverflow)?; let node_provider_id = payee.0; - let reward: BalanceOf = amount_to_reward.saturated_into::>(); - - ::Currency::transfer( - &updated_billing_report.vault, - &node_provider_id, - reward, - ExistenceRequirement::AllowDeath, - )?; - - updated_billing_report - .total_distributed_reward - .checked_add(amount_to_reward) - .ok_or(Error::::ArithmeticOverflow)?; + if amount_to_reward > 0 { + let reward: BalanceOf = amount_to_reward.saturated_into::>(); + + ::Currency::transfer( + &updated_billing_report.vault, + &node_provider_id, + reward, + ExistenceRequirement::AllowDeath, + )?; + + updated_billing_report.total_distributed_reward = updated_billing_report + .total_distributed_reward + .checked_add(amount_to_reward) + .ok_or(Error::::ArithmeticOverflow)?; + } Self::deposit_event(Event::::Rewarded { cluster_id, @@ -708,6 +713,22 @@ pub mod pallet { &billing_report.rewarding_max_batch_index, )?; + let expected_amount_to_reward = (|| -> Option { + billing_report + .total_customer_charge + .transfer + .checked_add(billing_report.total_customer_charge.storage)? + .checked_add(billing_report.total_customer_charge.puts)? + .checked_add(billing_report.total_customer_charge.gets) + })() + .ok_or(Error::::ArithmeticOverflow)?; + + ensure!( + expected_amount_to_reward - billing_report.total_distributed_reward <= + MaxDust::get().into(), + Error::::NotDistributedBalance + ); + billing_report.state = State::ProvidersRewarded; ActiveBillingReports::::insert(cluster_id, era, billing_report); @@ -729,20 +750,6 @@ pub mod pallet { .map_err(|_| Error::::BillingReportDoesNotExist)?; ensure!(billing_report.state == State::ProvidersRewarded, Error::::NotExpectedState); - let expected_amount_to_reward = (|| -> Option { - billing_report - .total_customer_charge - .transfer - .checked_add(billing_report.total_customer_charge.storage)? - .checked_add(billing_report.total_customer_charge.puts)? - .checked_add(billing_report.total_customer_charge.gets) - })() - .ok_or(Error::::ArithmeticOverflow)?; - - ensure!( - expected_amount_to_reward == billing_report.total_distributed_reward, - Error::::NotDistributedBalance - ); billing_report.charging_processed_batches.clear(); billing_report.rewarding_processed_batches.clear(); @@ -811,20 +818,23 @@ pub mod pallet { ) -> Option { let mut node_reward = NodeReward::default(); - let mut ratio = Perbill::from_rational( + let mut ratio = Perquintill::from_rational( node_usage.transferred_bytes, total_nodes_usage.transferred_bytes, ); + // ratio multiplied by X will be > 0, < X no overflow node_reward.transfer = ratio * total_customer_charge.transfer; - ratio = Perbill::from_rational(node_usage.stored_bytes, total_nodes_usage.stored_bytes); + ratio = Perquintill::from_rational(node_usage.stored_bytes, total_nodes_usage.stored_bytes); node_reward.storage = ratio * total_customer_charge.storage; - ratio = Perbill::from_rational(node_usage.number_of_puts, total_nodes_usage.number_of_puts); + ratio = + Perquintill::from_rational(node_usage.number_of_puts, total_nodes_usage.number_of_puts); node_reward.puts = ratio * total_customer_charge.puts; - ratio = Perbill::from_rational(node_usage.number_of_gets, total_nodes_usage.number_of_gets); + ratio = + Perquintill::from_rational(node_usage.number_of_gets, total_nodes_usage.number_of_gets); node_reward.gets = ratio * total_customer_charge.gets; Some(node_reward) diff --git a/pallets/ddc-payouts/src/mock.rs b/pallets/ddc-payouts/src/mock.rs index 25e6b443c..74abd95f2 100644 --- a/pallets/ddc-payouts/src/mock.rs +++ b/pallets/ddc-payouts/src/mock.rs @@ -23,7 +23,7 @@ use sp_io::TestExternalities; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, - DispatchError, + DispatchError, Perquintill, }; use sp_std::prelude::*; @@ -117,7 +117,10 @@ impl CustomerCharger for TestCustomerCharger { ensure!(amount > 1_000_000, DispatchError::BadOrigin); // any error will do let mut amount_to_charge = amount; - if amount_to_charge < 50_000_000 { + let temp = ACCOUNT_ID_5.to_ne_bytes(); + let account_5 = T::AccountId::decode(&mut &temp[..]).unwrap(); + + if amount_to_charge < 50_000_000 && content_owner != account_5 { amount_to_charge = PARTIAL_CHARGE; // for user 3 } @@ -133,6 +136,7 @@ impl CustomerCharger for TestCustomerCharger { } } +pub const ACCOUNT_ID_5: AccountId = 5; pub const RESERVE_ACCOUNT_ID: AccountId = 999; pub const TREASURY_ACCOUNT_ID: AccountId = 888; pub const VALIDATOR1_ACCOUNT_ID: AccountId = 111; @@ -142,6 +146,7 @@ pub const PARTIAL_CHARGE: u128 = 100; pub const USER3_BALANCE: u128 = 1000; pub const FREE_CLUSTER_ID: ClusterId = ClusterId::zero(); +pub const ONE_CLUSTER_ID: ClusterId = ClusterId::repeat_byte(5u8); pub const PRICING_PARAMS: ClusterPricingParams = ClusterPricingParams { unit_per_mb_streamed: 2_000_000, @@ -150,16 +155,23 @@ pub const PRICING_PARAMS: ClusterPricingParams = ClusterPricingParams { unit_per_get_request: 5_000_000, }; +pub const PRICING_PARAMS_ONE: ClusterPricingParams = ClusterPricingParams { + unit_per_mb_streamed: 10_000_000_000, + unit_per_mb_stored: 10_000_000_000, + unit_per_put_request: 10_000_000_000, + unit_per_get_request: 10_000_000_000, +}; + pub const PRICING_FEES: ClusterFeesParams = ClusterFeesParams { - treasury_share: Perbill::from_percent(1), - validators_share: Perbill::from_percent(10), - cluster_reserve_share: Perbill::from_percent(2), + treasury_share: Perquintill::from_percent(1), + validators_share: Perquintill::from_percent(10), + cluster_reserve_share: Perquintill::from_percent(2), }; pub const PRICING_FEES_ZERO: ClusterFeesParams = ClusterFeesParams { - treasury_share: Perbill::from_percent(0), - validators_share: Perbill::from_percent(0), - cluster_reserve_share: Perbill::from_percent(0), + treasury_share: Perquintill::from_percent(0), + validators_share: Perquintill::from_percent(0), + cluster_reserve_share: Perquintill::from_percent(0), }; pub struct TestTreasuryVisitor; @@ -240,7 +252,7 @@ impl SortedListProvider for TestValidator } pub fn get_fees(cluster_id: &ClusterId) -> Result { - if *cluster_id == FREE_CLUSTER_ID { + if *cluster_id == FREE_CLUSTER_ID || *cluster_id == ONE_CLUSTER_ID { Ok(PRICING_FEES_ZERO) } else { Ok(PRICING_FEES) @@ -275,9 +287,13 @@ impl ClusterVisitor for TestClusterVisitor { } fn get_pricing_params( - _cluster_id: &ClusterId, + cluster_id: &ClusterId, ) -> Result { - Ok(PRICING_PARAMS) + if *cluster_id == FREE_CLUSTER_ID || *cluster_id == ONE_CLUSTER_ID { + Ok(PRICING_PARAMS_ONE) + } else { + Ok(PRICING_PARAMS) + } } fn get_fees_params(cluster_id: &ClusterId) -> Result { @@ -303,10 +319,11 @@ impl ExtBuilder { let _ = pallet_balances::GenesisConfig:: { balances: vec![ - (1, 1000000000000000000000000), + (1, 10000000000000000000000000000), (2, 10), // < PARTIAL_CHARGE (3, USER3_BALANCE), // > PARTIAL_CHARGE (4, 1000000000000000000000000), + (5, 1000000000000000000000000), ], } .assimilate_storage(&mut storage); diff --git a/pallets/ddc-payouts/src/tests.rs b/pallets/ddc-payouts/src/tests.rs index 1e2ea13f2..6bab56cce 100644 --- a/pallets/ddc-payouts/src/tests.rs +++ b/pallets/ddc-payouts/src/tests.rs @@ -3,7 +3,7 @@ use super::{mock::*, *}; use ddc_primitives::ClusterId; use frame_support::{assert_noop, assert_ok, error::BadOrigin}; - +use sp_runtime::Perquintill; #[test] fn set_authorised_caller_works() { ExtBuilder.build_and_execute(|| { @@ -257,24 +257,30 @@ fn send_charging_customers_batch_fails_uninitialised() { }) } -fn calculate_charge_parts(usage: CustomerUsage) -> CustomerCharge { +fn calculate_charge_parts(cluster_id: ClusterId, usage: CustomerUsage) -> CustomerCharge { + let pricing_params = if cluster_id == FREE_CLUSTER_ID || cluster_id == ONE_CLUSTER_ID { + PRICING_PARAMS_ONE + } else { + PRICING_PARAMS + }; + CustomerCharge { - transfer: PRICING_PARAMS.unit_per_mb_streamed * (usage.transferred_bytes as u128) / + transfer: pricing_params.unit_per_mb_streamed * (usage.transferred_bytes as u128) / byte_unit::MEBIBYTE, - storage: (PRICING_PARAMS.unit_per_mb_stored * usage.stored_bytes as u128) / + storage: (pricing_params.unit_per_mb_stored * usage.stored_bytes as u128) / byte_unit::MEBIBYTE, - puts: PRICING_PARAMS.unit_per_put_request * usage.number_of_puts, - gets: PRICING_PARAMS.unit_per_get_request * usage.number_of_gets, + puts: pricing_params.unit_per_put_request * usage.number_of_puts, + gets: pricing_params.unit_per_get_request * usage.number_of_gets, } } -fn calculate_charge(usage: CustomerUsage) -> u128 { - let charge = calculate_charge_parts(usage); +fn calculate_charge(cluster_id: ClusterId, usage: CustomerUsage) -> u128 { + let charge = calculate_charge_parts(cluster_id, usage); charge.transfer + charge.storage + charge.puts + charge.gets } #[test] -fn send_charging_customers_batch_works() { +fn send_charging_customers_batch_works1() { ExtBuilder.build_and_execute(|| { System::set_block_number(1); @@ -343,17 +349,17 @@ fn send_charging_customers_batch_works() { payers1, )); - let usage4_charge = calculate_charge(usage4.clone()); + let usage4_charge = calculate_charge(cluster_id, usage4.clone()); let mut balance = Balances::free_balance(DdcPayouts::sub_account_id(cluster_id, era)); assert_eq!(balance, usage4_charge); let user2_debt = DdcPayouts::debtor_customers(cluster_id, user2_debtor).unwrap(); - let mut debt = calculate_charge(usage2.clone()); + let mut debt = calculate_charge(cluster_id, usage2.clone()); assert_eq!(user2_debt, debt); let mut report = DdcPayouts::active_billing_reports(cluster_id, era).unwrap(); - let charge2 = calculate_charge_parts(usage2); - let charge4 = calculate_charge_parts(usage4); + let charge2 = calculate_charge_parts(cluster_id, usage2); + let charge4 = calculate_charge_parts(cluster_id, usage4); assert_eq!(charge2.puts + charge4.puts, report.total_customer_charge.puts); assert_eq!(charge2.gets + charge4.gets, report.total_customer_charge.gets); assert_eq!(charge2.storage + charge4.storage, report.total_customer_charge.storage); @@ -410,13 +416,13 @@ fn send_charging_customers_batch_works() { era, batch_index, customer_id: user1, - amount: calculate_charge(usage1.clone()), + amount: calculate_charge(cluster_id, usage1.clone()), } .into(), ); report = DdcPayouts::active_billing_reports(cluster_id, era).unwrap(); - let charge1 = calculate_charge_parts(usage1); + let charge1 = calculate_charge_parts(cluster_id, usage1); assert_eq!( charge1.puts + before_total_customer_charge.puts, report.total_customer_charge.puts @@ -441,7 +447,7 @@ fn send_charging_customers_batch_works() { let balance_before = Balances::free_balance(DdcPayouts::sub_account_id(cluster_id, era)); // batch 3 - batch_index += 2; + batch_index += 1; before_total_customer_charge = report.total_customer_charge.clone(); assert_ok!(DdcPayouts::send_charging_customers_batch( RuntimeOrigin::signed(dac_account), @@ -451,9 +457,9 @@ fn send_charging_customers_batch_works() { payers3, )); - let user3_charge = calculate_charge(usage3.clone()); - let charge3 = calculate_charge_parts(usage3); - let ratio = Perbill::from_rational(PARTIAL_CHARGE, user3_charge); + let user3_charge = calculate_charge(cluster_id, usage3.clone()); + let charge3 = calculate_charge_parts(cluster_id, usage3); + let ratio = Perquintill::from_rational(PARTIAL_CHARGE, user3_charge); report = DdcPayouts::active_billing_reports(cluster_id, era).unwrap(); assert_eq!( ratio * charge3.puts + before_total_customer_charge.puts, @@ -503,6 +509,77 @@ fn send_charging_customers_batch_works() { }) } +#[test] +fn send_charging_customers_batch_works2() { + ExtBuilder.build_and_execute(|| { + System::set_block_number(1); + + let dac_account = 123u128; + let user5 = 5u128; + let cluster_id = ONE_CLUSTER_ID; + let era = 100; + let max_batch_index = 0; + let batch_index = 0; + let usage5 = CustomerUsage { + // should pass without debt + transferred_bytes: 1024, + stored_bytes: 1024, + number_of_puts: 1, + number_of_gets: 1, + }; + let payers5 = vec![(user5, usage5.clone())]; + + assert_ok!(DdcPayouts::set_authorised_caller(RuntimeOrigin::root(), dac_account)); + assert_ok!(DdcPayouts::begin_billing_report( + RuntimeOrigin::signed(dac_account), + cluster_id, + era, + )); + + assert_ok!(DdcPayouts::begin_charging_customers( + RuntimeOrigin::signed(dac_account), + cluster_id, + era, + max_batch_index, + )); + assert_eq!(System::events().len(), 3); + + // batch 1 + let mut report = DdcPayouts::active_billing_reports(cluster_id, era).unwrap(); + let before_total_customer_charge = report.total_customer_charge.clone(); + let balance_before = Balances::free_balance(DdcPayouts::sub_account_id(cluster_id, era)); + assert_ok!(DdcPayouts::send_charging_customers_batch( + RuntimeOrigin::signed(dac_account), + cluster_id, + era, + batch_index, + payers5, + )); + + let usage5_charge = calculate_charge(cluster_id, usage5.clone()); + let charge5 = calculate_charge_parts(cluster_id, usage5); + let balance = Balances::free_balance(DdcPayouts::sub_account_id(cluster_id, era)); + report = DdcPayouts::active_billing_reports(cluster_id, era).unwrap(); + assert_eq!(balance, usage5_charge + balance_before); + assert_eq!( + charge5.puts + before_total_customer_charge.puts, + report.total_customer_charge.puts + ); + assert_eq!( + charge5.gets + before_total_customer_charge.gets, + report.total_customer_charge.gets + ); + assert_eq!( + charge5.storage + before_total_customer_charge.storage, + report.total_customer_charge.storage + ); + assert_eq!( + charge5.transfer + before_total_customer_charge.transfer, + report.total_customer_charge.transfer + ); + }) +} + #[test] fn end_charging_customers_fails_uninitialised() { ExtBuilder.build_and_execute(|| { @@ -617,7 +694,7 @@ fn end_charging_customers_works() { )); let report_before = DdcPayouts::active_billing_reports(cluster_id, era).unwrap(); - let charge = calculate_charge(usage1); + let charge = calculate_charge(cluster_id, usage1); System::assert_last_event( Event::Charged { cluster_id, era, batch_index, customer_id: user1, amount: charge } .into(), @@ -710,8 +787,8 @@ fn end_charging_customers_works_zero_fees() { let usage1 = CustomerUsage { transferred_bytes: 23452345, stored_bytes: 3345234523, - number_of_puts: 4456456345234523, - number_of_gets: 523423, + number_of_puts: 1, + number_of_gets: 1, }; let payers = vec![(user1, usage1.clone())]; @@ -739,7 +816,7 @@ fn end_charging_customers_works_zero_fees() { )); let report_before = DdcPayouts::active_billing_reports(cluster_id, era).unwrap(); - let charge = calculate_charge(usage1); + let charge = calculate_charge(cluster_id, usage1); System::assert_last_event( Event::Charged { cluster_id, era, customer_id: user1, batch_index, amount: charge } .into(), @@ -767,11 +844,11 @@ fn end_charging_customers_works_zero_fees() { (fees.treasury_share + fees.validators_share + fees.cluster_reserve_share) .left_from_one(); - assert_eq!(total_left_from_one, Perbill::one()); + assert_eq!(total_left_from_one, Perquintill::one()); - assert_eq!(fees.treasury_share, Perbill::zero()); - assert_eq!(fees.validators_share, Perbill::zero()); - assert_eq!(fees.cluster_reserve_share, Perbill::zero()); + assert_eq!(fees.treasury_share, Perquintill::zero()); + assert_eq!(fees.validators_share, Perquintill::zero()); + assert_eq!(fees.cluster_reserve_share, Perquintill::zero()); balance = Balances::free_balance(TREASURY_ACCOUNT_ID); assert_eq!(balance, 0); @@ -1269,46 +1346,59 @@ fn send_rewarding_providers_batch_works() { payees1, )); - let mut ratio = Perbill::from_rational( + let ratio1_transfer = Perquintill::from_rational( node_usage1.transferred_bytes, total_nodes_usage.transferred_bytes, ); - let mut transfer_charge = ratio * report_after.total_customer_charge.transfer; + let mut transfer_charge = ratio1_transfer * report_after.total_customer_charge.transfer; - ratio = Perbill::from_rational(node_usage1.stored_bytes, total_nodes_usage.stored_bytes); - let mut storage_charge = ratio * report_after.total_customer_charge.storage; + let ratio1_storage = + Perquintill::from_rational(node_usage1.stored_bytes, total_nodes_usage.stored_bytes); + let mut storage_charge = ratio1_storage * report_after.total_customer_charge.storage; - ratio = - Perbill::from_rational(node_usage1.number_of_puts, total_nodes_usage.number_of_puts); - let mut puts_charge = ratio * report_after.total_customer_charge.puts; + let ratio1_puts = Perquintill::from_rational( + node_usage1.number_of_puts, + total_nodes_usage.number_of_puts, + ); + let mut puts_charge = ratio1_puts * report_after.total_customer_charge.puts; - ratio = - Perbill::from_rational(node_usage1.number_of_gets, total_nodes_usage.number_of_gets); - let mut gets_charge = ratio * report_after.total_customer_charge.gets; + let ratio1_gets = Perquintill::from_rational( + node_usage1.number_of_gets, + total_nodes_usage.number_of_gets, + ); + let mut gets_charge = ratio1_gets * report_after.total_customer_charge.gets; - let mut balance = Balances::free_balance(node1); - assert_eq!(balance, transfer_charge + storage_charge + puts_charge + gets_charge); + let balance_node1 = Balances::free_balance(node1); + assert_eq!(balance_node1, transfer_charge + storage_charge + puts_charge + gets_charge); + let mut report_reward = DdcPayouts::active_billing_reports(cluster_id, era).unwrap(); - ratio = Perbill::from_rational( + let ratio2_transfer = Perquintill::from_rational( node_usage2.transferred_bytes, total_nodes_usage.transferred_bytes, ); - transfer_charge = ratio * report_after.total_customer_charge.transfer; + transfer_charge = ratio2_transfer * report_after.total_customer_charge.transfer; - ratio = Perbill::from_rational(node_usage2.stored_bytes, total_nodes_usage.stored_bytes); - storage_charge = ratio * report_after.total_customer_charge.storage; + let ratio2_storage = + Perquintill::from_rational(node_usage2.stored_bytes, total_nodes_usage.stored_bytes); + storage_charge = ratio2_storage * report_after.total_customer_charge.storage; - ratio = - Perbill::from_rational(node_usage2.number_of_puts, total_nodes_usage.number_of_puts); - puts_charge = ratio * report_after.total_customer_charge.puts; + let ratio2_puts = Perquintill::from_rational( + node_usage2.number_of_puts, + total_nodes_usage.number_of_puts, + ); + puts_charge = ratio2_puts * report_after.total_customer_charge.puts; - ratio = - Perbill::from_rational(node_usage2.number_of_gets, total_nodes_usage.number_of_gets); - gets_charge = ratio * report_after.total_customer_charge.gets; + let ratio2_gets = Perquintill::from_rational( + node_usage2.number_of_gets, + total_nodes_usage.number_of_gets, + ); + gets_charge = ratio2_gets * report_after.total_customer_charge.gets; - balance = Balances::free_balance(node2); - assert_eq!(balance, transfer_charge + storage_charge + puts_charge + gets_charge); + let balance_node2 = Balances::free_balance(node2); + assert_eq!(balance_node2, transfer_charge + storage_charge + puts_charge + gets_charge); + assert_eq!(report_reward.total_distributed_reward, balance_node1 + balance_node2); + // batch 2 assert_ok!(DdcPayouts::send_rewarding_providers_batch( RuntimeOrigin::signed(dac_account), cluster_id, @@ -1317,25 +1407,42 @@ fn send_rewarding_providers_batch_works() { payees2, )); - ratio = Perbill::from_rational( + let ratio3_transfer = Perquintill::from_rational( node_usage3.transferred_bytes, total_nodes_usage.transferred_bytes, ); - transfer_charge = ratio * report_after.total_customer_charge.transfer; + transfer_charge = ratio3_transfer * report_after.total_customer_charge.transfer; - ratio = Perbill::from_rational(node_usage3.stored_bytes, total_nodes_usage.stored_bytes); - storage_charge = ratio * report_after.total_customer_charge.storage; + let ratio3_storage = + Perquintill::from_rational(node_usage3.stored_bytes, total_nodes_usage.stored_bytes); + storage_charge = ratio3_storage * report_after.total_customer_charge.storage; - ratio = - Perbill::from_rational(node_usage3.number_of_puts, total_nodes_usage.number_of_puts); - puts_charge = ratio * report_after.total_customer_charge.puts; + let ratio3_puts = Perquintill::from_rational( + node_usage3.number_of_puts, + total_nodes_usage.number_of_puts, + ); + puts_charge = ratio3_puts * report_after.total_customer_charge.puts; - ratio = - Perbill::from_rational(node_usage3.number_of_gets, total_nodes_usage.number_of_gets); - gets_charge = ratio * report_after.total_customer_charge.gets; + let ratio3_gets = Perquintill::from_rational( + node_usage3.number_of_gets, + total_nodes_usage.number_of_gets, + ); + gets_charge = ratio3_gets * report_after.total_customer_charge.gets; - balance = Balances::free_balance(node3); - assert_eq!(balance, transfer_charge + storage_charge + puts_charge + gets_charge); + report_reward = DdcPayouts::active_billing_reports(cluster_id, era).unwrap(); + let balance_node3 = Balances::free_balance(node3); + assert_eq!(balance_node3, transfer_charge + storage_charge + puts_charge + gets_charge); + assert_eq!( + report_reward.total_distributed_reward, + balance_node1 + balance_node2 + balance_node3 + ); + + let expected_amount_to_reward = report_reward.total_customer_charge.transfer + + report_reward.total_customer_charge.storage + + report_reward.total_customer_charge.puts + + report_reward.total_customer_charge.gets; + + assert!(expected_amount_to_reward - report_reward.total_distributed_reward <= 20000); assert_ok!(DdcPayouts::end_rewarding_providers( RuntimeOrigin::signed(dac_account), @@ -1509,15 +1616,29 @@ fn end_rewarding_providers_works() { System::set_block_number(1); let dac_account = 2u128; - let user1 = 3u128; + let user1 = 1u128; let node1 = 33u128; let cluster_id = ClusterId::from([12; 20]); let era = 100; let max_batch_index = 0; let batch_index = 0; - let total_node_usage = NodeUsage::default(); - let payers = vec![(user1, CustomerUsage::default())]; - let payees = vec![(node1, NodeUsage::default())]; + let usage1 = CustomerUsage { + transferred_bytes: 23452345, + stored_bytes: 3345234523, + number_of_puts: 4456456345234523, + number_of_gets: 523423, + }; + + let node_usage1 = NodeUsage { + // CDN + Storage + transferred_bytes: usage1.transferred_bytes * 2 / 3, + stored_bytes: usage1.stored_bytes * 2 / 3, + number_of_puts: usage1.number_of_puts * 2 / 3, + number_of_gets: usage1.number_of_gets * 2 / 3, + }; + let total_node_usage = node_usage1.clone(); + let payers = vec![(user1, usage1)]; + let payees = vec![(node1, node_usage1)]; assert_ok!(DdcPayouts::set_authorised_caller(RuntimeOrigin::root(), dac_account)); diff --git a/pallets/ddc-staking/src/mock.rs b/pallets/ddc-staking/src/mock.rs index eaee9f844..9085b5ed5 100644 --- a/pallets/ddc-staking/src/mock.rs +++ b/pallets/ddc-staking/src/mock.rs @@ -20,7 +20,7 @@ use sp_io::TestExternalities; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, - Perbill, + Perquintill, }; use sp_std::collections::btree_map::BTreeMap; @@ -146,9 +146,9 @@ impl ClusterVisitor for TestClusterVisitor { fn get_fees_params(_cluster_id: &ClusterId) -> Result { Ok(ClusterFeesParams { - treasury_share: Perbill::from_percent(1), - validators_share: Perbill::from_percent(10), - cluster_reserve_share: Perbill::from_percent(2), + treasury_share: Perquintill::from_percent(1), + validators_share: Perquintill::from_percent(10), + cluster_reserve_share: Perquintill::from_percent(2), }) } diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 78c25e2f7..54b1c0c9e 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -5,7 +5,7 @@ use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_core::hash::H160; -use sp_runtime::{AccountId32, Perbill, RuntimeDebug}; +use sp_runtime::{AccountId32, Perquintill, RuntimeDebug}; pub type ClusterId = H160; pub type DdcEra = u32; pub type BucketId = u64; @@ -21,9 +21,9 @@ pub struct ClusterPricingParams { #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo, PartialEq)] pub struct ClusterFeesParams { - pub treasury_share: Perbill, - pub validators_share: Perbill, - pub cluster_reserve_share: Perbill, + pub treasury_share: Perquintill, + pub validators_share: Perquintill, + pub cluster_reserve_share: Perquintill, } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]