Introduce safe types for handling imbalances (#2048)

* Be a little safer with total issuance.

* PairT instead of _Pair

* Remove rev causing upset

* Remove fees stuff.

* Fix build (including tests)

* Update runtime, bump version

* Fix

* Handle gas refunds properly.

* Rename identifier

ala #2025

* Address grumbles

* New not-quite-linear-typing API

* Slimmer API

* More linear-type test fixes

* Fix tests

* Tidy

* Fix some grumbles

* Keep unchecked functions private

* Remove another less-than-safe currency function and ensure that
contracts module can never create cash.

* Address a few grumbles and fix tests
This commit is contained in:
Gav Wood
2019-03-20 14:07:28 +01:00
committed by Robert Habermeier
parent f9e224e7b8
commit dcd77a147c
49 changed files with 1108 additions and 1100 deletions
+24 -5
View File
@@ -22,12 +22,14 @@
use serde_derive::{Serialize, Deserialize};
use rstd::prelude::*;
use srml_support::{StorageValue, StorageMap, decl_module, decl_storage, decl_event, ensure};
use srml_support::traits::{Currency, OnDilution, ArithmeticType};
use srml_support::traits::{Currency, OnDilution, OnUnbalanced, Imbalance};
use runtime_primitives::{Permill, traits::{Zero, EnsureOrigin, StaticLookup}};
use parity_codec::{Encode, Decode};
use system::ensure_signed;
type BalanceOf<T> = <<T as Trait>::Currency as ArithmeticType>::Type;
type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
type PositiveImbalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::PositiveImbalance;
type NegativeImbalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::NegativeImbalance;
/// Our module's configuration trait. All our types and consts go in here. If the
/// module is dependent on specific other modules, then their configuration traits
@@ -36,7 +38,7 @@ type BalanceOf<T> = <<T as Trait>::Currency as ArithmeticType>::Type;
/// `system::Trait` should always be included in our implied traits.
pub trait Trait: system::Trait {
/// The staking balance.
type Currency: ArithmeticType + Currency<Self::AccountId, Balance=<<Self as Trait>::Currency as ArithmeticType>::Type>;
type Currency: Currency<Self::AccountId>;
/// Origin from which approvals must come.
type ApproveOrigin: EnsureOrigin<Self::Origin>;
@@ -46,6 +48,12 @@ pub trait Trait: system::Trait {
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
/// Handler for the unbalanced increase when minting cash from the "Pot".
type MintedForSpending: OnUnbalanced<PositiveImbalanceOf<Self>>;
/// Handler for the unbalanced decrease when slashing for a rejected proposal.
type ProposalRejection: OnUnbalanced<NegativeImbalanceOf<Self>>;
}
type ProposalIndex = u32;
@@ -103,7 +111,8 @@ decl_module! {
let proposal = <Proposals<T>>::take(proposal_id).ok_or("No proposal at that index")?;
let value = proposal.bond;
let _ = T::Currency::slash_reserved(&proposal.proposer, value);
let imbalance = T::Currency::slash_reserved(&proposal.proposer, value).0;
T::ProposalRejection::on_unbalanced(imbalance);
}
/// Approve a proposal. At a later time, the proposal will be allocated to the beneficiary
@@ -202,6 +211,7 @@ impl<T: Trait> Module<T> {
Self::deposit_event(RawEvent::Spending(budget_remaining));
let mut missed_any = false;
let mut imbalance = <PositiveImbalanceOf<T>>::zero();
<Approvals<T>>::mutate(|v| {
v.retain(|&index| {
// Should always be true, but shouldn't panic if false or we're screwed.
@@ -214,7 +224,7 @@ impl<T: Trait> Module<T> {
let _ = T::Currency::unreserve(&p.proposer, p.bond);
// provide the allocation.
T::Currency::increase_free_balance_creating(&p.beneficiary, p.value);
imbalance.subsume(T::Currency::deposit_creating(&p.beneficiary, p.value));
Self::deposit_event(RawEvent::Awarded(index, p.value, p.beneficiary));
false
@@ -228,6 +238,8 @@ impl<T: Trait> Module<T> {
});
});
T::MintedForSpending::on_unbalanced(imbalance);
if !missed_any {
// burn some proportion of the remaining budget if we run a surplus.
let burn = (Self::burn() * budget_remaining).min(budget_remaining);
@@ -288,12 +300,17 @@ mod tests {
type OnNewAccount = ();
type OnFreeBalanceZero = ();
type Event = ();
type TransactionPayment = ();
type TransferPayment = ();
type DustRemoval = ();
}
impl Trait for Test {
type Currency = balances::Module<Test>;
type ApproveOrigin = system::EnsureRoot<u64>;
type RejectOrigin = system::EnsureRoot<u64>;
type Event = ();
type MintedForSpending = ();
type ProposalRejection = ();
}
type Balances = balances::Module<Test>;
type Treasury = Module<Test>;
@@ -302,6 +319,8 @@ mod tests {
let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap().0;
t.extend(balances::GenesisConfig::<Test>{
balances: vec![(0, 100), (1, 99), (2, 1)],
transaction_base_fee: 0,
transaction_byte_fee: 0,
transfer_fee: 0,
creation_fee: 0,
existential_deposit: 0,