From bcc0a50b49c8c8b9a5588685de2f7071d83af0aa Mon Sep 17 00:00:00 2001
From: Benjamin Gallois <business@gallois.cc>
Date: Wed, 13 Nov 2024 12:40:44 +0100
Subject: [PATCH] Refactore Runtime handlers and providers
 (nodes/rust/duniter-v2s!286)

* refactor inconsistent generic syntax

* optimize TreasuryAccount

* move MembersCount

* move handle dust
---
 runtime/common/src/handlers.rs       | 29 +++++++++++++--
 runtime/common/src/pallets_config.rs | 53 +++++++---------------------
 runtime/common/src/providers.rs      | 38 +++++++++++++-------
 runtime/g1/src/lib.rs                |  5 +--
 runtime/gdev/src/lib.rs              |  5 +--
 runtime/gtest/src/lib.rs             |  5 +--
 6 files changed, 67 insertions(+), 68 deletions(-)

diff --git a/runtime/common/src/handlers.rs b/runtime/common/src/handlers.rs
index 197e35743..ff9aba851 100644
--- a/runtime/common/src/handlers.rs
+++ b/runtime/common/src/handlers.rs
@@ -15,7 +15,10 @@
 // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
 
 use super::{entities::*, AccountId, IdtyIndex};
-use frame_support::{pallet_prelude::Weight, traits::UnfilteredDispatchable};
+use frame_support::{
+    pallet_prelude::Weight,
+    traits::{Imbalance, UnfilteredDispatchable},
+};
 use pallet_smith_members::SmithRemovalReason;
 use sp_core::Get;
 
@@ -97,7 +100,7 @@ impl<
 /// done at the handler level.
 pub struct OnRemoveMembershipHandler<Runtime>(core::marker::PhantomData<Runtime>);
 impl<
-        Runtime: frame_system::Config<AccountId = AccountId>
+        Runtime: frame_system::Config
             + pallet_identity::Config<IdtyData = IdtyData, IdtyIndex = IdtyIndex>
             + pallet_smith_members::Config<IdtyIndex = IdtyIndex>
             + pallet_duniter_wot::Config
@@ -178,3 +181,25 @@ impl<
         !pallet_authority_members::Pallet::<Runtime>::online().contains(idty_index)
     }
 }
