From 70ef6a6e12ca3c45d9e04f9a59ef745d035255fb Mon Sep 17 00:00:00 2001
From: Shawn Tabrizi <shawntabrizi@gmail.com>
Date: Thu, 29 Oct 2020 11:12:39 +0100
Subject: [PATCH] Update Tips to go 100% to Author (#1836)

* 100% of tip goes to Author

* refactor dealwithfees into common

* add fee and tip test

* fix
---
 polkadot/runtime/common/Cargo.toml   |   1 +
 polkadot/runtime/common/src/impls.rs | 183 ++++++++++++++++++++++++++-
 polkadot/runtime/kusama/src/lib.rs   |  18 +--
 polkadot/runtime/polkadot/src/lib.rs |  16 +--
 4 files changed, 192 insertions(+), 26 deletions(-)

diff --git a/polkadot/runtime/common/Cargo.toml b/polkadot/runtime/common/Cargo.toml
index cfdf76ee884..b3ac78e9040 100644
--- a/polkadot/runtime/common/Cargo.toml
+++ b/polkadot/runtime/common/Cargo.toml
@@ -32,6 +32,7 @@ pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "
 pallet-vesting = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
 pallet-offences = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
 pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
+pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
 frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true }
 
 primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false }
diff --git a/polkadot/runtime/common/src/impls.rs b/polkadot/runtime/common/src/impls.rs
index f371972ccae..72d4f6ce895 100644
--- a/polkadot/runtime/common/src/impls.rs
+++ b/polkadot/runtime/common/src/impls.rs
@@ -21,7 +21,6 @@ use crate::NegativeImbalance;
 
 /// Logic for the author to get a portion of fees.
 pub struct ToAuthor<R>(sp_std::marker::PhantomData<R>);
-
 impl<R> OnUnbalanced<NegativeImbalance<R>> for ToAuthor<R>
 where
 	R: pallet_balances::Trait + pallet_authorship::Trait,
@@ -40,3 +39,185 @@ where
 		<frame_system::Module<R>>::deposit_event(pallet_balances::RawEvent::Deposit(author, numeric_amount));
 	}
 }
