Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
use fungibles traits for treasury, tips and bounties pallets
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyalaribe committed Mar 6, 2023
1 parent 354aa13 commit 42789a2
Show file tree
Hide file tree
Showing 11 changed files with 400 additions and 238 deletions.
4 changes: 4 additions & 0 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,8 @@ parameter_types! {
pub enum HoldReason {
/// The NIS Pallet has reserved it for a non-fungible receipt.
Nis,
// The Treasury Pallet has reserved it for a treasury spend proposal.
Treasury,
}

impl pallet_balances::Config for Runtime {
Expand Down Expand Up @@ -1105,6 +1107,7 @@ parameter_types! {
pub const MaximumReasonLength: u32 = 300;
pub const MaxApprovals: u32 = 100;
pub const MaxBalance: Balance = Balance::max_value();
pub const TreasuryHoldReason: HoldReason = HoldReason::Treasury;
}

impl pallet_treasury::Config for Runtime {
Expand All @@ -1118,6 +1121,7 @@ impl pallet_treasury::Config for Runtime {
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionMoreThan<AccountId, CouncilCollective, 1, 2>,
>;
type HoldReason = TreasuryHoldReason;
type RuntimeEvent = RuntimeEvent;
type OnSlash = ();
type ProposalBond = ProposalBond;
Expand Down
93 changes: 64 additions & 29 deletions frame/bounties/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ pub mod weights;
use sp_std::prelude::*;

use frame_support::traits::{
Currency, ExistenceRequirement::AllowDeath, Get, Imbalance, OnUnbalanced, ReservableCurrency,
fungible::*,
tokens::{Precision, Preservation},
Get, Imbalance,
};

use sp_runtime::{
Expand All @@ -108,8 +110,7 @@ pub use weights::WeightInfo;
pub use pallet::*;

type BalanceOf<T, I = ()> = pallet_treasury::BalanceOf<T, I>;

type PositiveImbalanceOf<T, I = ()> = pallet_treasury::PositiveImbalanceOf<T, I>;
type DebtOf<T, I = ()> = pallet_treasury::DebtOf<T, I>;

/// An index of a bounty. Just a `u32`.
pub type BountyIndex = u32;
Expand Down Expand Up @@ -446,8 +447,9 @@ pub mod pallet {

let slash_curator = |curator: &T::AccountId,
curator_deposit: &mut BalanceOf<T, I>| {
let imbalance = T::Currency::slash_reserved(curator, *curator_deposit).0;
T::OnSlash::on_unbalanced(imbalance);
let imbalance =
T::Currency::slash(&T::HoldReason::get(), curator, *curator_deposit).0;
T::OnSlash::handle(imbalance);
*curator_deposit = Zero::zero();
};

Expand Down Expand Up @@ -484,9 +486,13 @@ pub mod pallet {
} else {
// Else this is the curator, willingly giving up their role.
// Give back their deposit.
let err_amount =
T::Currency::unreserve(curator, bounty.curator_deposit);
debug_assert!(err_amount.is_zero());
let err_amount = T::Currency::release(
&T::HoldReason::get(),
curator,
bounty.curator_deposit,
Precision::Exact,
);
debug_assert!(err_amount.is_ok());
bounty.curator_deposit = Zero::zero();
// Continue to change bounty status below...
}
Expand Down Expand Up @@ -532,7 +538,7 @@ pub mod pallet {
ensure!(signer == *curator, Error::<T, I>::RequireCurator);

let deposit = Self::calculate_curator_deposit(&bounty.fee);
T::Currency::reserve(curator, deposit)?;
T::Currency::hold(&T::HoldReason::get(), curator, deposit)?;
bounty.curator_deposit = deposit;

let update_due = frame_system::Pallet::<T>::block_number() +
Expand Down Expand Up @@ -623,23 +629,36 @@ pub mod pallet {
Error::<T, I>::Premature
);
let bounty_account = Self::bounty_account_id(bounty_id);
let balance = T::Currency::free_balance(&bounty_account);
let balance = T::Currency::balance(&bounty_account);
let fee = bounty.fee.min(balance); // just to be safe
let payout = balance.saturating_sub(fee);
let err_amount = T::Currency::unreserve(&curator, bounty.curator_deposit);
debug_assert!(err_amount.is_zero());
let err_amount = T::Currency::release(
&T::HoldReason::get(),
&curator,
bounty.curator_deposit,
Precision::Exact,
);
debug_assert!(err_amount.is_ok());

// Get total child bounties curator fees, and subtract it from the parent
// curator fee (the fee in present referenced bounty, `self`).
let children_fee = T::ChildBountyManager::children_curator_fees(bounty_id);
debug_assert!(children_fee <= fee);

let final_fee = fee.saturating_sub(children_fee);
let res =
T::Currency::transfer(&bounty_account, &curator, final_fee, AllowDeath); // should not fail
let res = T::Currency::transfer(
&bounty_account,
&curator,
final_fee,
Preservation::Expendable,
); // should not fail
debug_assert!(res.is_ok());
let res =
T::Currency::transfer(&bounty_account, &beneficiary, payout, AllowDeath); // should not fail
let res = T::Currency::transfer(
&bounty_account,
&beneficiary,
payout,
Preservation::Expendable,
); // should not fail
debug_assert!(res.is_ok());

*maybe_bounty = None;
Expand Down Expand Up @@ -693,8 +712,10 @@ pub mod pallet {
// The reject origin would like to cancel a proposed bounty.
BountyDescriptions::<T, I>::remove(bounty_id);
let value = bounty.bond;
let imbalance = T::Currency::slash_reserved(&bounty.proposer, value).0;
T::OnSlash::on_unbalanced(imbalance);
let credit =
T::Currency::slash(&T::HoldReason::get(), &bounty.proposer, value)
.0;
T::OnSlash::handle(credit);
*maybe_bounty = None;

Self::deposit_event(Event::<T, I>::BountyRejected {
Expand All @@ -716,9 +737,13 @@ pub mod pallet {
},
BountyStatus::Active { curator, .. } => {
// Cancelled by council, refund deposit of the working curator.
let err_amount =
T::Currency::unreserve(curator, bounty.curator_deposit);
debug_assert!(err_amount.is_zero());
let err_amount = T::Currency::release(
&T::HoldReason::get(),
curator,
bounty.curator_deposit,
Precision::Exact,
);
debug_assert!(err_amount.is_ok());
// Then execute removal of the bounty below.
},
BountyStatus::PendingPayout { .. } => {
Expand All @@ -734,12 +759,12 @@ pub mod pallet {

BountyDescriptions::<T, I>::remove(bounty_id);

let balance = T::Currency::free_balance(&bounty_account);
let balance = T::Currency::balance(&bounty_account);
let res = T::Currency::transfer(
&bounty_account,
&Self::account_id(),
balance,
AllowDeath,
Preservation::Expendable,
); // should not fail
debug_assert!(res.is_ok());
*maybe_bounty = None;
Expand Down Expand Up @@ -834,7 +859,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
// reserve deposit for new bounty
let bond = T::BountyDepositBase::get() +
T::DataDepositPerByte::get() * (bounded_description.len() as u32).into();
T::Currency::reserve(&proposer, bond)
T::Currency::hold(&T::HoldReason::get(), &proposer, bond)
.map_err(|_| Error::<T, I>::InsufficientProposersBalance)?;

BountyCount::<T, I>::put(index + 1);
Expand All @@ -860,7 +885,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
impl<T: Config<I>, I: 'static> pallet_treasury::SpendFunds<T, I> for Pallet<T, I> {
fn spend_funds(
budget_remaining: &mut BalanceOf<T, I>,
imbalance: &mut PositiveImbalanceOf<T, I>,
imbalance: &mut DebtOf<T, I>,
total_weight: &mut Weight,
missed_any: &mut bool,
) {
Expand All @@ -876,14 +901,24 @@ impl<T: Config<I>, I: 'static> pallet_treasury::SpendFunds<T, I> for Pallet<T, I
bounty.status = BountyStatus::Funded;

// return their deposit.
let err_amount = T::Currency::unreserve(&bounty.proposer, bounty.bond);
debug_assert!(err_amount.is_zero());
let released_amount = T::Currency::release(
&T::HoldReason::get(),
&bounty.proposer,
bounty.bond,
Precision::Exact,
);
debug_assert!(released_amount.is_ok());

// fund the bounty account
imbalance.subsume(T::Currency::deposit_creating(
let _ = T::Currency::deposit(
&Self::bounty_account_id(index),
bounty.value,
));
Precision::Exact,
)
.and_then(|debt| {
imbalance.subsume(debt);
Ok(())
});

Self::deposit_event(Event::<T, I>::BountyBecameActive { index });
false
Expand Down
Loading

0 comments on commit 42789a2

Please sign in to comment.