+
+/// Runtime handler for managing fee handling by transferring unbalanced amounts to a treasury account.
+pub struct HandleFees<TreasuryAccount, Balances>(
+    frame_support::pallet_prelude::PhantomData<TreasuryAccount>,
+    frame_support::pallet_prelude::PhantomData<Balances>,
+);
+type CreditOf<Balances> = frame_support::traits::tokens::fungible::Credit<AccountId, Balances>;
+impl<TreasuryAccount, Balances> frame_support::traits::OnUnbalanced<CreditOf<Balances>>
+    for HandleFees<TreasuryAccount, Balances>
+where
+    TreasuryAccount: Get<AccountId>,
+    Balances: frame_support::traits::fungible::Balanced<AccountId>,
+{
+    fn on_nonzero_unbalanced(amount: CreditOf<Balances>) {
+        // fee is moved to treasury
+        let _ = Balances::deposit(
+            &TreasuryAccount::get(),
+            amount.peek(),
+            frame_support::traits::tokens::Precision::Exact,
+        );
+    }
+}
diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs
index 0b906cddb..dd41a49ed 100644
--- a/runtime/common/src/pallets_config.rs
+++ b/runtime/common/src/pallets_config.rs
@@ -104,30 +104,22 @@ macro_rules! pallets_config {
 
         impl pallet_duniter_account::Config for Runtime {
             // does currency adapter in any case, but adds "refund with quota" feature
-            type InnerOnChargeTransaction = FungibleAdapter<Balances, HandleFees>;
+            type InnerOnChargeTransaction =
+                FungibleAdapter<Balances, HandleFees<TreasuryAccount, Balances>>;
             type Refund = Quota;
             type RuntimeEvent = RuntimeEvent;
             type WeightInfo = weights::pallet_duniter_account::WeightInfo<Runtime>;
         }
 
-        // QUOTA //
-        pub struct TreasuryAccountId;
-        impl frame_support::pallet_prelude::Get<AccountId> for TreasuryAccountId {
-            fn get() -> AccountId {
-                // TODO optimize: make this a constant
-                // calling Treasury.account_id() actually requires computation
-                Treasury::account_id()
-            }
-        }
         parameter_types! {
-                    pub const ReloadRate: BlockNumber = 1 * HOURS; // faster than DAYS
-                    pub const MaxQuota: Balance = 1000; // 10 ÄžD
-                    pub const MaxNominators: u32 = 64;
-        pub TreasuryAccount: AccountId = Treasury::account_id(); // TODO
-                }
+            pub const ReloadRate: BlockNumber = 1 * HOURS; // faster than DAYS
+            pub const MaxQuota: Balance = 1000; // 10 ÄžD
+            pub const MaxNominators: u32 = 64;
+            pub TreasuryAccount: AccountId = Treasury::account_id();
+        }
         impl pallet_quota::Config for Runtime {
             type MaxQuota = MaxQuota;
-            type RefundAccount = TreasuryAccountId;
+            type RefundAccount = TreasuryAccount;
             type ReloadRate = ReloadRate;
             type RuntimeEvent = RuntimeEvent;
             type WeightInfo = weights::pallet_quota::WeightInfo<Runtime>;
@@ -162,7 +154,7 @@ macro_rules! pallets_config {
         impl pallet_balances::Config for Runtime {
             type AccountStore = Account;
             type Balance = Balance;
-            type DustRemoval = HandleFees;
+            type DustRemoval = HandleFees<TreasuryAccount, Balances>;
             type ExistentialDeposit = ExistentialDeposit;
             type FreezeIdentifier = ();
             type MaxFreezes = frame_support::pallet_prelude::ConstU32<0>;
@@ -175,20 +167,6 @@ macro_rules! pallets_config {
             type WeightInfo = weights::pallet_balances::WeightInfo<Runtime>;
         }
 
-        type CreditOf = frame_support::traits::tokens::fungible::Credit<AccountId, Balances>;
-        pub struct HandleFees;
-        impl frame_support::traits::OnUnbalanced<CreditOf> for HandleFees {
-            fn on_nonzero_unbalanced(amount: CreditOf) {
-                // fee is moved to treasury
-                let _ = Balances::deposit(
-                    &Treasury::account_id(),
-                    amount.peek(),
-                    frame_support::traits::tokens::Precision::Exact,
-                );
-            }
-        }
-        pub struct OnChargeTransaction;
-
         parameter_types! {
         pub Target: Perquintill = Perquintill::from_percent(25);
         pub MaxMultiplier: sp_runtime::FixedU128 = 10.into();
@@ -336,7 +314,7 @@ macro_rules! pallets_config {
             type GetCurrentEpochIndex = GetCurrentEpochIndex<Self>;
             type MaxRequests = frame_support::traits::ConstU32<100>;
             type OnFilledRandomness = ();
-            type OnUnbalanced = HandleFees;
+            type OnUnbalanced = HandleFees<TreasuryAccount, Balances>;
             type ParentBlockRandomness = pallet_babe::ParentBlockRandomness<Self>;
             type RandomnessFromOneEpochAgo = pallet_babe::RandomnessFromOneEpochAgo<Self>;
             type RequestPrice = frame_support::traits::ConstU64<2_000>;
@@ -422,19 +400,12 @@ macro_rules! pallets_config {
 
         // UNIVERSAL DIVIDEND //
 
-        pub struct MembersCount;
-        impl frame_support::pallet_prelude::Get<Balance> for MembersCount {
-            fn get() -> Balance {
-                <Membership as sp_membership::traits::MembersCount>::members_count() as Balance
-            }
-        }
-
         impl pallet_universal_dividend::Config for Runtime {
             type Currency = Balances;
             #[cfg(feature = "runtime-benchmarks")]
             type IdtyAttr = Identity;
             type MaxPastReeval = frame_support::traits::ConstU32<160>;
-            type MembersCount = MembersCount;
+            type MembersCount = common_runtime::providers::MembersCount<Membership>;
             type MembersStorage = common_runtime::providers::UdMembersStorage<Runtime>;
             type MomentIntoBalance = sp_runtime::traits::ConvertInto;
             type RuntimeEvent = RuntimeEvent;
@@ -518,7 +489,7 @@ macro_rules! pallets_config {
             type EvaluationPrice = frame_support::traits::ConstU64<1000>;
             type MaxRefereeDistance = MaxRefereeDistance;
             type MinAccessibleReferees = MinAccessibleReferees;
-            type OnUnbalanced = HandleFees;
+            type OnUnbalanced = HandleFees<TreasuryAccount, Balances>;
             type OnValidDistanceStatus = Wot;
             type RuntimeEvent = RuntimeEvent;
             type RuntimeHoldReason = RuntimeHoldReason;
diff --git a/runtime/common/src/providers.rs b/runtime/common/src/providers.rs
index 829be1a07..015043f01 100644
--- a/runtime/common/src/providers.rs
+++ b/runtime/common/src/providers.rs
@@ -14,35 +14,36 @@
 // You should have received a copy of the GNU Affero General Public License
 // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
 
-use crate::{entities::IdtyData, AccountId, IdtyIndex};
+use crate::{entities::IdtyData, AccountId, Balance, IdtyIndex};
 use core::marker::PhantomData;
 use pallet_universal_dividend::FirstEligibleUd;
 
+/// A provider for converting IdtyIndex to associated AccountId.
 pub struct IdentityAccountIdProvider<Runtime>(PhantomData<Runtime>);
-
-impl<
-        Runtime: frame_system::Config<AccountId = AccountId>
-            + pallet_identity::Config<IdtyIndex = IdtyIndex>,
-    > sp_runtime::traits::Convert<IdtyIndex, Option<AccountId>>
+impl<Runtime> sp_runtime::traits::Convert<IdtyIndex, Option<AccountId>>
     for IdentityAccountIdProvider<Runtime>
+where
+    Runtime: frame_system::Config<AccountId = AccountId>
+        + pallet_identity::Config<IdtyIndex = IdtyIndex>,
 {
     fn convert(idty_index: IdtyIndex) -> Option<AccountId> {
         pallet_identity::Pallet::<Runtime>::identity(idty_index).map(|idty| idty.owner_key)
     }
 }
 
+/// A provider for converting AccountId to their associated IdtyIndex.
 pub struct IdentityIndexOf<T: pallet_identity::Config>(PhantomData<T>);
-
-impl<T: pallet_identity::Config> sp_runtime::traits::Convert<T::AccountId, Option<T::IdtyIndex>>
-    for IdentityIndexOf<T>
+impl<T> sp_runtime::traits::Convert<T::AccountId, Option<T::IdtyIndex>> for IdentityIndexOf<T>
+where
+    T: pallet_identity::Config,
 {
     fn convert(account_id: T::AccountId) -> Option<T::IdtyIndex> {
         pallet_identity::Pallet::<T>::identity_index_of(account_id)
     }
 }
 
+/// A provider associating an AccountId to their first eligible UD creation time.
 pub struct UdMembersStorage<T: pallet_identity::Config>(PhantomData<T>);
-
 impl<T> frame_support::traits::StoredMap<AccountId, FirstEligibleUd> for UdMembersStorage<T>
 where
     T: frame_system::Config<AccountId = AccountId>,
@@ -71,12 +72,12 @@ where
     }
 }
 
+/// A provider to WoT membership status based on an IdtyIndex.
 pub struct IsWoTMemberProvider<T>(PhantomData<T>);
-impl<T: pallet_smith_members::Config>
-    sp_runtime::traits::IsMember<<T as pallet_membership::Config>::IdtyId>
+impl<T> sp_runtime::traits::IsMember<<T as pallet_membership::Config>::IdtyId>
     for IsWoTMemberProvider<T>
 where
-    T: pallet_distance::Config + pallet_membership::Config,
+    T: pallet_distance::Config + pallet_membership::Config + pallet_smith_members::Config,
 {
     fn is_member(idty_id: &T::IdtyId) -> bool {
         pallet_membership::Pallet::<T>::is_member(idty_id)
@@ -116,3 +117,14 @@ macro_rules! impl_benchmark_setup_handler {
 
 #[cfg(feature = "runtime-benchmarks")]
 impl_benchmark_setup_handler!(pallet_membership::SetupBenchmark<<T as pallet_identity::Config>::IdtyIndex, T::AccountId>);
+
+/// A provider for retrieving the number of accounts allowed to create the universal dividend.
+pub struct MembersCount<T>(PhantomData<T>);
+impl<T> frame_support::pallet_prelude::Get<Balance> for MembersCount<T>
+where
+    T: sp_membership::traits::MembersCount,
+{
+    fn get() -> Balance {
+        T::members_count() as Balance
+    }
+}
diff --git a/runtime/g1/src/lib.rs b/runtime/g1/src/lib.rs
index c2b192a24..8dccda2f1 100644
--- a/runtime/g1/src/lib.rs
+++ b/runtime/g1/src/lib.rs
@@ -35,10 +35,7 @@ pub use common_runtime::{
     constants::*, entities::*, handlers::*, AccountId, Address, Balance, BlockNumber,
     FullIdentificationOfImpl, GetCurrentEpochIndex, Hash, Header, IdtyIndex, Index, Signature,
 };
-use frame_support::{
-    traits::{fungible::Balanced, Contains, Imbalance},
-    PalletId,
-};
+use frame_support::{traits::Contains, PalletId};
 pub use frame_system::Call as SystemCall;
 use frame_system::EnsureRoot;
 pub use pallet_balances::Call as BalancesCall;
diff --git a/runtime/gdev/src/lib.rs b/runtime/gdev/src/lib.rs
index a2b0ec5d8..cecb06be5 100644
--- a/runtime/gdev/src/lib.rs
+++ b/runtime/gdev/src/lib.rs
@@ -35,10 +35,7 @@ pub use common_runtime::{
     constants::*, entities::*, handlers::*, AccountId, Address, Balance, BlockNumber,
     FullIdentificationOfImpl, GetCurrentEpochIndex, Hash, Header, IdtyIndex, Index, Signature,
 };
-use frame_support::{
-    traits::{fungible::Balanced, Contains, Imbalance},
-    PalletId,
-};
+use frame_support::{traits::Contains, PalletId};
 pub use frame_system::Call as SystemCall;
 use frame_system::EnsureRoot;
 pub use pallet_balances::Call as BalancesCall;
diff --git a/runtime/gtest/src/lib.rs b/runtime/gtest/src/lib.rs
index 6be12db81..842fc6a38 100644
--- a/runtime/gtest/src/lib.rs
+++ b/runtime/gtest/src/lib.rs
@@ -35,10 +35,7 @@ pub use common_runtime::{
     constants::*, entities::*, handlers::*, AccountId, Address, Balance, BlockNumber,
     FullIdentificationOfImpl, GetCurrentEpochIndex, Hash, Header, IdtyIndex, Index, Signature,
 };
-use frame_support::{
-    traits::{fungible::Balanced, Contains, Imbalance},
-    PalletId,
-};
+use frame_support::{traits::Contains, PalletId};
 pub use frame_system::Call as SystemCall;
 use frame_system::EnsureRoot;
 pub use pallet_balances::Call as BalancesCall;
-- 
GitLab