From 0b770609868f781adc7a3476560e67253f37f39a Mon Sep 17 00:00:00 2001
From: Leszek Wiesner <leszek@jsgenesis.com>
Date: Sun, 9 Oct 2022 11:22:43 +0200
Subject: [PATCH] Vesting pallet - make WithdrawReasons configurable (#12109)

* Vesting pallet - make WithdrawReasons configurable

* Update `pallet-vesting` README

Co-authored-by: parity-processbot <>
---
 substrate/bin/node/runtime/src/lib.rs |  5 ++++-
 substrate/frame/vesting/README.md     |  3 ++-
 substrate/frame/vesting/src/lib.rs    | 13 ++++++++++---
 substrate/frame/vesting/src/mock.rs   |  5 ++++-
 4 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index 34f6988c316..14217362103 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -34,7 +34,7 @@ use frame_support::{
 	traits::{
 		AsEnsureOriginWithArg, ConstU128, ConstU16, ConstU32, Currency, EitherOfDiverse,
 		EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem,
-		LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote,
+		LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote, WithdrawReasons,
 	},
 	weights::{
 		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
@@ -1374,6 +1374,8 @@ impl pallet_society::Config for Runtime {
 
 parameter_types! {
 	pub const MinVestedTransfer: Balance = 100 * DOLLARS;
+	pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons =
+		WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE);
 }
 
 impl pallet_vesting::Config for Runtime {
@@ -1382,6 +1384,7 @@ impl pallet_vesting::Config for Runtime {
 	type BlockNumberToBalance = ConvertInto;
 	type MinVestedTransfer = MinVestedTransfer;
 	type WeightInfo = pallet_vesting::weights::SubstrateWeight<Runtime>;
+	type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
 	// `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the
 	// highest number of schedules that encodes less than 2^10.
 	const MAX_VESTING_SCHEDULES: u32 = 28;
diff --git a/substrate/frame/vesting/README.md b/substrate/frame/vesting/README.md
index c3800eb994d..b19a60c5b68 100644
--- a/substrate/frame/vesting/README.md
+++ b/substrate/frame/vesting/README.md
@@ -7,7 +7,8 @@
 
 A simple module providing a means of placing a linear curve on an account's locked balance. This
 module ensures that there is a lock in place preventing the balance to drop below the *unvested*
-amount for any reason other than transaction fee payment.
+amount for reason other than the ones specified in `UnvestedFundsAllowedWithdrawReasons`
+configuration value.
 
 As the amount vested increases over time, the amount unvested reduces. However, locks remain in
 place and explicit action is needed on behalf of the user to ensure that the amount locked is
diff --git a/substrate/frame/vesting/src/lib.rs b/substrate/frame/vesting/src/lib.rs
index 1ca8d41f9a4..a92f94baf6c 100644
--- a/substrate/frame/vesting/src/lib.rs
+++ b/substrate/frame/vesting/src/lib.rs
@@ -24,7 +24,8 @@
 //!
 //! A simple pallet providing a means of placing a linear curve on an account's locked balance. This
 //! pallet ensures that there is a lock in place preventing the balance to drop below the *unvested*
-//! amount for any reason other than transaction fee payment.
+//! amount for any reason other than the ones specified in `UnvestedFundsAllowedWithdrawReasons`
+//! configuration value.
 //!
 //! As the amount vested increases over time, the amount unvested reduces. However, locks remain in
 //! place and explicit action is needed on behalf of the user to ensure that the amount locked is
@@ -170,6 +171,10 @@ pub mod pallet {
 		/// Weight information for extrinsics in this pallet.
 		type WeightInfo: WeightInfo;
 
+		/// Reasons that determine under which conditions the balance may drop below
+		/// the unvested amount.
+		type UnvestedFundsAllowedWithdrawReasons: Get<WithdrawReasons>;
+
 		/// Maximum number of vesting schedules an account may have at a given moment.
 		const MAX_VESTING_SCHEDULES: u32;
 	}
@@ -249,7 +254,9 @@ pub mod pallet {
 				Vesting::<T>::try_append(who, vesting_info)
 					.expect("Too many vesting schedules at genesis.");
 
-				let reasons = WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE;
+				let reasons =
+					WithdrawReasons::except(T::UnvestedFundsAllowedWithdrawReasons::get());
+
 				T::Currency::set_lock(VESTING_ID, who, locked, reasons);
 			}
 		}
@@ -569,7 +576,7 @@ impl<T: Config> Pallet<T> {
 			T::Currency::remove_lock(VESTING_ID, who);
 			Self::deposit_event(Event::<T>::VestingCompleted { account: who.clone() });
 		} else {
-			let reasons = WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE;
+			let reasons = WithdrawReasons::except(T::UnvestedFundsAllowedWithdrawReasons::get());
 			T::Currency::set_lock(VESTING_ID, who, total_locked_now, reasons);
 			Self::deposit_event(Event::<T>::VestingUpdated {
 				account: who.clone(),
diff --git a/substrate/frame/vesting/src/mock.rs b/substrate/frame/vesting/src/mock.rs
index c4e520b37c8..0bd371a0353 100644
--- a/substrate/frame/vesting/src/mock.rs
+++ b/substrate/frame/vesting/src/mock.rs
@@ -17,7 +17,7 @@
 
 use frame_support::{
 	parameter_types,
-	traits::{ConstU32, ConstU64, GenesisBuild},
+	traits::{ConstU32, ConstU64, GenesisBuild, WithdrawReasons},
 };
 use sp_core::H256;
 use sp_runtime::{
@@ -87,6 +87,8 @@ impl pallet_balances::Config for Test {
 }
 parameter_types! {
 	pub const MinVestedTransfer: u64 = 256 * 2;
+	pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons =
+		WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE);
 	pub static ExistentialDeposit: u64 = 0;
 }
 impl Config for Test {
@@ -96,6 +98,7 @@ impl Config for Test {
 	const MAX_VESTING_SCHEDULES: u32 = 3;
 	type MinVestedTransfer = MinVestedTransfer;
 	type WeightInfo = ();
+	type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
 }
 
 pub struct ExtBuilder {
-- 
GitLab