+
+pub struct DealWithFees<R>(sp_std::marker::PhantomData<R>);
+impl<R> OnUnbalanced<NegativeImbalance<R>> for DealWithFees<R>
+where
+	R: pallet_balances::Trait + pallet_treasury::Trait + pallet_authorship::Trait,
+	pallet_treasury::Module<R>: OnUnbalanced<NegativeImbalance<R>>,
+	<R as frame_system::Trait>::AccountId: From<primitives::v1::AccountId>,
+	<R as frame_system::Trait>::AccountId: Into<primitives::v1::AccountId>,
+	<R as frame_system::Trait>::Event: From<pallet_balances::RawEvent<
+		<R as frame_system::Trait>::AccountId,
+		<R as pallet_balances::Trait>::Balance,
+		pallet_balances::DefaultInstance>
+	>,
+{
+	fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item=NegativeImbalance<R>>) {
+		if let Some(fees) = fees_then_tips.next() {
+			// for fees, 80% to treasury, 20% to author
+			let mut split = fees.ration(80, 20);
+			if let Some(tips) = fees_then_tips.next() {
+				// for tips, if any, 100% to author
+				tips.merge_into(&mut split.1);
+			}
+			use pallet_treasury::Module as Treasury;
+			<Treasury<R> as OnUnbalanced<_>>::on_unbalanced(split.0);
+			<ToAuthor<R> as OnUnbalanced<_>>::on_unbalanced(split.1);
+		}
+	}
+}
+
+
+#[cfg(test)]
+mod tests {
+	use super::*;
+	use frame_support::{impl_outer_origin, parameter_types, weights::Weight};
+	use frame_support::traits::FindAuthor;
+	use sp_core::H256;
+	use sp_runtime::{
+		testing::Header, ModuleId,
+		traits::{BlakeTwo256, IdentityLookup},
+		Perbill,
+	};
+	use primitives::v1::AccountId;
+
+	#[derive(Clone, PartialEq, Eq, Debug)]
+	pub struct Test;
+
+	impl_outer_origin!{
+		pub enum Origin for Test {}
+	}
+
+	parameter_types! {
+		pub const BlockHashCount: u64 = 250;
+		pub const ExtrinsicBaseWeight: u64 = 100;
+		pub const MaximumBlockWeight: Weight = 1024;
+		pub const MaximumBlockLength: u32 = 2 * 1024;
+		pub const AvailableBlockRatio: Perbill = Perbill::one();
+	}
+
+	impl frame_system::Trait for Test {
+		type BaseCallFilter = ();
+		type Origin = Origin;
+		type Index = u64;
+		type BlockNumber = u64;
+		type Call = ();
+		type Hash = H256;
+		type Hashing = BlakeTwo256;
+		type AccountId = AccountId;
+		type Lookup = IdentityLookup<Self::AccountId>;
+		type Header = Header;
+		type Event = ();
+		type BlockHashCount = BlockHashCount;
+		type MaximumBlockWeight = MaximumBlockWeight;
+		type DbWeight = ();
+		type BlockExecutionWeight = ();
+		type ExtrinsicBaseWeight = ExtrinsicBaseWeight;
+		type MaximumExtrinsicWeight = MaximumBlockWeight;
+		type MaximumBlockLength = MaximumBlockLength;
+		type AvailableBlockRatio = AvailableBlockRatio;
+		type Version = ();
+		type PalletInfo = ();
+		type AccountData = pallet_balances::AccountData<u64>;
+		type OnNewAccount = ();
+		type OnKilledAccount = ();
+		type SystemWeightInfo = ();
+	}
+
+	impl pallet_balances::Trait for Test {
+		type Balance = u64;
+		type Event = ();
+		type DustRemoval = ();
+		type ExistentialDeposit = ();
+		type AccountStore = System;
+		type MaxLocks = ();
+		type WeightInfo = ();
+	}
+
+	pub struct Nobody;
+	impl frame_support::traits::Contains<AccountId> for Nobody {
+		fn contains(_: &AccountId) -> bool { false }
+		fn sorted_members() -> Vec<AccountId> { vec![] }
+		#[cfg(feature = "runtime-benchmarks")]
+		fn add(_: &AccountId) { unimplemented!() }
+	}
+	impl frame_support::traits::ContainsLengthBound for Nobody {
+		fn min_len() -> usize { 0 }
+		fn max_len() -> usize { 0 }
+	}
+
+	parameter_types! {
+		pub const TreasuryModuleId: ModuleId = ModuleId(*b"py/trsry");
+	}
+
+	impl pallet_treasury::Trait for Test {
+		type Currency = pallet_balances::Module<Test>;
+		type ApproveOrigin = frame_system::EnsureRoot<AccountId>;
+		type RejectOrigin = frame_system::EnsureRoot<AccountId>;
+		type Event = ();
+		type OnSlash = ();
+		type ProposalBond = ();
+		type ProposalBondMinimum = ();
+		type SpendPeriod = ();
+		type Burn = ();
+		type BurnDestination = ();
+		type Tippers = Nobody;
+		type TipCountdown = ();
+		type TipFindersFee = ();
+		type TipReportDepositBase = ();
+		type DataDepositPerByte = ();
+		type BountyDepositBase = ();
+		type BountyDepositPayoutDelay = ();
+		type BountyUpdatePeriod = ();
+		type MaximumReasonLength = ();
+		type BountyCuratorDeposit = ();
+		type BountyValueMinimum = ();
+		type ModuleId = TreasuryModuleId;
+		type WeightInfo = ();
+	}
+
+	pub struct OneAuthor;
+	impl FindAuthor<AccountId> for OneAuthor {
+		fn find_author<'a, I>(_: I) -> Option<AccountId>
+			where I: 'a,
+		{
+			Some(Default::default())
+		}
+	}
+	impl pallet_authorship::Trait for Test {
+		type FindAuthor = OneAuthor;
+		type UncleGenerations = ();
+		type FilterUncle = ();
+		type EventHandler = ();
+	}
+
+	type Treasury = pallet_treasury::Module<Test>;
+	type Balances = pallet_balances::Module<Test>;
+	type System = frame_system::Module<Test>;
+
+	pub fn new_test_ext() -> sp_io::TestExternalities {
+		let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
+		// We use default for brevity, but you can configure as desired if needed.
+		pallet_balances::GenesisConfig::<Test>::default().assimilate_storage(&mut t).unwrap();
+		t.into()
+	}
+
+	#[test]
+	fn test_fees_and_tip_split() {
+		new_test_ext().execute_with(|| {
+			let fee = Balances::issue(10);
+			let tip = Balances::issue(20);
+
+			assert_eq!(Balances::free_balance(Treasury::account_id()), 0);
+			assert_eq!(Balances::free_balance(AccountId::default()), 0);
+
+			DealWithFees::on_unbalanceds(vec![fee, tip].into_iter());
+
+			// Author gets 100% of tip and 20% of fee = 22
+			assert_eq!(Balances::free_balance(AccountId::default()), 22);
+			// Treasury gets 80% of fee
+			assert_eq!(Balances::free_balance(Treasury::account_id()), 8);
+		});
+	}
+}
diff --git a/polkadot/runtime/kusama/src/lib.rs b/polkadot/runtime/kusama/src/lib.rs
index 54ae7a16250..aac964802cc 100644
--- a/polkadot/runtime/kusama/src/lib.rs
+++ b/polkadot/runtime/kusama/src/lib.rs
@@ -21,7 +21,7 @@
 #![recursion_limit = "256"]
 
 use sp_std::prelude::*;
-use sp_core::u32_trait::{_1, _2, _3, _4, _5};
+use sp_core::u32_trait::{_1, _2, _3, _5};
 use codec::{Encode, Decode};
 use primitives::v1::{
 	AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CommittedCandidateReceipt,
@@ -30,8 +30,8 @@ use primitives::v1::{
 };
 use runtime_common::{
 	claims, SlowAdjustingFeeUpdate, CurrencyToVote,
-	impls::ToAuthor,
-	NegativeImbalance, BlockHashCount, MaximumBlockWeight, AvailableBlockRatio,
+	impls::DealWithFees,
+	BlockHashCount, MaximumBlockWeight, AvailableBlockRatio,
 	MaximumBlockLength, BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight,
 	MaximumExtrinsicWeight, ParachainSessionKeyPlaceholder,
 };
@@ -55,7 +55,7 @@ use sp_core::OpaqueMetadata;
 use sp_staking::SessionIndex;
 use frame_support::{
 	parameter_types, construct_runtime, debug, RuntimeDebug,
-	traits::{KeyOwnerProofSystem, SplitTwoWays, Randomness, LockIdentifier, Filter, InstanceFilter},
+	traits::{KeyOwnerProofSystem, Randomness, LockIdentifier, Filter, InstanceFilter},
 	weights::Weight,
 };
 use frame_system::{EnsureRoot, EnsureOneOf};
@@ -214,14 +214,6 @@ parameter_types! {
 	pub const MaxLocks: u32 = 50;
 }
 
-/// Splits fees 80/20 between treasury and block author.
-pub type DealWithFees = SplitTwoWays<
-	Balance,
-	NegativeImbalance<Runtime>,
-	_4, Treasury,   // 4 parts (80%) goes to the treasury.
-	_1, ToAuthor<Runtime>,   // 1 part (20%) goes to the block author.
->;
-
 impl pallet_balances::Trait for Runtime {
 	type Balance = Balance;
 	type DustRemoval = ();
@@ -238,7 +230,7 @@ parameter_types! {
 
 impl pallet_transaction_payment::Trait for Runtime {
 	type Currency = Balances;
-	type OnTransactionPayment = DealWithFees;
+	type OnTransactionPayment = DealWithFees<Self>;
 	type TransactionByteFee = TransactionByteFee;
 	type WeightToFee = WeightToFee;
 	type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
diff --git a/polkadot/runtime/polkadot/src/lib.rs b/polkadot/runtime/polkadot/src/lib.rs
index e2e0b1780ec..b14771b8e77 100644
--- a/polkadot/runtime/polkadot/src/lib.rs
+++ b/polkadot/runtime/polkadot/src/lib.rs
@@ -22,8 +22,8 @@
 
 use runtime_common::{
 	claims, SlowAdjustingFeeUpdate, CurrencyToVote,
-	impls::ToAuthor,
-	NegativeImbalance, BlockHashCount, MaximumBlockWeight, AvailableBlockRatio,
+	impls::DealWithFees,
+	BlockHashCount, MaximumBlockWeight, AvailableBlockRatio,
 	MaximumBlockLength, BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight,
 	MaximumExtrinsicWeight, ParachainSessionKeyPlaceholder,
 };
@@ -55,7 +55,7 @@ use sp_core::OpaqueMetadata;
 use sp_staking::SessionIndex;
 use frame_support::{
 	parameter_types, construct_runtime, debug, RuntimeDebug,
-	traits::{KeyOwnerProofSystem, SplitTwoWays, Randomness, LockIdentifier, Filter},
+	traits::{KeyOwnerProofSystem, Randomness, LockIdentifier, Filter},
 	weights::Weight,
 };
 use frame_system::{EnsureRoot, EnsureOneOf};
@@ -227,14 +227,6 @@ parameter_types! {
 	pub const MaxLocks: u32 = 50;
 }
 
-/// Splits fees 80/20 between treasury and block author.
-pub type DealWithFees = SplitTwoWays<
-	Balance,
-	NegativeImbalance<Runtime>,
-	_4, Treasury,   		// 4 parts (80%) goes to the treasury.
-	_1, ToAuthor<Runtime>,   	// 1 part (20%) goes to the block author.
->;
-
 impl pallet_balances::Trait for Runtime {
 	type Balance = Balance;
 	type DustRemoval = ();
@@ -251,7 +243,7 @@ parameter_types! {
 
 impl pallet_transaction_payment::Trait for Runtime {
 	type Currency = Balances;
-	type OnTransactionPayment = DealWithFees;
+	type OnTransactionPayment = DealWithFees<Runtime>;
 	type TransactionByteFee = TransactionByteFee;
 	type WeightToFee = WeightToFee;
 	type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
-- 
GitLab