mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 20:11:09 +00:00
Refactor the balances module (#4649)
* Initially scoping out of the problem * Remove need for exiry in balance locks. * Remove expiry from locks. * Remove supefluous balance test * Amalgamate pieces of balance module * Split out vesting * Fix tests * Fixes for vesting. * Docs. * Weight docs. * Refactor things in terms of set_balances. * Switch out ED to be free + reserved. * Remove on_free_balance_zero and some docs. * Build fixes * Update frame/vesting/src/lib.rs Co-Authored-By: Xiliang Chen <xlchen1291@gmail.com> * Update frame/vesting/src/lib.rs Co-Authored-By: Xiliang Chen <xlchen1291@gmail.com> * Migration * Remove superfluous code. * Test fixes * Fix some tests * Fix repatriate reserve * Fixes * Add test for migration * Final cleanups * Fix * Indentation. * Undo unneeded referencing * Bump runtime version * Fixes Co-authored-by: Xiliang Chen <xlchen1291@gmail.com>
This commit is contained in:
Generated
+20
@@ -3683,6 +3683,7 @@ version = "2.0.0"
|
||||
dependencies = [
|
||||
"frame-support 2.0.0",
|
||||
"frame-system 2.0.0",
|
||||
"hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pallet-balances 2.0.0",
|
||||
"parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -3690,6 +3691,7 @@ dependencies = [
|
||||
"sp-io 2.0.0",
|
||||
"sp-runtime 2.0.0",
|
||||
"sp-std 2.0.0",
|
||||
"sp-storage 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4125,6 +4127,24 @@ dependencies = [
|
||||
"sp-std 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pallet-vesting"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"enumflags2 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"frame-support 2.0.0",
|
||||
"frame-system 2.0.0",
|
||||
"hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pallet-balances 2.0.0",
|
||||
"parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sp-core 2.0.0",
|
||||
"sp-io 2.0.0",
|
||||
"sp-runtime 2.0.0",
|
||||
"sp-std 2.0.0",
|
||||
"sp-storage 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parity-bytes"
|
||||
version = "0.1.1"
|
||||
|
||||
@@ -99,6 +99,7 @@ members = [
|
||||
"frame/transaction-payment/rpc/runtime-api",
|
||||
"frame/treasury",
|
||||
"frame/utility",
|
||||
"frame/vesting",
|
||||
"primitives/allocator",
|
||||
"primitives/application-crypto",
|
||||
"primitives/application-crypto/test",
|
||||
|
||||
@@ -196,15 +196,12 @@ impl timestamp::Trait for Runtime {
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u128 = 500;
|
||||
pub const TransferFee: u128 = 0;
|
||||
pub const CreationFee: u128 = 0;
|
||||
}
|
||||
|
||||
impl balances::Trait for Runtime {
|
||||
/// The type for recording an account's balance.
|
||||
type Balance = Balance;
|
||||
/// What to do if an account's free balance gets zeroed.
|
||||
type OnFreeBalanceZero = ();
|
||||
/// What to do if an account is fully reaped from the system.
|
||||
type OnReapAccount = System;
|
||||
/// What to do if a new account is created.
|
||||
@@ -214,7 +211,6 @@ impl balances::Trait for Runtime {
|
||||
type DustRemoval = ();
|
||||
type TransferPayment = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,6 @@ fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>,
|
||||
}),
|
||||
balances: Some(BalancesConfig {
|
||||
balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(),
|
||||
vesting: vec![],
|
||||
}),
|
||||
sudo: Some(SudoConfig {
|
||||
key: root_key,
|
||||
|
||||
@@ -237,7 +237,6 @@ pub fn testnet_genesis(
|
||||
.map(|k| (k, ENDOWMENT))
|
||||
.chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
|
||||
.collect(),
|
||||
vesting: vec![],
|
||||
}),
|
||||
pallet_indices: Some(IndicesConfig {
|
||||
ids: endowed_accounts.iter().cloned()
|
||||
|
||||
@@ -35,8 +35,7 @@ use frame_system::{self, EventRecord, Phase};
|
||||
|
||||
use node_runtime::{
|
||||
Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances,
|
||||
System, TransactionPayment, Event,
|
||||
TransferFee, TransactionBaseFee, TransactionByteFee,
|
||||
System, TransactionPayment, Event, TransactionBaseFee, TransactionByteFee, CreationFee,
|
||||
constants::currency::*,
|
||||
};
|
||||
use node_primitives::{Balance, Hash};
|
||||
@@ -62,7 +61,7 @@ fn transfer_fee<E: Encode>(extrinsic: &E, fee_multiplier: Fixed64) -> Balance {
|
||||
::WeightToFee::convert(weight);
|
||||
|
||||
let base_fee = TransactionBaseFee::get();
|
||||
base_fee + fee_multiplier.saturated_multiply_accumulate(length_fee + weight_fee) + TransferFee::get()
|
||||
base_fee + fee_multiplier.saturated_multiply_accumulate(length_fee + weight_fee)
|
||||
}
|
||||
|
||||
fn xt() -> UncheckedExtrinsic {
|
||||
@@ -164,8 +163,8 @@ fn block_with_size(time: u64, nonce: u32, size: usize) -> (Vec<u8>, Hash) {
|
||||
fn panic_execution_with_foreign_code_gives_error() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(BLOATY_CODE, Storage {
|
||||
top: map![
|
||||
<pallet_balances::FreeBalance<Runtime>>::hashed_key_for(alice()) => {
|
||||
69_u128.encode()
|
||||
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
|
||||
(69u128, 0u128, 0u128, 0u128).encode()
|
||||
},
|
||||
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
|
||||
69_u128.encode()
|
||||
@@ -203,8 +202,8 @@ fn panic_execution_with_foreign_code_gives_error() {
|
||||
fn bad_extrinsic_with_native_equivalent_code_gives_error() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, Storage {
|
||||
top: map![
|
||||
<pallet_balances::FreeBalance<Runtime>>::hashed_key_for(alice()) => {
|
||||
69_u128.encode()
|
||||
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
|
||||
(69u128, 0u128, 0u128, 0u128).encode()
|
||||
},
|
||||
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
|
||||
69_u128.encode()
|
||||
@@ -242,8 +241,8 @@ fn bad_extrinsic_with_native_equivalent_code_gives_error() {
|
||||
fn successful_execution_with_native_equivalent_code_gives_ok() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, Storage {
|
||||
top: map![
|
||||
<pallet_balances::FreeBalance<Runtime>>::hashed_key_for(alice()) => {
|
||||
(111 * DOLLARS).encode()
|
||||
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
|
||||
(111 * DOLLARS, 0u128, 0u128, 0u128).encode()
|
||||
},
|
||||
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
|
||||
(111 * DOLLARS).encode()
|
||||
@@ -275,7 +274,8 @@ fn successful_execution_with_native_equivalent_code_gives_ok() {
|
||||
assert!(r.is_ok());
|
||||
|
||||
t.execute_with(|| {
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm));
|
||||
let fees = transfer_fee(&xt(), fm) + CreationFee::get();
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
|
||||
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
|
||||
});
|
||||
}
|
||||
@@ -284,8 +284,8 @@ fn successful_execution_with_native_equivalent_code_gives_ok() {
|
||||
fn successful_execution_with_foreign_code_gives_ok() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(BLOATY_CODE, Storage {
|
||||
top: map![
|
||||
<pallet_balances::FreeBalance<Runtime>>::hashed_key_for(alice()) => {
|
||||
(111 * DOLLARS).encode()
|
||||
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
|
||||
(111 * DOLLARS, 0u128, 0u128, 0u128).encode()
|
||||
},
|
||||
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
|
||||
(111 * DOLLARS).encode()
|
||||
@@ -317,7 +317,8 @@ fn successful_execution_with_foreign_code_gives_ok() {
|
||||
assert!(r.is_ok());
|
||||
|
||||
t.execute_with(|| {
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm));
|
||||
let fees = transfer_fee(&xt(), fm) + CreationFee::get();
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
|
||||
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
|
||||
});
|
||||
}
|
||||
@@ -340,7 +341,8 @@ fn full_native_block_import_works() {
|
||||
).0.unwrap();
|
||||
|
||||
t.execute_with(|| {
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm));
|
||||
let fees = transfer_fee(&xt(), fm);
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
|
||||
assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS);
|
||||
alice_last_known_balance = Balances::total_balance(&alice());
|
||||
let events = vec![
|
||||
@@ -362,7 +364,7 @@ fn full_native_block_import_works() {
|
||||
alice().into(),
|
||||
bob().into(),
|
||||
69 * DOLLARS,
|
||||
1 * CENTS,
|
||||
0,
|
||||
)),
|
||||
topics: vec![],
|
||||
},
|
||||
@@ -416,7 +418,7 @@ fn full_native_block_import_works() {
|
||||
bob().into(),
|
||||
alice().into(),
|
||||
5 * DOLLARS,
|
||||
1 * CENTS,
|
||||
0,
|
||||
)
|
||||
),
|
||||
topics: vec![],
|
||||
@@ -440,7 +442,7 @@ fn full_native_block_import_works() {
|
||||
alice().into(),
|
||||
bob().into(),
|
||||
15 * DOLLARS,
|
||||
1 * CENTS,
|
||||
0,
|
||||
)
|
||||
),
|
||||
topics: vec![],
|
||||
@@ -710,8 +712,8 @@ fn native_big_block_import_fails_on_fallback() {
|
||||
fn panic_execution_gives_error() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(BLOATY_CODE, Storage {
|
||||
top: map![
|
||||
<pallet_balances::FreeBalance<Runtime>>::hashed_key_for(alice()) => {
|
||||
0_u128.encode()
|
||||
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
|
||||
(0_u128, 0_u128, 0_u128, 0_u128).encode()
|
||||
},
|
||||
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
|
||||
0_u128.encode()
|
||||
@@ -745,8 +747,8 @@ fn panic_execution_gives_error() {
|
||||
fn successful_execution_gives_ok() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, Storage {
|
||||
top: map![
|
||||
<pallet_balances::FreeBalance<Runtime>>::hashed_key_for(alice()) => {
|
||||
(111 * DOLLARS).encode()
|
||||
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
|
||||
(111 * DOLLARS, 0u128, 0u128, 0u128).encode()
|
||||
},
|
||||
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
|
||||
(111 * DOLLARS).encode()
|
||||
@@ -779,7 +781,8 @@ fn successful_execution_gives_ok() {
|
||||
.expect("Extrinsic did not fail");
|
||||
|
||||
t.execute_with(|| {
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * transfer_fee(&xt(), fm));
|
||||
let fees = transfer_fee(&xt(), fm) + CreationFee::get();
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
|
||||
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ use sp_runtime::{
|
||||
};
|
||||
use node_runtime::{
|
||||
CheckedExtrinsic, Call, Runtime, Balances,
|
||||
TransactionPayment, TransferFee, TransactionBaseFee, TransactionByteFee,
|
||||
TransactionPayment, TransactionBaseFee, TransactionByteFee,
|
||||
WeightFeeCoefficient, constants::currency::*,
|
||||
};
|
||||
use node_runtime::impls::LinearWeightToFee;
|
||||
@@ -134,14 +134,14 @@ fn transaction_fee_is_correct_ultimate() {
|
||||
// (this baed on assigning 0.1 CENT to the cheapest tx with `weight = 100`)
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, Storage {
|
||||
top: map![
|
||||
<pallet_balances::FreeBalance<Runtime>>::hashed_key_for(alice()) => {
|
||||
(100 * DOLLARS).encode()
|
||||
<pallet_balances::Account<Runtime>>::hashed_key_for(alice()) => {
|
||||
(100 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode()
|
||||
},
|
||||
<pallet_balances::FreeBalance<Runtime>>::hashed_key_for(bob()) => {
|
||||
(10 * DOLLARS).encode()
|
||||
<pallet_balances::Account<Runtime>>::hashed_key_for(bob()) => {
|
||||
(10 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode()
|
||||
},
|
||||
<pallet_balances::TotalIssuance<Runtime>>::hashed_key().to_vec() => {
|
||||
(110 * DOLLARS).encode()
|
||||
(110 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS, 0 * DOLLARS).encode()
|
||||
},
|
||||
<pallet_indices::NextEnumSet<Runtime>>::hashed_key().to_vec() => vec![0u8; 16],
|
||||
<frame_system::BlockHash<Runtime>>::hashed_key_for(0) => vec![0u8; 32]
|
||||
@@ -193,9 +193,7 @@ fn transaction_fee_is_correct_ultimate() {
|
||||
// we know that weight to fee multiplier is effect-less in block 1.
|
||||
assert_eq!(weight_fee as Balance, MILLICENTS);
|
||||
balance_alice -= weight_fee;
|
||||
|
||||
balance_alice -= tip;
|
||||
balance_alice -= TransferFee::get();
|
||||
|
||||
assert_eq!(Balances::total_balance(&alice()), balance_alice);
|
||||
});
|
||||
|
||||
@@ -167,7 +167,8 @@ fn submitted_transaction_should_be_valid() {
|
||||
// add balance to the account
|
||||
let author = extrinsic.signature.clone().unwrap().0;
|
||||
let address = Indices::lookup(author).unwrap();
|
||||
<pallet_balances::FreeBalance<Runtime, _>>::insert(&address, 5_000_000_000_000);
|
||||
let account = pallet_balances::AccountData { free: 5_000_000_000_000, ..Default::default() };
|
||||
<pallet_balances::Account<Runtime, _>>::insert(&address, account);
|
||||
|
||||
// check validity
|
||||
let res = Executive::validate_transaction(extrinsic);
|
||||
|
||||
@@ -167,20 +167,17 @@ impl pallet_indices::Trait for Runtime {
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: Balance = 1 * DOLLARS;
|
||||
pub const TransferFee: Balance = 1 * CENTS;
|
||||
pub const CreationFee: Balance = 1 * CENTS;
|
||||
}
|
||||
|
||||
impl pallet_balances::Trait for Runtime {
|
||||
type Balance = Balance;
|
||||
type OnFreeBalanceZero = ((Staking, Contracts), Session);
|
||||
type OnReapAccount = (System, Recovery);
|
||||
type OnReapAccount = ((((System, Staking), Contracts), Session), Recovery);
|
||||
type OnNewAccount = Indices;
|
||||
type Event = Event;
|
||||
type DustRemoval = ();
|
||||
type TransferPayment = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
|
||||
@@ -430,7 +427,6 @@ impl pallet_contracts::Trait for Runtime {
|
||||
type RentByteFee = RentByteFee;
|
||||
type RentDepositOffset = RentDepositOffset;
|
||||
type SurchargeReward = SurchargeReward;
|
||||
type TransferFee = ContractTransferFee;
|
||||
type CreationFee = ContractCreationFee;
|
||||
type TransactionBaseFee = ContractTransactionBaseFee;
|
||||
type TransactionByteFee = ContractTransactionByteFee;
|
||||
|
||||
@@ -49,7 +49,6 @@ pub fn config(support_changes_trie: bool, code: Option<&[u8]>) -> GenesisConfig
|
||||
(eve(), 101 * DOLLARS),
|
||||
(ferdie(), 100 * DOLLARS),
|
||||
],
|
||||
vesting: vec![],
|
||||
}),
|
||||
pallet_session: Some(SessionConfig {
|
||||
keys: vec![
|
||||
|
||||
@@ -9,6 +9,7 @@ license = "GPL-3.0"
|
||||
serde = { version = "1.0.101", optional = true }
|
||||
codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] }
|
||||
sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" }
|
||||
sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" }
|
||||
sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" }
|
||||
frame-support = { version = "2.0.0", default-features = false, path = "../support" }
|
||||
frame-system = { version = "2.0.0", default-features = false, path = "../system" }
|
||||
@@ -24,7 +25,8 @@ std = [
|
||||
"serde",
|
||||
"codec/std",
|
||||
"sp-std/std",
|
||||
"frame-support/std",
|
||||
"sp-io/std",
|
||||
"sp-runtime/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
]
|
||||
|
||||
+492
-478
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Some utilities for helping access storage with arbitrary key types.
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use codec::{Encode, Decode};
|
||||
use frame_support::{StorageHasher, Twox128};
|
||||
|
||||
pub struct StorageIterator<T> {
|
||||
prefix: [u8; 32],
|
||||
previous_key: Vec<u8>,
|
||||
drain: bool,
|
||||
_phantom: ::sp_std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> StorageIterator<T> {
|
||||
pub fn new(module: &[u8], item: &[u8]) -> Self {
|
||||
let mut prefix = [0u8; 32];
|
||||
prefix[0..16].copy_from_slice(&Twox128::hash(module));
|
||||
prefix[16..32].copy_from_slice(&Twox128::hash(item));
|
||||
Self { prefix, previous_key: prefix[..].to_vec(), drain: false, _phantom: Default::default() }
|
||||
}
|
||||
pub fn drain(mut self) -> Self {
|
||||
self.drain = true;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Decode + Sized> Iterator for StorageIterator<T> {
|
||||
type Item = (Vec<u8>, T);
|
||||
|
||||
fn next(&mut self) -> Option<(Vec<u8>, T)> {
|
||||
loop {
|
||||
let maybe_next = sp_io::storage::next_key(&self.previous_key)
|
||||
.filter(|n| n.starts_with(&self.prefix));
|
||||
break match maybe_next {
|
||||
Some(next) => {
|
||||
self.previous_key = next.clone();
|
||||
let maybe_value = frame_support::storage::unhashed::get::<T>(&next);
|
||||
match maybe_value {
|
||||
Some(value) => {
|
||||
if self.drain {
|
||||
frame_support::storage::unhashed::kill(&next);
|
||||
}
|
||||
Some((self.previous_key[32..].to_vec(), value))
|
||||
}
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_storage_value<T: Decode + Sized>(module: &[u8], item: &[u8], hash: &[u8]) -> Option<T> {
|
||||
let mut key = vec![0u8; 32 + hash.len()];
|
||||
key[0..16].copy_from_slice(&Twox128::hash(module));
|
||||
key[16..32].copy_from_slice(&Twox128::hash(item));
|
||||
key[32..].copy_from_slice(hash);
|
||||
frame_support::storage::unhashed::get::<T>(&key)
|
||||
}
|
||||
|
||||
pub fn put_storage_value<T: Encode>(module: &[u8], item: &[u8], hash: &[u8], value: T) {
|
||||
let mut key = vec![0u8; 32 + hash.len()];
|
||||
key[0..16].copy_from_slice(&Twox128::hash(module));
|
||||
key[16..32].copy_from_slice(&Twox128::hash(item));
|
||||
key[32..].copy_from_slice(hash);
|
||||
frame_support::storage::unhashed::put(&key, &value);
|
||||
}
|
||||
@@ -32,7 +32,6 @@ impl_outer_origin!{
|
||||
|
||||
thread_local! {
|
||||
pub(crate) static EXISTENTIAL_DEPOSIT: RefCell<u64> = RefCell::new(0);
|
||||
static TRANSFER_FEE: RefCell<u64> = RefCell::new(0);
|
||||
static CREATION_FEE: RefCell<u64> = RefCell::new(0);
|
||||
}
|
||||
|
||||
@@ -41,11 +40,6 @@ impl Get<u64> for ExistentialDeposit {
|
||||
fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) }
|
||||
}
|
||||
|
||||
pub struct TransferFee;
|
||||
impl Get<u64> for TransferFee {
|
||||
fn get() -> u64 { TRANSFER_FEE.with(|v| *v.borrow()) }
|
||||
}
|
||||
|
||||
pub struct CreationFee;
|
||||
impl Get<u64> for CreationFee {
|
||||
fn get() -> u64 { CREATION_FEE.with(|v| *v.borrow()) }
|
||||
@@ -92,32 +86,26 @@ impl pallet_transaction_payment::Trait for Test {
|
||||
}
|
||||
impl Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type OnNewAccount = ();
|
||||
type Event = ();
|
||||
type DustRemoval = ();
|
||||
type TransferPayment = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
|
||||
pub struct ExtBuilder {
|
||||
existential_deposit: u64,
|
||||
transfer_fee: u64,
|
||||
creation_fee: u64,
|
||||
monied: bool,
|
||||
vesting: bool,
|
||||
}
|
||||
impl Default for ExtBuilder {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
existential_deposit: 0,
|
||||
transfer_fee: 0,
|
||||
creation_fee: 0,
|
||||
monied: false,
|
||||
vesting: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,11 +114,6 @@ impl ExtBuilder {
|
||||
self.existential_deposit = existential_deposit;
|
||||
self
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn transfer_fee(mut self, transfer_fee: u64) -> Self {
|
||||
self.transfer_fee = transfer_fee;
|
||||
self
|
||||
}
|
||||
pub fn creation_fee(mut self, creation_fee: u64) -> Self {
|
||||
self.creation_fee = creation_fee;
|
||||
self
|
||||
@@ -142,13 +125,8 @@ impl ExtBuilder {
|
||||
}
|
||||
self
|
||||
}
|
||||
pub fn vesting(mut self, vesting: bool) -> Self {
|
||||
self.vesting = vesting;
|
||||
self
|
||||
}
|
||||
pub fn set_associated_consts(&self) {
|
||||
EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit);
|
||||
TRANSFER_FEE.with(|v| *v.borrow_mut() = self.transfer_fee);
|
||||
CREATION_FEE.with(|v| *v.borrow_mut() = self.creation_fee);
|
||||
}
|
||||
pub fn build(self) -> sp_io::TestExternalities {
|
||||
@@ -166,15 +144,6 @@ impl ExtBuilder {
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
vesting: if self.vesting && self.monied {
|
||||
vec![
|
||||
(1, 0, 10, 5 * self.existential_deposit),
|
||||
(2, 10, 20, 0),
|
||||
(12, 10, 20, 5 * self.existential_deposit)
|
||||
]
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
t.into()
|
||||
}
|
||||
@@ -187,5 +156,5 @@ pub const CALL: &<Test as frame_system::Trait>::Call = &();
|
||||
|
||||
/// create a transaction info struct from weight. Handy to avoid building the whole struct.
|
||||
pub fn info_from_weight(w: Weight) -> DispatchInfo {
|
||||
DispatchInfo { weight: w, ..Default::default() }
|
||||
DispatchInfo { weight: w, pays_fee: true, ..Default::default() }
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use super::*;
|
||||
use mock::{Balances, ExtBuilder, Test, System, info_from_weight, CALL};
|
||||
use sp_runtime::traits::{SignedExtension, BadOrigin};
|
||||
use sp_runtime::{Fixed64, traits::{SignedExtension, BadOrigin}};
|
||||
use frame_support::{
|
||||
assert_noop, assert_ok, assert_err,
|
||||
traits::{LockableCurrency, LockIdentifier, WithdrawReason, WithdrawReasons,
|
||||
@@ -29,13 +29,12 @@ use frame_system::RawOrigin;
|
||||
|
||||
const ID_1: LockIdentifier = *b"1 ";
|
||||
const ID_2: LockIdentifier = *b"2 ";
|
||||
const ID_3: LockIdentifier = *b"3 ";
|
||||
|
||||
#[test]
|
||||
fn basic_locking_should_work() {
|
||||
ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| {
|
||||
assert_eq!(Balances::free_balance(&1), 10);
|
||||
Balances::set_lock(ID_1, &1, 9, u64::max_value(), WithdrawReasons::all());
|
||||
assert_eq!(Balances::free_balance(1), 10);
|
||||
Balances::set_lock(ID_1, &1, 9, WithdrawReasons::all());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 5, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
@@ -46,7 +45,7 @@ fn basic_locking_should_work() {
|
||||
#[test]
|
||||
fn partial_locking_should_work() {
|
||||
ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| {
|
||||
Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all());
|
||||
Balances::set_lock(ID_1, &1, 5, WithdrawReasons::all());
|
||||
assert_ok!(<Balances as Currency<_>>::transfer(&1, &2, 1, AllowDeath));
|
||||
});
|
||||
}
|
||||
@@ -54,7 +53,7 @@ fn partial_locking_should_work() {
|
||||
#[test]
|
||||
fn lock_removal_should_work() {
|
||||
ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| {
|
||||
Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all());
|
||||
Balances::set_lock(ID_1, &1, u64::max_value(), WithdrawReasons::all());
|
||||
Balances::remove_lock(ID_1, &1);
|
||||
assert_ok!(<Balances as Currency<_>>::transfer(&1, &2, 1, AllowDeath));
|
||||
});
|
||||
@@ -63,8 +62,8 @@ fn lock_removal_should_work() {
|
||||
#[test]
|
||||
fn lock_replacement_should_work() {
|
||||
ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| {
|
||||
Balances::set_lock(ID_1, &1, u64::max_value(), u64::max_value(), WithdrawReasons::all());
|
||||
Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all());
|
||||
Balances::set_lock(ID_1, &1, u64::max_value(), WithdrawReasons::all());
|
||||
Balances::set_lock(ID_1, &1, 5, WithdrawReasons::all());
|
||||
assert_ok!(<Balances as Currency<_>>::transfer(&1, &2, 1, AllowDeath));
|
||||
});
|
||||
}
|
||||
@@ -72,8 +71,8 @@ fn lock_replacement_should_work() {
|
||||
#[test]
|
||||
fn double_locking_should_work() {
|
||||
ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| {
|
||||
Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all());
|
||||
Balances::set_lock(ID_2, &1, 5, u64::max_value(), WithdrawReasons::all());
|
||||
Balances::set_lock(ID_1, &1, 5, WithdrawReasons::all());
|
||||
Balances::set_lock(ID_2, &1, 5, WithdrawReasons::all());
|
||||
assert_ok!(<Balances as Currency<_>>::transfer(&1, &2, 1, AllowDeath));
|
||||
});
|
||||
}
|
||||
@@ -81,9 +80,8 @@ fn double_locking_should_work() {
|
||||
#[test]
|
||||
fn combination_locking_should_work() {
|
||||
ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| {
|
||||
Balances::set_lock(ID_1, &1, u64::max_value(), 0, WithdrawReasons::none());
|
||||
Balances::set_lock(ID_2, &1, 0, u64::max_value(), WithdrawReasons::none());
|
||||
Balances::set_lock(ID_3, &1, 0, 0, WithdrawReasons::all());
|
||||
Balances::set_lock(ID_1, &1, u64::max_value(), WithdrawReasons::none());
|
||||
Balances::set_lock(ID_2, &1, 0, WithdrawReasons::all());
|
||||
assert_ok!(<Balances as Currency<_>>::transfer(&1, &2, 1, AllowDeath));
|
||||
});
|
||||
}
|
||||
@@ -91,17 +89,17 @@ fn combination_locking_should_work() {
|
||||
#[test]
|
||||
fn lock_value_extension_should_work() {
|
||||
ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| {
|
||||
Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all());
|
||||
Balances::set_lock(ID_1, &1, 5, WithdrawReasons::all());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
);
|
||||
Balances::extend_lock(ID_1, &1, 2, u64::max_value(), WithdrawReasons::all());
|
||||
Balances::extend_lock(ID_1, &1, 2, WithdrawReasons::all());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
);
|
||||
Balances::extend_lock(ID_1, &1, 8, u64::max_value(), WithdrawReasons::all());
|
||||
Balances::extend_lock(ID_1, &1, 8, WithdrawReasons::all());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 3, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
@@ -116,23 +114,12 @@ fn lock_reasons_should_work() {
|
||||
.monied(true)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Transfer.into());
|
||||
pallet_transaction_payment::NextFeeMultiplier::put(Fixed64::from_natural(1));
|
||||
Balances::set_lock(ID_1, &1, 10, WithdrawReason::Reserve.into());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 1, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
);
|
||||
assert_ok!(<Balances as ReservableCurrency<_>>::reserve(&1, 1));
|
||||
// NOTE: this causes a fee payment.
|
||||
assert!(<ChargeTransactionPayment<Test> as SignedExtension>::pre_dispatch(
|
||||
ChargeTransactionPayment::from(1),
|
||||
&1,
|
||||
CALL,
|
||||
info_from_weight(1),
|
||||
0,
|
||||
).is_ok());
|
||||
|
||||
Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Reserve.into());
|
||||
assert_ok!(<Balances as Currency<_>>::transfer(&1, &2, 1, AllowDeath));
|
||||
assert_noop!(
|
||||
<Balances as ReservableCurrency<_>>::reserve(&1, 1),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
@@ -142,10 +129,17 @@ fn lock_reasons_should_work() {
|
||||
&1,
|
||||
CALL,
|
||||
info_from_weight(1),
|
||||
0,
|
||||
1,
|
||||
).is_err());
|
||||
assert!(<ChargeTransactionPayment<Test> as SignedExtension>::pre_dispatch(
|
||||
ChargeTransactionPayment::from(0),
|
||||
&1,
|
||||
CALL,
|
||||
info_from_weight(1),
|
||||
1,
|
||||
).is_ok());
|
||||
|
||||
Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::TransactionPayment.into());
|
||||
Balances::set_lock(ID_1, &1, 10, WithdrawReason::TransactionPayment.into());
|
||||
assert_ok!(<Balances as Currency<_>>::transfer(&1, &2, 1, AllowDeath));
|
||||
assert_ok!(<Balances as ReservableCurrency<_>>::reserve(&1, 1));
|
||||
assert!(<ChargeTransactionPayment<Test> as SignedExtension>::pre_dispatch(
|
||||
@@ -153,40 +147,33 @@ fn lock_reasons_should_work() {
|
||||
&1,
|
||||
CALL,
|
||||
info_from_weight(1),
|
||||
0,
|
||||
1,
|
||||
).is_err());
|
||||
assert!(<ChargeTransactionPayment<Test> as SignedExtension>::pre_dispatch(
|
||||
ChargeTransactionPayment::from(0),
|
||||
&1,
|
||||
CALL,
|
||||
info_from_weight(1),
|
||||
1,
|
||||
).is_err());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lock_block_number_should_work() {
|
||||
ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| {
|
||||
Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 1, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
);
|
||||
|
||||
System::set_block_number(2);
|
||||
assert_ok!(<Balances as Currency<_>>::transfer(&1, &2, 1, AllowDeath));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lock_block_number_extension_should_work() {
|
||||
ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| {
|
||||
Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all());
|
||||
Balances::set_lock(ID_1, &1, 10, WithdrawReasons::all());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
);
|
||||
Balances::extend_lock(ID_1, &1, 10, 1, WithdrawReasons::all());
|
||||
Balances::extend_lock(ID_1, &1, 10, WithdrawReasons::all());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
);
|
||||
System::set_block_number(2);
|
||||
Balances::extend_lock(ID_1, &1, 10, 8, WithdrawReasons::all());
|
||||
Balances::extend_lock(ID_1, &1, 10, WithdrawReasons::all());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 3, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
@@ -197,17 +184,17 @@ fn lock_block_number_extension_should_work() {
|
||||
#[test]
|
||||
fn lock_reasons_extension_should_work() {
|
||||
ExtBuilder::default().existential_deposit(1).monied(true).build().execute_with(|| {
|
||||
Balances::set_lock(ID_1, &1, 10, 10, WithdrawReason::Transfer.into());
|
||||
Balances::set_lock(ID_1, &1, 10, WithdrawReason::Transfer.into());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
);
|
||||
Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReasons::none());
|
||||
Balances::extend_lock(ID_1, &1, 10, WithdrawReasons::none());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
);
|
||||
Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReason::Reserve.into());
|
||||
Balances::extend_lock(ID_1, &1, 10, WithdrawReason::Reserve.into());
|
||||
assert_noop!(
|
||||
<Balances as Currency<_>>::transfer(&1, &2, 6, AllowDeath),
|
||||
Error::<Test, _>::LiquidityRestrictions
|
||||
@@ -230,7 +217,7 @@ fn default_indexing_on_new_accounts_should_not_work2() {
|
||||
Error::<Test, _>::ExistentialDeposit,
|
||||
);
|
||||
assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist
|
||||
assert_eq!(Balances::free_balance(&1), 100);
|
||||
assert_eq!(Balances::free_balance(1), 100);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -247,7 +234,7 @@ fn reserved_balance_should_prevent_reclaim_count() {
|
||||
assert_eq!(Balances::total_balance(&2), 256 * 20);
|
||||
|
||||
assert_ok!(Balances::reserve(&2, 256 * 19 + 1)); // account 2 becomes mostly reserved
|
||||
assert_eq!(Balances::free_balance(&2), 0); // "free" account deleted."
|
||||
assert_eq!(Balances::free_balance(2), 255); // "free" account deleted."
|
||||
assert_eq!(Balances::total_balance(&2), 256 * 20); // reserve still exists.
|
||||
assert_eq!(Balances::is_dead_account(&2), false);
|
||||
assert_eq!(System::account_nonce(&2), 1);
|
||||
@@ -322,11 +309,11 @@ fn dust_account_removal_should_work2() {
|
||||
fn balance_works() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
let _ = Balances::deposit_creating(&1, 42);
|
||||
assert_eq!(Balances::free_balance(&1), 42);
|
||||
assert_eq!(Balances::reserved_balance(&1), 0);
|
||||
assert_eq!(Balances::free_balance(1), 42);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
assert_eq!(Balances::total_balance(&1), 42);
|
||||
assert_eq!(Balances::free_balance(&2), 0);
|
||||
assert_eq!(Balances::reserved_balance(&2), 0);
|
||||
assert_eq!(Balances::free_balance(2), 0);
|
||||
assert_eq!(Balances::reserved_balance(2), 0);
|
||||
assert_eq!(Balances::total_balance(&2), 0);
|
||||
});
|
||||
}
|
||||
@@ -361,14 +348,14 @@ fn reserving_balance_should_work() {
|
||||
let _ = Balances::deposit_creating(&1, 111);
|
||||
|
||||
assert_eq!(Balances::total_balance(&1), 111);
|
||||
assert_eq!(Balances::free_balance(&1), 111);
|
||||
assert_eq!(Balances::reserved_balance(&1), 0);
|
||||
assert_eq!(Balances::free_balance(1), 111);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
|
||||
assert_ok!(Balances::reserve(&1, 69));
|
||||
|
||||
assert_eq!(Balances::total_balance(&1), 111);
|
||||
assert_eq!(Balances::free_balance(&1), 42);
|
||||
assert_eq!(Balances::reserved_balance(&1), 69);
|
||||
assert_eq!(Balances::free_balance(1), 42);
|
||||
assert_eq!(Balances::reserved_balance(1), 69);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -389,7 +376,7 @@ fn deducting_balance_should_work() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
let _ = Balances::deposit_creating(&1, 111);
|
||||
assert_ok!(Balances::reserve(&1, 69));
|
||||
assert_eq!(Balances::free_balance(&1), 42);
|
||||
assert_eq!(Balances::free_balance(1), 42);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -397,10 +384,11 @@ fn deducting_balance_should_work() {
|
||||
fn refunding_balance_should_work() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
let _ = Balances::deposit_creating(&1, 42);
|
||||
Balances::set_reserved_balance(&1, 69);
|
||||
let account = Balances::account(&1);
|
||||
Balances::set_account(&1, &AccountData { reserved: 69, ..account }, &account);
|
||||
Balances::unreserve(&1, 69);
|
||||
assert_eq!(Balances::free_balance(&1), 111);
|
||||
assert_eq!(Balances::reserved_balance(&1), 0);
|
||||
assert_eq!(Balances::free_balance(1), 111);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -410,8 +398,8 @@ fn slashing_balance_should_work() {
|
||||
let _ = Balances::deposit_creating(&1, 111);
|
||||
assert_ok!(Balances::reserve(&1, 69));
|
||||
assert!(Balances::slash(&1, 69).1.is_zero());
|
||||
assert_eq!(Balances::free_balance(&1), 0);
|
||||
assert_eq!(Balances::reserved_balance(&1), 42);
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
assert_eq!(Balances::reserved_balance(1), 42);
|
||||
assert_eq!(<TotalIssuance<Test>>::get(), 42);
|
||||
});
|
||||
}
|
||||
@@ -422,8 +410,8 @@ fn slashing_incomplete_balance_should_work() {
|
||||
let _ = Balances::deposit_creating(&1, 42);
|
||||
assert_ok!(Balances::reserve(&1, 21));
|
||||
assert_eq!(Balances::slash(&1, 69).1, 27);
|
||||
assert_eq!(Balances::free_balance(&1), 0);
|
||||
assert_eq!(Balances::reserved_balance(&1), 0);
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
assert_eq!(<TotalIssuance<Test>>::get(), 0);
|
||||
});
|
||||
}
|
||||
@@ -434,8 +422,8 @@ fn unreserving_balance_should_work() {
|
||||
let _ = Balances::deposit_creating(&1, 111);
|
||||
assert_ok!(Balances::reserve(&1, 111));
|
||||
Balances::unreserve(&1, 42);
|
||||
assert_eq!(Balances::reserved_balance(&1), 69);
|
||||
assert_eq!(Balances::free_balance(&1), 42);
|
||||
assert_eq!(Balances::reserved_balance(1), 69);
|
||||
assert_eq!(Balances::free_balance(1), 42);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -445,8 +433,8 @@ fn slashing_reserved_balance_should_work() {
|
||||
let _ = Balances::deposit_creating(&1, 111);
|
||||
assert_ok!(Balances::reserve(&1, 111));
|
||||
assert_eq!(Balances::slash_reserved(&1, 42).1, 0);
|
||||
assert_eq!(Balances::reserved_balance(&1), 69);
|
||||
assert_eq!(Balances::free_balance(&1), 0);
|
||||
assert_eq!(Balances::reserved_balance(1), 69);
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
assert_eq!(<TotalIssuance<Test>>::get(), 69);
|
||||
});
|
||||
}
|
||||
@@ -457,8 +445,8 @@ fn slashing_incomplete_reserved_balance_should_work() {
|
||||
let _ = Balances::deposit_creating(&1, 111);
|
||||
assert_ok!(Balances::reserve(&1, 42));
|
||||
assert_eq!(Balances::slash_reserved(&1, 69).1, 27);
|
||||
assert_eq!(Balances::free_balance(&1), 69);
|
||||
assert_eq!(Balances::reserved_balance(&1), 0);
|
||||
assert_eq!(Balances::free_balance(1), 69);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
assert_eq!(<TotalIssuance<Test>>::get(), 69);
|
||||
});
|
||||
}
|
||||
@@ -470,10 +458,10 @@ fn transferring_reserved_balance_should_work() {
|
||||
let _ = Balances::deposit_creating(&2, 1);
|
||||
assert_ok!(Balances::reserve(&1, 110));
|
||||
assert_ok!(Balances::repatriate_reserved(&1, &2, 41), 0);
|
||||
assert_eq!(Balances::reserved_balance(&1), 69);
|
||||
assert_eq!(Balances::free_balance(&1), 0);
|
||||
assert_eq!(Balances::reserved_balance(&2), 0);
|
||||
assert_eq!(Balances::free_balance(&2), 42);
|
||||
assert_eq!(Balances::reserved_balance(1), 69);
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
assert_eq!(Balances::reserved_balance(2), 0);
|
||||
assert_eq!(Balances::free_balance(2), 42);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -493,26 +481,26 @@ fn transferring_incomplete_reserved_balance_should_work() {
|
||||
let _ = Balances::deposit_creating(&2, 1);
|
||||
assert_ok!(Balances::reserve(&1, 41));
|
||||
assert_ok!(Balances::repatriate_reserved(&1, &2, 69), 28);
|
||||
assert_eq!(Balances::reserved_balance(&1), 0);
|
||||
assert_eq!(Balances::free_balance(&1), 69);
|
||||
assert_eq!(Balances::reserved_balance(&2), 0);
|
||||
assert_eq!(Balances::free_balance(&2), 42);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
assert_eq!(Balances::free_balance(1), 69);
|
||||
assert_eq!(Balances::reserved_balance(2), 0);
|
||||
assert_eq!(Balances::free_balance(2), 42);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transferring_too_high_value_should_not_panic() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
<FreeBalance<Test>>::insert(1, u64::max_value());
|
||||
<FreeBalance<Test>>::insert(2, 1);
|
||||
Account::<Test>::insert(1, AccountData { free: u64::max_value(), .. Default::default() });
|
||||
Account::<Test>::insert(2, AccountData { free: 1, .. Default::default() });
|
||||
|
||||
assert_err!(
|
||||
Balances::transfer(Some(1).into(), 2, u64::max_value()),
|
||||
Error::<Test, _>::Overflow,
|
||||
);
|
||||
|
||||
assert_eq!(Balances::free_balance(&1), u64::max_value());
|
||||
assert_eq!(Balances::free_balance(&2), 1);
|
||||
assert_eq!(Balances::free_balance(1), u64::max_value());
|
||||
assert_eq!(Balances::free_balance(2), 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -524,7 +512,7 @@ fn account_create_on_free_too_low_with_other() {
|
||||
|
||||
// No-op.
|
||||
let _ = Balances::deposit_creating(&2, 50);
|
||||
assert_eq!(Balances::free_balance(&2), 0);
|
||||
assert_eq!(Balances::free_balance(2), 0);
|
||||
assert_eq!(<TotalIssuance<Test>>::get(), 100);
|
||||
})
|
||||
}
|
||||
@@ -535,7 +523,7 @@ fn account_create_on_free_too_low() {
|
||||
ExtBuilder::default().existential_deposit(100).build().execute_with(|| {
|
||||
// No-op.
|
||||
let _ = Balances::deposit_creating(&2, 50);
|
||||
assert_eq!(Balances::free_balance(&2), 0);
|
||||
assert_eq!(Balances::free_balance(2), 0);
|
||||
assert_eq!(<TotalIssuance<Test>>::get(), 0);
|
||||
})
|
||||
}
|
||||
@@ -549,8 +537,8 @@ fn account_removal_on_free_too_low() {
|
||||
let _ = Balances::deposit_creating(&1, 110);
|
||||
let _ = Balances::deposit_creating(&2, 110);
|
||||
|
||||
assert_eq!(Balances::free_balance(&1), 110);
|
||||
assert_eq!(Balances::free_balance(&2), 110);
|
||||
assert_eq!(Balances::free_balance(1), 110);
|
||||
assert_eq!(Balances::free_balance(2), 110);
|
||||
assert_eq!(<TotalIssuance<Test>>::get(), 220);
|
||||
|
||||
// Transfer funds from account 1 of such amount that after this transfer
|
||||
@@ -559,8 +547,8 @@ fn account_removal_on_free_too_low() {
|
||||
assert_ok!(Balances::transfer(Some(1).into(), 2, 20));
|
||||
|
||||
// Verify free balance removal of account 1.
|
||||
assert_eq!(Balances::free_balance(&1), 0);
|
||||
assert_eq!(Balances::free_balance(&2), 130);
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
assert_eq!(Balances::free_balance(2), 130);
|
||||
|
||||
// Verify that TotalIssuance tracks balance removal when free balance is too low.
|
||||
assert_eq!(<TotalIssuance<Test>>::get(), 130);
|
||||
@@ -580,160 +568,6 @@ fn transfer_overflow_isnt_exploitable() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_vesting_status() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(256)
|
||||
.monied(true)
|
||||
.vesting(true)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
let user1_free_balance = Balances::free_balance(&1);
|
||||
let user2_free_balance = Balances::free_balance(&2);
|
||||
let user12_free_balance = Balances::free_balance(&12);
|
||||
assert_eq!(user1_free_balance, 256 * 10); // Account 1 has free balance
|
||||
assert_eq!(user2_free_balance, 256 * 20); // Account 2 has free balance
|
||||
assert_eq!(user12_free_balance, 256 * 10); // Account 12 has free balance
|
||||
let user1_vesting_schedule = VestingSchedule {
|
||||
locked: 256 * 5,
|
||||
per_block: 128, // Vesting over 10 blocks
|
||||
starting_block: 0,
|
||||
};
|
||||
let user2_vesting_schedule = VestingSchedule {
|
||||
locked: 256 * 20,
|
||||
per_block: 256, // Vesting over 20 blocks
|
||||
starting_block: 10,
|
||||
};
|
||||
let user12_vesting_schedule = VestingSchedule {
|
||||
locked: 256 * 5,
|
||||
per_block: 64, // Vesting over 20 blocks
|
||||
starting_block: 10,
|
||||
};
|
||||
assert_eq!(Balances::vesting(&1), Some(user1_vesting_schedule)); // Account 1 has a vesting schedule
|
||||
assert_eq!(Balances::vesting(&2), Some(user2_vesting_schedule)); // Account 2 has a vesting schedule
|
||||
assert_eq!(Balances::vesting(&12), Some(user12_vesting_schedule)); // Account 12 has a vesting schedule
|
||||
|
||||
// Account 1 has only 128 units vested from their illiquid 256 * 5 units at block 1
|
||||
assert_eq!(Balances::vesting_balance(&1), 128 * 9);
|
||||
// Account 2 has their full balance locked
|
||||
assert_eq!(Balances::vesting_balance(&2), user2_free_balance);
|
||||
// Account 12 has only their illiquid funds locked
|
||||
assert_eq!(Balances::vesting_balance(&12), user12_free_balance - 256 * 5);
|
||||
|
||||
System::set_block_number(10);
|
||||
assert_eq!(System::block_number(), 10);
|
||||
|
||||
// Account 1 has fully vested by block 10
|
||||
assert_eq!(Balances::vesting_balance(&1), 0);
|
||||
// Account 2 has started vesting by block 10
|
||||
assert_eq!(Balances::vesting_balance(&2), user2_free_balance);
|
||||
// Account 12 has started vesting by block 10
|
||||
assert_eq!(Balances::vesting_balance(&12), user12_free_balance - 256 * 5);
|
||||
|
||||
System::set_block_number(30);
|
||||
assert_eq!(System::block_number(), 30);
|
||||
|
||||
assert_eq!(Balances::vesting_balance(&1), 0); // Account 1 is still fully vested, and not negative
|
||||
assert_eq!(Balances::vesting_balance(&2), 0); // Account 2 has fully vested by block 30
|
||||
assert_eq!(Balances::vesting_balance(&12), 0); // Account 2 has fully vested by block 30
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unvested_balance_should_not_transfer() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(10)
|
||||
.monied(true)
|
||||
.vesting(true)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
let user1_free_balance = Balances::free_balance(&1);
|
||||
assert_eq!(user1_free_balance, 100); // Account 1 has free balance
|
||||
// Account 1 has only 5 units vested at block 1 (plus 50 unvested)
|
||||
assert_eq!(Balances::vesting_balance(&1), 45);
|
||||
assert_noop!(
|
||||
Balances::transfer(Some(1).into(), 2, 56),
|
||||
Error::<Test, _>::VestingBalance,
|
||||
); // Account 1 cannot send more than vested amount
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vested_balance_should_transfer() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(10)
|
||||
.monied(true)
|
||||
.vesting(true)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
let user1_free_balance = Balances::free_balance(&1);
|
||||
assert_eq!(user1_free_balance, 100); // Account 1 has free balance
|
||||
// Account 1 has only 5 units vested at block 1 (plus 50 unvested)
|
||||
assert_eq!(Balances::vesting_balance(&1), 45);
|
||||
assert_ok!(Balances::transfer(Some(1).into(), 2, 55));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extra_balance_should_transfer() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(10)
|
||||
.monied(true)
|
||||
.vesting(true)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
assert_ok!(Balances::transfer(Some(3).into(), 1, 100));
|
||||
assert_ok!(Balances::transfer(Some(3).into(), 2, 100));
|
||||
|
||||
let user1_free_balance = Balances::free_balance(&1);
|
||||
assert_eq!(user1_free_balance, 200); // Account 1 has 100 more free balance than normal
|
||||
|
||||
let user2_free_balance = Balances::free_balance(&2);
|
||||
assert_eq!(user2_free_balance, 300); // Account 2 has 100 more free balance than normal
|
||||
|
||||
// Account 1 has only 5 units vested at block 1 (plus 150 unvested)
|
||||
assert_eq!(Balances::vesting_balance(&1), 45);
|
||||
assert_ok!(Balances::transfer(Some(1).into(), 3, 155)); // Account 1 can send extra units gained
|
||||
|
||||
// Account 2 has no units vested at block 1, but gained 100
|
||||
assert_eq!(Balances::vesting_balance(&2), 200);
|
||||
assert_ok!(Balances::transfer(Some(2).into(), 3, 100)); // Account 2 can send extra units gained
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn liquid_funds_should_transfer_with_delayed_vesting() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(256)
|
||||
.monied(true)
|
||||
.vesting(true)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
let user12_free_balance = Balances::free_balance(&12);
|
||||
|
||||
assert_eq!(user12_free_balance, 2560); // Account 12 has free balance
|
||||
// Account 12 has liquid funds
|
||||
assert_eq!(Balances::vesting_balance(&12), user12_free_balance - 256 * 5);
|
||||
|
||||
// Account 12 has delayed vesting
|
||||
let user12_vesting_schedule = VestingSchedule {
|
||||
locked: 256 * 5,
|
||||
per_block: 64, // Vesting over 20 blocks
|
||||
starting_block: 10,
|
||||
};
|
||||
assert_eq!(Balances::vesting(&12), Some(user12_vesting_schedule));
|
||||
|
||||
// Account 12 can still send liquid funds
|
||||
assert_ok!(Balances::transfer(Some(12).into(), 3, 256 * 5));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn burn_must_work() {
|
||||
ExtBuilder::default().monied(true).build().execute_with(|| {
|
||||
@@ -766,45 +600,58 @@ fn cannot_set_genesis_value_below_ed() {
|
||||
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
||||
let _ = GenesisConfig::<Test> {
|
||||
balances: vec![(1, 10)],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dust_moves_between_free_and_reserved() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(100)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
// Set balance to free and reserved at the existential deposit
|
||||
assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 1, 100, 100));
|
||||
assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 2, 100, 100));
|
||||
// Check balance
|
||||
assert_eq!(Balances::free_balance(1), 100);
|
||||
assert_eq!(Balances::reserved_balance(1), 100);
|
||||
assert_eq!(Balances::free_balance(2), 100);
|
||||
assert_eq!(Balances::reserved_balance(2), 100);
|
||||
.existential_deposit(100)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
// Set balance to free and reserved at the existential deposit
|
||||
assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 1, 100, 0));
|
||||
// Check balance
|
||||
assert_eq!(Balances::free_balance(1), 100);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
|
||||
// Drop 1 free_balance below ED
|
||||
assert_ok!(Balances::transfer(Some(1).into(), 2, 1));
|
||||
// Check balance, the other 99 should move to reserved_balance
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
assert_eq!(Balances::reserved_balance(1), 199);
|
||||
// Reserve some free balance
|
||||
assert_ok!(Balances::reserve(&1, 50));
|
||||
// Check balance, the account should be ok.
|
||||
assert_eq!(Balances::free_balance(1), 50);
|
||||
assert_eq!(Balances::reserved_balance(1), 50);
|
||||
|
||||
// Reset accounts
|
||||
assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 1, 100, 100));
|
||||
assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 2, 100, 100));
|
||||
// Reserve the rest of the free balance
|
||||
assert_ok!(Balances::reserve(&1, 50));
|
||||
// Check balance, the account should be ok.
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
assert_eq!(Balances::reserved_balance(1), 100);
|
||||
|
||||
// Drop 2 reserved_balance below ED
|
||||
Balances::unreserve(&2, 1);
|
||||
// Check balance, all 100 should move to free_balance
|
||||
assert_eq!(Balances::free_balance(2), 200);
|
||||
assert_eq!(Balances::reserved_balance(2), 0);
|
||||
|
||||
// An account with both too little free and reserved is completely killed
|
||||
assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 1, 99, 99));
|
||||
// Check balance is 0 for everything
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
});
|
||||
// Unreserve everything
|
||||
Balances::unreserve(&1, 100);
|
||||
// Check balance, all 100 should move to free_balance
|
||||
assert_eq!(Balances::free_balance(1), 100);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn account_deleted_when_just_dust() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(100)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
// Set balance to free and reserved at the existential deposit
|
||||
assert_ok!(Balances::set_balance(RawOrigin::Root.into(), 1, 50, 50));
|
||||
// Check balance
|
||||
assert_eq!(Balances::free_balance(1), 50);
|
||||
assert_eq!(Balances::reserved_balance(1), 50);
|
||||
|
||||
// Reserve some free balance
|
||||
let _ = Balances::slash(&1, 1);
|
||||
// The account should be dead.
|
||||
assert!(Balances::is_dead_account(&1));
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ impl<T: Trait> AccountDb<T> for DirectAccountDb {
|
||||
let (imbalance, outcome) = T::Currency::make_free_balance_be(&address, balance);
|
||||
total_imbalance = total_imbalance.merge(imbalance);
|
||||
if let UpdateBalanceOutcome::AccountKilled = outcome {
|
||||
// Account killed. This will ultimately lead to calling `OnFreeBalanceZero` callback
|
||||
// Account killed. This will ultimately lead to calling `OnReapAccount` callback
|
||||
// which will make removal of CodeHashOf and AccountStorage for this account.
|
||||
// In order to avoid writing over the deleted properties we `continue` here.
|
||||
continue;
|
||||
|
||||
@@ -573,7 +573,7 @@ impl<T: Trait> Token<T> for TransferFeeToken<BalanceOf<T>> {
|
||||
let balance_fee = match self.kind {
|
||||
TransferFeeKind::ContractInstantiate => metadata.contract_account_instantiate_fee,
|
||||
TransferFeeKind::AccountCreate => metadata.account_create_fee,
|
||||
TransferFeeKind::Transfer => metadata.transfer_fee,
|
||||
TransferFeeKind::Transfer => return metadata.schedule.transfer_cost,
|
||||
};
|
||||
approx_gas_for_balance(self.gas_price, balance_fee)
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ use frame_support::{
|
||||
parameter_types, IsSubType,
|
||||
weights::DispatchInfo,
|
||||
};
|
||||
use frame_support::traits::{OnFreeBalanceZero, OnUnbalanced, Currency, Get, Time, Randomness};
|
||||
use frame_support::traits::{OnReapAccount, OnUnbalanced, Currency, Get, Time, Randomness};
|
||||
use frame_system::{self as system, ensure_signed, RawOrigin, ensure_root};
|
||||
use sp_core::storage::well_known_keys::CHILD_STORAGE_KEY_PREFIX;
|
||||
use pallet_contracts_primitives::{RentProjection, ContractAccessError};
|
||||
@@ -401,9 +401,6 @@ pub trait Trait: frame_system::Trait {
|
||||
/// to removal of a contract.
|
||||
type SurchargeReward: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The fee required to make a transfer.
|
||||
type TransferFee: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The fee required to create an account.
|
||||
type CreationFee: Get<BalanceOf<Self>>;
|
||||
|
||||
@@ -520,9 +517,6 @@ decl_module! {
|
||||
/// to removal of a contract.
|
||||
const SurchargeReward: BalanceOf<T> = T::SurchargeReward::get();
|
||||
|
||||
/// The fee required to make a transfer.
|
||||
const TransferFee: BalanceOf<T> = T::TransferFee::get();
|
||||
|
||||
/// The fee required to create an account.
|
||||
const CreationFee: BalanceOf<T> = T::CreationFee::get();
|
||||
|
||||
@@ -953,8 +947,8 @@ decl_storage! {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> OnFreeBalanceZero<T::AccountId> for Module<T> {
|
||||
fn on_free_balance_zero(who: &T::AccountId) {
|
||||
impl<T: Trait> OnReapAccount<T::AccountId> for Module<T> {
|
||||
fn on_reap_account(who: &T::AccountId) {
|
||||
if let Some(ContractInfo::Alive(info)) = <ContractInfoOf<T>>::take(who) {
|
||||
child::kill_storage(&info.trie_id, info.child_trie_unique_id());
|
||||
}
|
||||
@@ -973,7 +967,6 @@ pub struct Config<T: Trait> {
|
||||
pub max_value_size: u32,
|
||||
pub contract_account_instantiate_fee: BalanceOf<T>,
|
||||
pub account_create_fee: BalanceOf<T>,
|
||||
pub transfer_fee: BalanceOf<T>,
|
||||
}
|
||||
|
||||
impl<T: Trait> Config<T> {
|
||||
@@ -986,7 +979,6 @@ impl<T: Trait> Config<T> {
|
||||
max_value_size: T::MaxValueSize::get(),
|
||||
contract_account_instantiate_fee: T::ContractFee::get(),
|
||||
account_create_fee: T::CreationFee::get(),
|
||||
transfer_fee: T::TransferFee::get(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1031,6 +1023,9 @@ pub struct Schedule {
|
||||
/// Gas cost per one byte written to the sandbox memory.
|
||||
pub sandbox_data_write_cost: Gas,
|
||||
|
||||
/// Cost for a simple balance transfer.
|
||||
pub transfer_cost: Gas,
|
||||
|
||||
/// The maximum number of topics supported by an event.
|
||||
pub max_event_topics: u32,
|
||||
|
||||
@@ -1069,6 +1064,7 @@ impl Default for Schedule {
|
||||
instantiate_base_cost: 175,
|
||||
sandbox_data_read_cost: 1,
|
||||
sandbox_data_write_cost: 1,
|
||||
transfer_cost: 100,
|
||||
max_event_topics: 4,
|
||||
max_stack_height: 64 * 1024,
|
||||
max_memory_pages: 16,
|
||||
|
||||
@@ -121,14 +121,12 @@ impl frame_system::Trait for Test {
|
||||
}
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = Contract;
|
||||
type OnReapAccount = System;
|
||||
type OnReapAccount = (System, Contract);
|
||||
type OnNewAccount = ();
|
||||
type Event = MetaEvent;
|
||||
type DustRemoval = ();
|
||||
type TransferPayment = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
parameter_types! {
|
||||
@@ -171,7 +169,6 @@ impl Trait for Test {
|
||||
type RentByteFee = RentByteFee;
|
||||
type RentDepositOffset = RentDepositOffset;
|
||||
type SurchargeReward = SurchargeReward;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
@@ -278,7 +275,6 @@ impl ExtBuilder {
|
||||
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
||||
pallet_balances::GenesisConfig::<Test> {
|
||||
balances: vec![],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
GenesisConfig::<Test> {
|
||||
current_schedule: Schedule {
|
||||
@@ -311,7 +307,7 @@ fn refunds_unused_gas() {
|
||||
assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, Vec::new()));
|
||||
|
||||
// 2 * 135 - gas price multiplied by the call base fee.
|
||||
assert_eq!(Balances::free_balance(&ALICE), 100_000_000 - (2 * 135));
|
||||
assert_eq!(Balances::free_balance(ALICE), 100_000_000 - (2 * 135));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1018,7 +1014,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
|
||||
// Trigger rent must have no effect
|
||||
assert!(trigger_call());
|
||||
assert_eq!(ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000);
|
||||
assert_eq!(Balances::free_balance(&BOB), 100);
|
||||
assert_eq!(Balances::free_balance(BOB), 100);
|
||||
|
||||
// Advance blocks
|
||||
initialize_block(10);
|
||||
@@ -1026,7 +1022,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
|
||||
// Trigger rent through call
|
||||
assert!(trigger_call());
|
||||
assert!(ContractInfoOf::<Test>::get(BOB).unwrap().get_tombstone().is_some());
|
||||
assert_eq!(Balances::free_balance(&BOB), subsistence_threshold);
|
||||
assert_eq!(Balances::free_balance(BOB), subsistence_threshold);
|
||||
|
||||
// Advance blocks
|
||||
initialize_block(20);
|
||||
@@ -1034,7 +1030,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
|
||||
// Trigger rent must have no effect
|
||||
assert!(trigger_call());
|
||||
assert!(ContractInfoOf::<Test>::get(BOB).unwrap().get_tombstone().is_some());
|
||||
assert_eq!(Balances::free_balance(&BOB), subsistence_threshold);
|
||||
assert_eq!(Balances::free_balance(BOB), subsistence_threshold);
|
||||
});
|
||||
|
||||
// Allowance exceeded
|
||||
@@ -1052,7 +1048,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
|
||||
// Trigger rent must have no effect
|
||||
assert!(trigger_call());
|
||||
assert_eq!(ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 100);
|
||||
assert_eq!(Balances::free_balance(&BOB), 1_000);
|
||||
assert_eq!(Balances::free_balance(BOB), 1_000);
|
||||
|
||||
// Advance blocks
|
||||
initialize_block(10);
|
||||
@@ -1061,7 +1057,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
|
||||
assert!(trigger_call());
|
||||
assert!(ContractInfoOf::<Test>::get(BOB).unwrap().get_tombstone().is_some());
|
||||
// Balance should be initial balance - initial rent_allowance
|
||||
assert_eq!(Balances::free_balance(&BOB), 900);
|
||||
assert_eq!(Balances::free_balance(BOB), 900);
|
||||
|
||||
// Advance blocks
|
||||
initialize_block(20);
|
||||
@@ -1069,7 +1065,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
|
||||
// Trigger rent must have no effect
|
||||
assert!(trigger_call());
|
||||
assert!(ContractInfoOf::<Test>::get(BOB).unwrap().get_tombstone().is_some());
|
||||
assert_eq!(Balances::free_balance(&BOB), 900);
|
||||
assert_eq!(Balances::free_balance(BOB), 900);
|
||||
});
|
||||
|
||||
// Balance reached and inferior to subsistence threshold
|
||||
@@ -1087,12 +1083,12 @@ fn removals(trigger_call: impl Fn() -> bool) {
|
||||
// Trigger rent must have no effect
|
||||
assert!(trigger_call());
|
||||
assert_eq!(ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000);
|
||||
assert_eq!(Balances::free_balance(&BOB), 50 + Balances::minimum_balance());
|
||||
assert_eq!(Balances::free_balance(BOB), 50 + Balances::minimum_balance());
|
||||
|
||||
// Transfer funds
|
||||
assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::transfer()));
|
||||
assert_eq!(ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000);
|
||||
assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance());
|
||||
assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance());
|
||||
|
||||
// Advance blocks
|
||||
initialize_block(10);
|
||||
@@ -1100,7 +1096,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
|
||||
// Trigger rent through call
|
||||
assert!(trigger_call());
|
||||
assert!(ContractInfoOf::<Test>::get(BOB).is_none());
|
||||
assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance());
|
||||
assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance());
|
||||
|
||||
// Advance blocks
|
||||
initialize_block(20);
|
||||
@@ -1108,7 +1104,7 @@ fn removals(trigger_call: impl Fn() -> bool) {
|
||||
// Trigger rent must have no effect
|
||||
assert!(trigger_call());
|
||||
assert!(ContractInfoOf::<Test>::get(BOB).is_none());
|
||||
assert_eq!(Balances::free_balance(&BOB), Balances::minimum_balance());
|
||||
assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ frame-system = { version = "2.0.0", default-features = false, path = "../system"
|
||||
[dev-dependencies]
|
||||
sp-core = { version = "2.0.0", path = "../../primitives/core" }
|
||||
pallet-balances = { version = "2.0.0", path = "../balances" }
|
||||
sp-storage = { version = "2.0.0", path = "../../primitives/storage" }
|
||||
hex-literal = "0.2.1"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
||||
@@ -30,7 +30,7 @@ use frame_support::{
|
||||
weights::SimpleDispatchInfo,
|
||||
traits::{
|
||||
Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, Get,
|
||||
OnFreeBalanceZero, OnUnbalanced
|
||||
OnReapAccount, OnUnbalanced
|
||||
}
|
||||
};
|
||||
use frame_system::{self as system, ensure_signed, ensure_root};
|
||||
@@ -305,6 +305,10 @@ decl_storage! {
|
||||
pub Delegations get(fn delegations):
|
||||
linked_map hasher(blake2_256) T::AccountId => (T::AccountId, Conviction);
|
||||
|
||||
/// Accounts for which there are locks in action which may be removed at some point in the
|
||||
/// future. The value is the block number at which the lock expires and may be removed.
|
||||
pub Locks get(locks): map hasher(blake2_256) T::AccountId => Option<T::BlockNumber>;
|
||||
|
||||
/// True if the last referendum tabled was submitted externally. False if it was a public
|
||||
/// proposal.
|
||||
pub LastTabledWasExternal: bool;
|
||||
@@ -364,6 +368,8 @@ decl_event! {
|
||||
PreimageMissing(Hash, ReferendumIndex),
|
||||
/// A registered preimage was removed and the deposit collected by the reaper (last item).
|
||||
PreimageReaped(Hash, AccountId, Balance, AccountId),
|
||||
/// An account has been unlocked successfully.
|
||||
Unlocked(AccountId),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,6 +419,10 @@ decl_error! {
|
||||
PreimageInvalid,
|
||||
/// No proposals waiting
|
||||
NoneWaiting,
|
||||
/// The target account does not have a lock.
|
||||
NotLocked,
|
||||
/// The lock on the account to be unlocked has not yet expired.
|
||||
NotExpired,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,9 +711,9 @@ decl_module! {
|
||||
DEMOCRACY_ID,
|
||||
&who,
|
||||
Bounded::max_value(),
|
||||
T::BlockNumber::max_value(),
|
||||
WithdrawReason::Transfer.into()
|
||||
);
|
||||
Locks::<T>::remove(&who);
|
||||
Self::deposit_event(RawEvent::Delegated(who, to));
|
||||
}
|
||||
|
||||
@@ -720,12 +730,12 @@ decl_module! {
|
||||
// Indefinite lock is reduced to the maximum voting lock that could be possible.
|
||||
let now = <frame_system::Module<T>>::block_number();
|
||||
let locked_until = now + T::EnactmentPeriod::get() * conviction.lock_periods().into();
|
||||
Locks::<T>::insert(&who, locked_until);
|
||||
T::Currency::set_lock(
|
||||
DEMOCRACY_ID,
|
||||
&who,
|
||||
Bounded::max_value(),
|
||||
locked_until,
|
||||
WithdrawReason::Transfer.into()
|
||||
WithdrawReason::Transfer.into(),
|
||||
);
|
||||
Self::deposit_event(RawEvent::Undelegated(who));
|
||||
}
|
||||
@@ -796,6 +806,18 @@ decl_module! {
|
||||
<Preimages<T>>::remove(&proposal_hash);
|
||||
Self::deposit_event(RawEvent::PreimageReaped(proposal_hash, old, deposit, who));
|
||||
}
|
||||
|
||||
#[weight = SimpleDispatchInfo::FixedNormal(10_000)]
|
||||
fn unlock(origin, target: T::AccountId) {
|
||||
ensure_signed(origin)?;
|
||||
|
||||
let expiry = Locks::<T>::get(&target).ok_or(Error::<T>::NotLocked)?;
|
||||
ensure!(expiry <= system::Module::<T>::block_number(), Error::<T>::NotExpired);
|
||||
|
||||
T::Currency::remove_lock(DEMOCRACY_ID, &target);
|
||||
Locks::<T>::remove(&target);
|
||||
Self::deposit_event(RawEvent::Unlocked(target));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1081,14 +1103,15 @@ impl<T: Trait> Module<T> {
|
||||
// now plus: the base lock period multiplied by the number of periods this voter
|
||||
// offered to lock should they win...
|
||||
let locked_until = now + T::EnactmentPeriod::get() * conviction.lock_periods().into();
|
||||
Locks::<T>::insert(&a, locked_until);
|
||||
// ...extend their bondage until at least then.
|
||||
T::Currency::extend_lock(
|
||||
DEMOCRACY_ID,
|
||||
&a,
|
||||
Bounded::max_value(),
|
||||
locked_until,
|
||||
WithdrawReason::Transfer.into()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Self::clear_referendum(index);
|
||||
@@ -1139,8 +1162,8 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> OnFreeBalanceZero<T::AccountId> for Module<T> {
|
||||
fn on_free_balance_zero(who: &T::AccountId) {
|
||||
impl<T: Trait> OnReapAccount<T::AccountId> for Module<T> {
|
||||
fn on_reap_account(who: &T::AccountId) {
|
||||
<Proxy<T>>::remove(who)
|
||||
}
|
||||
}
|
||||
@@ -1155,11 +1178,12 @@ mod tests {
|
||||
};
|
||||
use sp_core::H256;
|
||||
use sp_runtime::{
|
||||
traits::{BlakeTwo256, IdentityLookup, Bounded, BadOrigin},
|
||||
traits::{BlakeTwo256, IdentityLookup, Bounded, BadOrigin, OnInitialize},
|
||||
testing::Header, Perbill,
|
||||
};
|
||||
use pallet_balances::{BalanceLock, Error as BalancesError};
|
||||
use frame_system::EnsureSignedBy;
|
||||
use sp_storage::Storage;
|
||||
|
||||
const AYE: Vote = Vote{ aye: true, conviction: Conviction::None };
|
||||
const NAY: Vote = Vote{ aye: false, conviction: Conviction::None };
|
||||
@@ -1206,19 +1230,16 @@ mod tests {
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type OnNewAccount = ();
|
||||
type Event = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
parameter_types! {
|
||||
@@ -1273,7 +1294,6 @@ mod tests {
|
||||
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
||||
pallet_balances::GenesisConfig::<Test>{
|
||||
balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
GenesisConfig::default().assimilate_storage(&mut t).unwrap();
|
||||
sp_io::TestExternalities::new(t)
|
||||
@@ -1283,11 +1303,60 @@ mod tests {
|
||||
type Balances = pallet_balances::Module<Test>;
|
||||
type Democracy = Module<Test>;
|
||||
|
||||
#[test]
|
||||
fn lock_info_via_migration_should_work() {
|
||||
let mut s = Storage::default();
|
||||
use hex_literal::hex;
|
||||
// A dump of data from the previous version for which we know account 1 has 5 of its 10
|
||||
// reserved and 3 of the rest is locked for misc. Account 2 has all 20 locked until block 5
|
||||
// for everything and additionally 3 locked for just fees.
|
||||
let data = vec![
|
||||
(hex!["26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac"].to_vec(), hex!["0100000000000000"].to_vec()),
|
||||
(hex!["26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850"].to_vec(), hex!["02000000"].to_vec()),
|
||||
(hex!["26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7"].to_vec(), hex!["08000000000000000000000000"].to_vec()),
|
||||
(hex!["26aa394eea5630e07c48ae0c9558cef78a42f33323cb5ced3b44dd825fda9fcc"].to_vec(), hex!["4545454545454545454545454545454545454545454545454545454545454545"].to_vec()),
|
||||
(hex!["26aa394eea5630e07c48ae0c9558cef7a44704b568d21667356a5a050c11874681e47a19e6b29b0a65b9591762ce5143ed30d0261e5d24a3201752506b20f15c"].to_vec(), hex!["4545454545454545454545454545454545454545454545454545454545454545"].to_vec()),
|
||||
(hex!["3a636f6465"].to_vec(), hex![""].to_vec()),
|
||||
(hex!["3a65787472696e7369635f696e646578"].to_vec(), hex!["00000000"].to_vec()),
|
||||
(hex!["3a686561707061676573"].to_vec(), hex!["0800000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc61dbd7d0b561a41d23c2a469ad42fbd70d5438bae826f6fd607413190c37c363b"].to_vec(), hex!["046d697363202020200300000000000000ffffffffffffffff04"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc66cddb367afbd583bb48f9bbd7d5ba3b1d0738b4881b1cddd38169526d8158137"].to_vec(), hex!["0474786665657320200300000000000000ffffffffffffffff01"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6e88b43fded6323ef02ffeffbd8c40846ee09bf316271bd22369659c959dd733a"].to_vec(), hex!["08616c6c20202020200300000000000000ffffffffffffffff1f64656d6f63726163ffffffffffffffff030000000000000002"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f3c22813def93ef32c365b55cb92f10f91dbd7d0b561a41d23c2a469ad42fbd70d5438bae826f6fd607413190c37c363b"].to_vec(), hex!["0500000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80"].to_vec(), hex!["d200000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f5f27b51b5ec208ee9cb25b55d8728243b8788bb218b185b63e3e92653953f29b6b143fb8cf5159fc908632e6fe490501"].to_vec(), hex!["1e0000000000000006000000000000000200000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b41dbd7d0b561a41d23c2a469ad42fbd70d5438bae826f6fd607413190c37c363b"].to_vec(), hex!["0500000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b46cddb367afbd583bb48f9bbd7d5ba3b1d0738b4881b1cddd38169526d8158137"].to_vec(), hex!["1e00000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b4b8788bb218b185b63e3e92653953f29b6b143fb8cf5159fc908632e6fe490501"].to_vec(), hex!["3c00000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b4e88b43fded6323ef02ffeffbd8c40846ee09bf316271bd22369659c959dd733a"].to_vec(), hex!["1400000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b4e96760d274653a39b429a87ebaae9d3aa4fdf58b9096cf0bebc7c4e5a4c2ed8d"].to_vec(), hex!["2800000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b4effb728943197fd12e694cbf3f3ede28fbf7498b0370c6dfa0013874b417c178"].to_vec(), hex!["3200000000000000"].to_vec()),
|
||||
(hex!["f2794c22e353e9a839f12faab03a911b7f17cdfbfa73331856cca0acddd7842e"].to_vec(), hex!["00000000"].to_vec()),
|
||||
(hex!["f2794c22e353e9a839f12faab03a911bbdcb0c5143a8617ed38ae3810dd45bc6"].to_vec(), hex!["00000000"].to_vec()),
|
||||
(hex!["f2794c22e353e9a839f12faab03a911be2f6cb0456905c189bcb0458f9440f13"].to_vec(), hex!["00000000"].to_vec()),
|
||||
];
|
||||
s.top = data.into_iter().collect();
|
||||
sp_io::TestExternalities::new(s).execute_with(|| {
|
||||
Balances::on_initialize(1);
|
||||
assert_eq!(Balances::free_balance(1), 5);
|
||||
assert_eq!(Balances::reserved_balance(1), 5);
|
||||
assert_eq!(Balances::usable_balance(&1), 2);
|
||||
assert_eq!(Balances::usable_balance_for_fees(&1), 5);
|
||||
assert_eq!(Balances::free_balance(2), 20);
|
||||
assert_eq!(Balances::reserved_balance(2), 0);
|
||||
assert_eq!(Balances::usable_balance(&2), 0);
|
||||
assert_eq!(Balances::usable_balance_for_fees(&2), 17);
|
||||
fast_forward_to(5);
|
||||
assert_ok!(Democracy::unlock(Origin::signed(2), 2));
|
||||
assert_eq!(Balances::usable_balance(&2), 17);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn params_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(Democracy::referendum_count(), 0);
|
||||
assert_eq!(Balances::free_balance(&42), 0);
|
||||
assert_eq!(Balances::free_balance(42), 0);
|
||||
assert_eq!(Balances::total_issuance(), 210);
|
||||
});
|
||||
}
|
||||
@@ -1353,7 +1422,7 @@ mod tests {
|
||||
next_block();
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 0);
|
||||
assert_eq!(Balances::free_balance(42), 0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1405,8 +1474,8 @@ mod tests {
|
||||
next_block();
|
||||
assert_ok!(Democracy::reap_preimage(Origin::signed(6), set_balance_proposal_hash(2)));
|
||||
|
||||
assert_eq!(Balances::reserved_balance(6), 0);
|
||||
assert_eq!(Balances::free_balance(6), 60);
|
||||
assert_eq!(Balances::reserved_balance(6), 0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1869,7 +1938,7 @@ mod tests {
|
||||
// referendum passes and wait another two blocks for enactment.
|
||||
fast_forward_to(6);
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1942,7 +2011,7 @@ mod tests {
|
||||
assert_eq!(Democracy::tally(r), (1, 0, 1));
|
||||
|
||||
fast_forward_to(6);
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1967,7 +2036,7 @@ mod tests {
|
||||
|
||||
fast_forward_to(6);
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1993,7 +2062,7 @@ mod tests {
|
||||
|
||||
fast_forward_to(6);
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2020,7 +2089,7 @@ mod tests {
|
||||
|
||||
fast_forward_to(6);
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2048,7 +2117,7 @@ mod tests {
|
||||
|
||||
fast_forward_to(6);
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2080,7 +2149,7 @@ mod tests {
|
||||
|
||||
fast_forward_to(6);
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2093,9 +2162,9 @@ mod tests {
|
||||
assert_ok!(Democracy::second(Origin::signed(5), 0));
|
||||
assert_ok!(Democracy::second(Origin::signed(5), 0));
|
||||
assert_ok!(Democracy::second(Origin::signed(5), 0));
|
||||
assert_eq!(Balances::free_balance(&1), 5);
|
||||
assert_eq!(Balances::free_balance(&2), 15);
|
||||
assert_eq!(Balances::free_balance(&5), 35);
|
||||
assert_eq!(Balances::free_balance(1), 5);
|
||||
assert_eq!(Balances::free_balance(2), 15);
|
||||
assert_eq!(Balances::free_balance(5), 35);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2109,9 +2178,9 @@ mod tests {
|
||||
assert_ok!(Democracy::second(Origin::signed(5), 0));
|
||||
assert_ok!(Democracy::second(Origin::signed(5), 0));
|
||||
fast_forward_to(3);
|
||||
assert_eq!(Balances::free_balance(&1), 10);
|
||||
assert_eq!(Balances::free_balance(&2), 20);
|
||||
assert_eq!(Balances::free_balance(&5), 50);
|
||||
assert_eq!(Balances::free_balance(1), 10);
|
||||
assert_eq!(Balances::free_balance(2), 20);
|
||||
assert_eq!(Balances::free_balance(5), 50);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2179,7 +2248,7 @@ mod tests {
|
||||
assert_eq!(Democracy::tally(r2), (1, 0, 1));
|
||||
|
||||
next_block();
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
|
||||
assert_ok!(Democracy::vote(Origin::signed(1), r1, AYE));
|
||||
assert_eq!(Democracy::voters_for(r1), vec![1]);
|
||||
@@ -2187,7 +2256,7 @@ mod tests {
|
||||
assert_eq!(Democracy::tally(r1), (1, 0, 1));
|
||||
|
||||
next_block();
|
||||
assert_eq!(Balances::free_balance(&42), 3);
|
||||
assert_eq!(Balances::free_balance(42), 3);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2210,7 +2279,7 @@ mod tests {
|
||||
next_block();
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2230,7 +2299,7 @@ mod tests {
|
||||
next_block();
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 0);
|
||||
assert_eq!(Balances::free_balance(42), 0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2253,7 +2322,7 @@ mod tests {
|
||||
next_block();
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 0);
|
||||
assert_eq!(Balances::free_balance(42), 0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2280,7 +2349,7 @@ mod tests {
|
||||
next_block();
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2304,11 +2373,11 @@ mod tests {
|
||||
assert_eq!(Democracy::tally(r), (21, 0, 21));
|
||||
|
||||
next_block();
|
||||
assert_eq!(Balances::free_balance(&42), 0);
|
||||
assert_eq!(Balances::free_balance(42), 0);
|
||||
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2330,14 +2399,14 @@ mod tests {
|
||||
next_block();
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 0);
|
||||
assert_eq!(Balances::free_balance(42), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn passing_low_turnout_voting_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(Balances::free_balance(&42), 0);
|
||||
assert_eq!(Balances::free_balance(42), 0);
|
||||
assert_eq!(Balances::total_issuance(), 210);
|
||||
|
||||
System::set_block_number(1);
|
||||
@@ -2356,7 +2425,7 @@ mod tests {
|
||||
next_block();
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2399,24 +2468,44 @@ mod tests {
|
||||
assert_eq!(Balances::locks(2), vec![BalanceLock {
|
||||
id: DEMOCRACY_ID,
|
||||
amount: u64::max_value(),
|
||||
until: 18,
|
||||
reasons: WithdrawReason::Transfer.into()
|
||||
reasons: pallet_balances::Reasons::Misc,
|
||||
}]);
|
||||
assert_eq!(Democracy::locks(2), Some(18));
|
||||
assert_eq!(Balances::locks(3), vec![BalanceLock {
|
||||
id: DEMOCRACY_ID,
|
||||
amount: u64::max_value(),
|
||||
until: 10,
|
||||
reasons: WithdrawReason::Transfer.into()
|
||||
reasons: pallet_balances::Reasons::Misc,
|
||||
}]);
|
||||
assert_eq!(Democracy::locks(3), Some(10));
|
||||
assert_eq!(Balances::locks(4), vec![BalanceLock {
|
||||
id: DEMOCRACY_ID,
|
||||
amount: u64::max_value(),
|
||||
until: 6,
|
||||
reasons: WithdrawReason::Transfer.into()
|
||||
reasons: pallet_balances::Reasons::Misc,
|
||||
}]);
|
||||
assert_eq!(Democracy::locks(4), Some(6));
|
||||
assert_eq!(Balances::locks(5), vec![]);
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
|
||||
assert_noop!(Democracy::unlock(Origin::signed(1), 1), Error::<Test>::NotLocked);
|
||||
|
||||
fast_forward_to(5);
|
||||
assert_noop!(Democracy::unlock(Origin::signed(1), 4), Error::<Test>::NotExpired);
|
||||
fast_forward_to(6);
|
||||
assert_ok!(Democracy::unlock(Origin::signed(1), 4));
|
||||
assert_noop!(Democracy::unlock(Origin::signed(1), 4), Error::<Test>::NotLocked);
|
||||
|
||||
fast_forward_to(9);
|
||||
assert_noop!(Democracy::unlock(Origin::signed(1), 3), Error::<Test>::NotExpired);
|
||||
fast_forward_to(10);
|
||||
assert_ok!(Democracy::unlock(Origin::signed(1), 3));
|
||||
assert_noop!(Democracy::unlock(Origin::signed(1), 3), Error::<Test>::NotLocked);
|
||||
|
||||
fast_forward_to(17);
|
||||
assert_noop!(Democracy::unlock(Origin::signed(1), 2), Error::<Test>::NotExpired);
|
||||
fast_forward_to(18);
|
||||
assert_ok!(Democracy::unlock(Origin::signed(1), 2));
|
||||
assert_noop!(Democracy::unlock(Origin::signed(1), 2), Error::<Test>::NotLocked);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2453,7 +2542,7 @@ mod tests {
|
||||
next_block();
|
||||
next_block();
|
||||
|
||||
assert_eq!(Balances::free_balance(&42), 2);
|
||||
assert_eq!(Balances::free_balance(42), 2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use sp_runtime::{print, DispatchResult, DispatchError, traits::{Zero, StaticLookup, Bounded, Convert}};
|
||||
use sp_runtime::{print, DispatchResult, DispatchError, traits::{Zero, StaticLookup, Convert}};
|
||||
use frame_support::{
|
||||
decl_storage, decl_event, ensure, decl_module, decl_error, weights::SimpleDispatchInfo,
|
||||
traits::{
|
||||
@@ -260,7 +260,6 @@ decl_module! {
|
||||
MODULE_ID,
|
||||
&who,
|
||||
locked_balance,
|
||||
T::BlockNumber::max_value(),
|
||||
WithdrawReasons::except(WithdrawReason::TransactionPayment),
|
||||
);
|
||||
<StakeOf<T>>::insert(&who, locked_balance);
|
||||
@@ -816,20 +815,17 @@ mod tests {
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnNewAccount = ();
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type Event = Event;
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
|
||||
@@ -989,7 +985,6 @@ mod tests {
|
||||
(5, 50 * self.balance_factor),
|
||||
(6, 60 * self.balance_factor)
|
||||
],
|
||||
vesting: vec![],
|
||||
}),
|
||||
}.build_storage().unwrap().into()
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
use sp_std::prelude::*;
|
||||
use sp_runtime::{
|
||||
RuntimeDebug, DispatchResult, print,
|
||||
traits::{Zero, One, StaticLookup, Bounded, Saturating},
|
||||
traits::{Zero, One, StaticLookup, Saturating},
|
||||
};
|
||||
use frame_support::{
|
||||
decl_storage, decl_event, ensure, decl_module, decl_error,
|
||||
@@ -894,7 +894,6 @@ impl<T: Trait> Module<T> {
|
||||
MODULE_ID,
|
||||
&who,
|
||||
locked_balance,
|
||||
T::BlockNumber::max_value(),
|
||||
WithdrawReasons::all(),
|
||||
);
|
||||
|
||||
|
||||
@@ -58,19 +58,16 @@ impl frame_system::Trait for Test {
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnNewAccount = ();
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type Event = Event;
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
|
||||
@@ -222,7 +219,6 @@ impl ExtBuilder {
|
||||
(5, 50 * self.balance_factor),
|
||||
(6, 60 * self.balance_factor)
|
||||
],
|
||||
vesting: vec![],
|
||||
}),
|
||||
elections: Some(elections::GenesisConfig::<Test>{
|
||||
members: vec![],
|
||||
@@ -270,7 +266,8 @@ pub(crate) fn create_candidate(i: u64, index: u32) {
|
||||
}
|
||||
|
||||
pub(crate) fn balances(who: &u64) -> (u64, u64) {
|
||||
(Balances::free_balance(who), Balances::reserved_balance(who))
|
||||
let a = Balances::account(who);
|
||||
(a.free, a.reserved)
|
||||
}
|
||||
|
||||
pub(crate) fn locks(who: &u64) -> Vec<u64> {
|
||||
|
||||
@@ -1179,14 +1179,14 @@ fn election_present_when_presenter_is_poor_should_not_work() {
|
||||
|
||||
// -3
|
||||
assert_ok!(Elections::submit_candidacy(Origin::signed(1), 0));
|
||||
assert_eq!(Balances::free_balance(&1), 12);
|
||||
assert_eq!(Balances::free_balance(1), 12);
|
||||
// -2 -5
|
||||
assert_ok!(Elections::set_approvals(Origin::signed(1), vec![true], 0, 0, 15));
|
||||
assert_ok!(Elections::end_block(System::block_number()));
|
||||
|
||||
System::set_block_number(6);
|
||||
assert_eq!(Balances::free_balance(&1), 5);
|
||||
assert_eq!(Balances::reserved_balance(&1), 5);
|
||||
assert_eq!(Balances::free_balance(1), 5);
|
||||
assert_eq!(Balances::reserved_balance(1), 5);
|
||||
if p > 5 {
|
||||
assert_noop!(Elections::present_winner(
|
||||
Origin::signed(1), 1, 10, 0),
|
||||
|
||||
@@ -690,19 +690,16 @@ mod tests {
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type OnNewAccount = ();
|
||||
type Event = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
impl Trait for Test {
|
||||
|
||||
@@ -454,19 +454,16 @@ mod tests {
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
impl pallet_balances::Trait for Runtime {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type OnNewAccount = ();
|
||||
type Event = MetaEvent;
|
||||
type DustRemoval = ();
|
||||
type TransferPayment = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
|
||||
@@ -528,7 +525,6 @@ mod tests {
|
||||
let mut t = frame_system::GenesisConfig::default().build_storage::<Runtime>().unwrap();
|
||||
pallet_balances::GenesisConfig::<Runtime> {
|
||||
balances: vec![(1, 211)],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
let xt = sp_runtime::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(2, 69)));
|
||||
let weight = xt.get_dispatch_info().weight as u64;
|
||||
@@ -552,7 +548,6 @@ mod tests {
|
||||
let mut t = frame_system::GenesisConfig::default().build_storage::<Runtime>().unwrap();
|
||||
pallet_balances::GenesisConfig::<Runtime> {
|
||||
balances: vec![(1, 111 * balance_factor)],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
t.into()
|
||||
}
|
||||
@@ -564,7 +559,7 @@ mod tests {
|
||||
header: Header {
|
||||
parent_hash: [69u8; 32].into(),
|
||||
number: 1,
|
||||
state_root: hex!("c6b01b27df520ba23adb96e7fc032acb7c586ba1b477c6282de43184111f2091").into(),
|
||||
state_root: hex!("a0b84fec49718caf59350dab6ec2993f12db399a7cccdb80f3cf79618ed93bd8").into(),
|
||||
extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(),
|
||||
digest: Digest { logs: vec![], },
|
||||
},
|
||||
@@ -711,7 +706,6 @@ mod tests {
|
||||
id,
|
||||
&1,
|
||||
110,
|
||||
Bounded::max_value(),
|
||||
lock,
|
||||
);
|
||||
let xt = sp_runtime::testing::TestXt(
|
||||
|
||||
@@ -427,10 +427,9 @@ decl_module! {
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
|
||||
pub struct BalanceLock<Balance, BlockNumber> {
|
||||
pub struct BalanceLock<Balance> {
|
||||
pub id: LockIdentifier,
|
||||
pub amount: Balance,
|
||||
pub until: BlockNumber,
|
||||
pub reasons: WithdrawReasons,
|
||||
}
|
||||
|
||||
@@ -459,7 +458,7 @@ decl_storage! {
|
||||
|
||||
/// Any liquidity locks on some account balances.
|
||||
pub Locks get(fn locks):
|
||||
map hasher(blake2_256) T::AccountId => Vec<BalanceLock<T::Balance, T::BlockNumber>>;
|
||||
map hasher(blake2_256) T::AccountId => Vec<BalanceLock<T::Balance>>;
|
||||
|
||||
/// The identity of the asset which is the one that is designated for the chain's staking system.
|
||||
pub StakingAssetId get(fn staking_asset_id) config(): T::AssetId;
|
||||
@@ -796,10 +795,8 @@ impl<T: Trait> Module<T> {
|
||||
if locks.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let now = <frame_system::Module<T>>::block_number();
|
||||
if Self::locks(who)
|
||||
.into_iter()
|
||||
.all(|l| now >= l.until || new_balance >= l.amount || !l.reasons.intersects(reasons))
|
||||
.into_iter().all(|l| new_balance >= l.amount || !l.reasons.intersects(reasons))
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -825,14 +822,11 @@ impl<T: Trait> Module<T> {
|
||||
id: LockIdentifier,
|
||||
who: &T::AccountId,
|
||||
amount: T::Balance,
|
||||
until: T::BlockNumber,
|
||||
reasons: WithdrawReasons,
|
||||
) {
|
||||
let now = <frame_system::Module<T>>::block_number();
|
||||
let mut new_lock = Some(BalanceLock {
|
||||
id,
|
||||
amount,
|
||||
until,
|
||||
reasons,
|
||||
});
|
||||
let mut locks = <Module<T>>::locks(who)
|
||||
@@ -840,10 +834,8 @@ impl<T: Trait> Module<T> {
|
||||
.filter_map(|l| {
|
||||
if l.id == id {
|
||||
new_lock.take()
|
||||
} else if l.until > now {
|
||||
Some(l)
|
||||
} else {
|
||||
None
|
||||
Some(l)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -857,14 +849,11 @@ impl<T: Trait> Module<T> {
|
||||
id: LockIdentifier,
|
||||
who: &T::AccountId,
|
||||
amount: T::Balance,
|
||||
until: T::BlockNumber,
|
||||
reasons: WithdrawReasons,
|
||||
) {
|
||||
let now = <frame_system::Module<T>>::block_number();
|
||||
let mut new_lock = Some(BalanceLock {
|
||||
id,
|
||||
amount,
|
||||
until,
|
||||
reasons,
|
||||
});
|
||||
let mut locks = <Module<T>>::locks(who)
|
||||
@@ -874,13 +863,10 @@ impl<T: Trait> Module<T> {
|
||||
new_lock.take().map(|nl| BalanceLock {
|
||||
id: l.id,
|
||||
amount: l.amount.max(nl.amount),
|
||||
until: l.until.max(nl.until),
|
||||
reasons: l.reasons | nl.reasons,
|
||||
})
|
||||
} else if l.until > now {
|
||||
Some(l)
|
||||
} else {
|
||||
None
|
||||
Some(l)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -891,11 +877,8 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
|
||||
fn remove_lock(id: LockIdentifier, who: &T::AccountId) {
|
||||
let now = <frame_system::Module<T>>::block_number();
|
||||
let locks = <Module<T>>::locks(who)
|
||||
.into_iter()
|
||||
.filter_map(|l| if l.until > now && l.id != id { Some(l) } else { None })
|
||||
.collect::<Vec<_>>();
|
||||
let mut locks = <Module<T>>::locks(who);
|
||||
locks.retain(|l| l.id != id);
|
||||
<Locks<T>>::insert(who, locks);
|
||||
}
|
||||
}
|
||||
@@ -1339,20 +1322,18 @@ where
|
||||
id: LockIdentifier,
|
||||
who: &T::AccountId,
|
||||
amount: T::Balance,
|
||||
until: T::BlockNumber,
|
||||
reasons: WithdrawReasons,
|
||||
) {
|
||||
<Module<T>>::set_lock(id, who, amount, until, reasons)
|
||||
<Module<T>>::set_lock(id, who, amount, reasons)
|
||||
}
|
||||
|
||||
fn extend_lock(
|
||||
id: LockIdentifier,
|
||||
who: &T::AccountId,
|
||||
amount: T::Balance,
|
||||
until: T::BlockNumber,
|
||||
reasons: WithdrawReasons,
|
||||
) {
|
||||
<Module<T>>::extend_lock(id, who, amount, until, reasons)
|
||||
<Module<T>>::extend_lock(id, who, amount, reasons)
|
||||
}
|
||||
|
||||
fn remove_lock(id: LockIdentifier, who: &T::AccountId) {
|
||||
|
||||
@@ -925,19 +925,16 @@ mod tests {
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type OnNewAccount = ();
|
||||
type Event = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
parameter_types! {
|
||||
@@ -981,7 +978,6 @@ mod tests {
|
||||
(20, 100),
|
||||
(30, 100),
|
||||
],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
t.into()
|
||||
}
|
||||
|
||||
@@ -288,19 +288,16 @@ mod tests {
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type OnNewAccount = ();
|
||||
type Event = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
parameter_types! {
|
||||
@@ -334,7 +331,6 @@ mod tests {
|
||||
(1, 10),
|
||||
(2, 10),
|
||||
],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
t.into()
|
||||
}
|
||||
@@ -359,9 +355,9 @@ mod tests {
|
||||
);
|
||||
|
||||
assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec()));
|
||||
assert_eq!(Balances::reserved_balance(&2), 2);
|
||||
assert_eq!(Balances::reserved_balance(2), 2);
|
||||
assert_ok!(Nicks::force_name(Origin::signed(1), 2, b"Dr. David Brubeck, III".to_vec()));
|
||||
assert_eq!(Balances::reserved_balance(&2), 2);
|
||||
assert_eq!(Balances::reserved_balance(2), 2);
|
||||
assert_eq!(<NameOf<Test>>::get(2).unwrap(), (b"Dr. David Brubeck, III".to_vec(), 2));
|
||||
});
|
||||
}
|
||||
@@ -370,18 +366,18 @@ mod tests {
|
||||
fn normal_operation_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Nicks::set_name(Origin::signed(1), b"Gav".to_vec()));
|
||||
assert_eq!(Balances::reserved_balance(&1), 2);
|
||||
assert_eq!(Balances::free_balance(&1), 8);
|
||||
assert_eq!(Balances::reserved_balance(1), 2);
|
||||
assert_eq!(Balances::free_balance(1), 8);
|
||||
assert_eq!(<NameOf<Test>>::get(1).unwrap().0, b"Gav".to_vec());
|
||||
|
||||
assert_ok!(Nicks::set_name(Origin::signed(1), b"Gavin".to_vec()));
|
||||
assert_eq!(Balances::reserved_balance(&1), 2);
|
||||
assert_eq!(Balances::free_balance(&1), 8);
|
||||
assert_eq!(Balances::reserved_balance(1), 2);
|
||||
assert_eq!(Balances::free_balance(1), 8);
|
||||
assert_eq!(<NameOf<Test>>::get(1).unwrap().0, b"Gavin".to_vec());
|
||||
|
||||
assert_ok!(Nicks::clear_name(Origin::signed(1)));
|
||||
assert_eq!(Balances::reserved_balance(&1), 0);
|
||||
assert_eq!(Balances::free_balance(&1), 10);
|
||||
assert_eq!(Balances::reserved_balance(1), 0);
|
||||
assert_eq!(Balances::free_balance(1), 10);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -81,20 +81,17 @@ impl frame_system::Trait for Test {
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u128;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = (System, Recovery);
|
||||
type OnNewAccount = ();
|
||||
type Event = TestEvent;
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
|
||||
@@ -126,7 +123,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
||||
pallet_balances::GenesisConfig::<Test> {
|
||||
balances: vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100)],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
t.into()
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ fn basic_setup_works() {
|
||||
assert_eq!(Recovery::active_recovery(&1, &2), None);
|
||||
assert_eq!(Recovery::recovery_config(&1), None);
|
||||
// Everyone should have starting balance of 100
|
||||
assert_eq!(Balances::free_balance(&1), 100);
|
||||
assert_eq!(Balances::free_balance(1), 100);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ fn initiate_recovery_handles_basic_errors() {
|
||||
assert_ok!(Recovery::initiate_recovery(Origin::signed(1), 5));
|
||||
assert_noop!(Recovery::initiate_recovery(Origin::signed(1), 5), Error::<Test>::AlreadyStarted);
|
||||
// No double deposit
|
||||
assert_eq!(Balances::reserved_balance(&1), 10);
|
||||
assert_eq!(Balances::reserved_balance(1), 10);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ fn initiate_recovery_works() {
|
||||
// Recovery can be initiated
|
||||
assert_ok!(Recovery::initiate_recovery(Origin::signed(1), 5));
|
||||
// Deposit is reserved
|
||||
assert_eq!(Balances::reserved_balance(&1), 10);
|
||||
assert_eq!(Balances::reserved_balance(1), 10);
|
||||
// Recovery status object is created correctly
|
||||
let recovery_status = ActiveRecovery {
|
||||
created: 1,
|
||||
|
||||
@@ -47,7 +47,6 @@ parameter_types! {
|
||||
pub const AvailableBlockRatio: Perbill = Perbill::one();
|
||||
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
ord_parameter_types! {
|
||||
@@ -76,14 +75,12 @@ impl frame_system::Trait for Test {
|
||||
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type OnNewAccount = ();
|
||||
type Event = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
|
||||
@@ -144,7 +141,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
|
||||
(40, 500_000),
|
||||
(99, 1),
|
||||
],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
GenesisConfig::<Test>{
|
||||
pool: vec![
|
||||
|
||||
@@ -30,8 +30,8 @@ type Balances = pallet_balances::Module<Test>;
|
||||
fn query_membership_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(ScoredPool::members(), vec![20, 40]);
|
||||
assert_eq!(Balances::reserved_balance(&31), CandidateDeposit::get());
|
||||
assert_eq!(Balances::reserved_balance(&40), CandidateDeposit::get());
|
||||
assert_eq!(Balances::reserved_balance(31), CandidateDeposit::get());
|
||||
assert_eq!(Balances::reserved_balance(40), CandidateDeposit::get());
|
||||
assert_eq!(MEMBERS.with(|m| m.borrow().clone()), vec![20, 40]);
|
||||
});
|
||||
}
|
||||
@@ -61,7 +61,7 @@ fn submit_candidacy_works() {
|
||||
assert_eq!(fetch_from_pool(15), Some((who, None)));
|
||||
|
||||
// then
|
||||
assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get());
|
||||
assert_eq!(Balances::reserved_balance(who), CandidateDeposit::get());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ fn kicking_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// given
|
||||
let who = 40;
|
||||
assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get());
|
||||
assert_eq!(Balances::reserved_balance(who), CandidateDeposit::get());
|
||||
assert_eq!(find_in_pool(who), Some(0));
|
||||
|
||||
// when
|
||||
@@ -128,7 +128,7 @@ fn kicking_works() {
|
||||
assert_eq!(find_in_pool(who), None);
|
||||
assert_eq!(ScoredPool::members(), vec![20, 31]);
|
||||
assert_eq!(MEMBERS.with(|m| m.borrow().clone()), ScoredPool::members());
|
||||
assert_eq!(Balances::reserved_balance(&who), 0); // deposit must have been returned
|
||||
assert_eq!(Balances::reserved_balance(who), 0); // deposit must have been returned
|
||||
});
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ fn withdraw_scored_candidacy_must_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// given
|
||||
let who = 40;
|
||||
assert_eq!(Balances::reserved_balance(&who), CandidateDeposit::get());
|
||||
assert_eq!(Balances::reserved_balance(who), CandidateDeposit::get());
|
||||
|
||||
// when
|
||||
let index = find_in_pool(who).expect("entity must be in pool") as u32;
|
||||
@@ -255,7 +255,7 @@ fn withdraw_scored_candidacy_must_work() {
|
||||
// then
|
||||
assert_eq!(fetch_from_pool(who), None);
|
||||
assert_eq!(ScoredPool::members(), vec![20, 31]);
|
||||
assert_eq!(Balances::reserved_balance(&who), 0);
|
||||
assert_eq!(Balances::reserved_balance(who), 0);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ use frame_support::weights::SimpleDispatchInfo;
|
||||
use sp_runtime::traits::{Convert, Zero, Member, OpaqueKeys};
|
||||
use sp_staking::SessionIndex;
|
||||
use frame_support::{dispatch, ConsensusEngineId, decl_module, decl_event, decl_storage, decl_error};
|
||||
use frame_support::{ensure, traits::{OnFreeBalanceZero, Get, FindAuthor, ValidatorRegistration}, Parameter};
|
||||
use frame_support::{ensure, traits::{OnReapAccount, Get, FindAuthor, ValidatorRegistration}, Parameter};
|
||||
use frame_system::{self as system, ensure_signed};
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -676,8 +676,8 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> OnFreeBalanceZero<T::ValidatorId> for Module<T> {
|
||||
fn on_free_balance_zero(who: &T::ValidatorId) {
|
||||
impl<T: Trait> OnReapAccount<T::ValidatorId> for Module<T> {
|
||||
fn on_reap_account(who: &T::ValidatorId) {
|
||||
Self::prune_dead_keys(who);
|
||||
}
|
||||
}
|
||||
@@ -754,7 +754,7 @@ mod tests {
|
||||
let id = DUMMY;
|
||||
assert_eq!(Session::key_owner(id, UintAuthorityId(1).get_raw(id)), Some(1));
|
||||
|
||||
Session::on_free_balance_zero(&1);
|
||||
Session::on_reap_account(&1);
|
||||
assert_eq!(Session::load_keys(&1), None);
|
||||
assert_eq!(Session::key_owner(id, UintAuthorityId(1).get_raw(id)), None);
|
||||
})
|
||||
|
||||
@@ -51,7 +51,6 @@ parameter_types! {
|
||||
pub const AvailableBlockRatio: Perbill = Perbill::one();
|
||||
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
|
||||
@@ -81,13 +80,11 @@ impl frame_system::Trait for Test {
|
||||
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnNewAccount = ();
|
||||
type Event = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type OnReapAccount = System;
|
||||
}
|
||||
@@ -146,7 +143,6 @@ impl EnvBuilder {
|
||||
self.balances.push((Society::account_id(), self.balance.max(self.pot)));
|
||||
pallet_balances::GenesisConfig::<Test> {
|
||||
balances: self.balances,
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
GenesisConfig::<Test>{
|
||||
members: self.members,
|
||||
|
||||
@@ -261,7 +261,7 @@ use frame_support::{
|
||||
decl_module, decl_event, decl_storage, ensure, decl_error,
|
||||
weights::SimpleDispatchInfo,
|
||||
traits::{
|
||||
Currency, OnFreeBalanceZero, LockIdentifier, LockableCurrency,
|
||||
Currency, LockIdentifier, LockableCurrency,
|
||||
WithdrawReasons, OnUnbalanced, Imbalance, Get, Time
|
||||
}
|
||||
};
|
||||
@@ -284,6 +284,7 @@ use sp_runtime::{Serialize, Deserialize};
|
||||
use frame_system::{self as system, ensure_signed, ensure_root};
|
||||
|
||||
use sp_phragmen::ExtendedBalance;
|
||||
use frame_support::traits::OnReapAccount;
|
||||
|
||||
const DEFAULT_MINIMUM_VALIDATOR_COUNT: u32 = 4;
|
||||
const MAX_NOMINATIONS: usize = 16;
|
||||
@@ -1286,7 +1287,6 @@ impl<T: Trait> Module<T> {
|
||||
STAKING_ID,
|
||||
&ledger.stash,
|
||||
ledger.total,
|
||||
T::BlockNumber::max_value(),
|
||||
WithdrawReasons::all(),
|
||||
);
|
||||
<Ledger<T>>::insert(controller, ledger);
|
||||
@@ -1682,8 +1682,8 @@ impl<T: Trait> SessionManager<T::AccountId, Exposure<T::AccountId, BalanceOf<T>>
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> OnFreeBalanceZero<T::AccountId> for Module<T> {
|
||||
fn on_free_balance_zero(stash: &T::AccountId) {
|
||||
impl<T: Trait> OnReapAccount<T::AccountId> for Module<T> {
|
||||
fn on_reap_account(stash: &T::AccountId) {
|
||||
Self::ensure_storage_upgraded();
|
||||
Self::kill_stash(stash);
|
||||
}
|
||||
|
||||
@@ -140,19 +140,16 @@ impl frame_system::Trait for Test {
|
||||
type ModuleToIndex = ();
|
||||
}
|
||||
parameter_types! {
|
||||
pub const TransferFee: Balance = 0;
|
||||
pub const CreationFee: Balance = 0;
|
||||
}
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = Balance;
|
||||
type OnFreeBalanceZero = Staking;
|
||||
type OnReapAccount = System;
|
||||
type OnReapAccount = (System, Staking);
|
||||
type OnNewAccount = ();
|
||||
type Event = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
parameter_types! {
|
||||
@@ -323,7 +320,6 @@ impl ExtBuilder {
|
||||
// This allow us to have a total_payout different from 0.
|
||||
(999, 1_000_000_000_000),
|
||||
],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut storage);
|
||||
|
||||
let stake_21 = if self.fair { 1000 } else { 2000 };
|
||||
|
||||
@@ -110,8 +110,8 @@ fn basic_setup_works() {
|
||||
assert_eq!(Staking::current_era(), 0);
|
||||
|
||||
// Account 10 has `balance_factor` free balance
|
||||
assert_eq!(Balances::free_balance(&10), 1);
|
||||
assert_eq!(Balances::free_balance(&10), 1);
|
||||
assert_eq!(Balances::free_balance(10), 1);
|
||||
assert_eq!(Balances::free_balance(10), 1);
|
||||
|
||||
// New era is not being forced
|
||||
assert_eq!(Staking::force_era(), Forcing::NotForcing);
|
||||
@@ -759,7 +759,7 @@ fn cannot_transfer_staked_balance() {
|
||||
// Confirm account 11 is stashed
|
||||
assert_eq!(Staking::bonded(&11), Some(10));
|
||||
// Confirm account 11 has some free balance
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
// Confirm account 11 (via controller 10) is totally staked
|
||||
assert_eq!(Staking::stakers(&11).total, 1000);
|
||||
// Confirm account 11 cannot transfer as a result
|
||||
@@ -788,7 +788,7 @@ fn cannot_transfer_staked_balance_2() {
|
||||
// Confirm account 21 is stashed
|
||||
assert_eq!(Staking::bonded(&21), Some(20));
|
||||
// Confirm account 21 has some free balance
|
||||
assert_eq!(Balances::free_balance(&21), 2000);
|
||||
assert_eq!(Balances::free_balance(21), 2000);
|
||||
// Confirm account 21 (via controller 20) is totally staked
|
||||
assert_eq!(Staking::stakers(&21).total, 1000);
|
||||
// Confirm account 21 can transfer at most 1000
|
||||
@@ -811,7 +811,7 @@ fn cannot_reserve_staked_balance() {
|
||||
// Confirm account 11 is stashed
|
||||
assert_eq!(Staking::bonded(&11), Some(10));
|
||||
// Confirm account 11 has some free balance
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
// Confirm account 11 (via controller 10) is totally staked
|
||||
assert_eq!(Staking::stakers(&11).own, 1000);
|
||||
// Confirm account 11 cannot transfer as a result
|
||||
@@ -838,9 +838,9 @@ fn reward_destination_works() {
|
||||
// Check that account 11 is a validator
|
||||
assert!(Staking::current_elected().contains(&11));
|
||||
// Check the balance of the validator account
|
||||
assert_eq!(Balances::free_balance(&10), 1);
|
||||
assert_eq!(Balances::free_balance(10), 1);
|
||||
// Check the balance of the stash account
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
// Check how much is at stake
|
||||
assert_eq!(Staking::ledger(&10), Some(StakingLedger {
|
||||
stash: 11,
|
||||
@@ -859,7 +859,7 @@ fn reward_destination_works() {
|
||||
// Check that RewardDestination is Staked (default)
|
||||
assert_eq!(Staking::payee(&11), RewardDestination::Staked);
|
||||
// Check that reward went to the stash account of validator
|
||||
assert_eq!(Balances::free_balance(&11), 1000 + total_payout_0);
|
||||
assert_eq!(Balances::free_balance(11), 1000 + total_payout_0);
|
||||
// Check that amount at stake increased accordingly
|
||||
assert_eq!(Staking::ledger(&10), Some(StakingLedger {
|
||||
stash: 11,
|
||||
@@ -881,7 +881,7 @@ fn reward_destination_works() {
|
||||
// Check that RewardDestination is Stash
|
||||
assert_eq!(Staking::payee(&11), RewardDestination::Stash);
|
||||
// Check that reward went to the stash account
|
||||
assert_eq!(Balances::free_balance(&11), 1000 + total_payout_0 + total_payout_1);
|
||||
assert_eq!(Balances::free_balance(11), 1000 + total_payout_0 + total_payout_1);
|
||||
// Record this value
|
||||
let recorded_stash_balance = 1000 + total_payout_0 + total_payout_1;
|
||||
// Check that amount at stake is NOT increased
|
||||
@@ -896,7 +896,7 @@ fn reward_destination_works() {
|
||||
<Payee<Test>>::insert(&11, RewardDestination::Controller);
|
||||
|
||||
// Check controller balance
|
||||
assert_eq!(Balances::free_balance(&10), 1);
|
||||
assert_eq!(Balances::free_balance(10), 1);
|
||||
|
||||
// Compute total payout now for whole duration as other parameter won't change
|
||||
let total_payout_2 = current_total_payout_for_duration(3000);
|
||||
@@ -908,7 +908,7 @@ fn reward_destination_works() {
|
||||
// Check that RewardDestination is Controller
|
||||
assert_eq!(Staking::payee(&11), RewardDestination::Controller);
|
||||
// Check that reward went to the controller account
|
||||
assert_eq!(Balances::free_balance(&10), 1 + total_payout_2);
|
||||
assert_eq!(Balances::free_balance(10), 1 + total_payout_2);
|
||||
// Check that amount at stake is NOT increased
|
||||
assert_eq!(Staking::ledger(&10), Some(StakingLedger {
|
||||
stash: 11,
|
||||
@@ -917,7 +917,7 @@ fn reward_destination_works() {
|
||||
unlocking: vec![],
|
||||
}));
|
||||
// Check that amount in staked account is NOT increased.
|
||||
assert_eq!(Balances::free_balance(&11), recorded_stash_balance);
|
||||
assert_eq!(Balances::free_balance(11), recorded_stash_balance);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1422,9 +1422,9 @@ fn on_free_balance_zero_stash_removes_validator() {
|
||||
// Tests that storage items are untouched when controller is empty
|
||||
ExtBuilder::default().existential_deposit(10).build().execute_with(|| {
|
||||
// Check the balance of the validator account
|
||||
assert_eq!(Balances::free_balance(&10), 256);
|
||||
assert_eq!(Balances::free_balance(10), 256);
|
||||
// Check the balance of the stash account
|
||||
assert_eq!(Balances::free_balance(&11), 256000);
|
||||
assert_eq!(Balances::free_balance(11), 256000);
|
||||
// Check these two accounts are bonded
|
||||
assert_eq!(Staking::bonded(&11), Some(10));
|
||||
|
||||
@@ -1442,7 +1442,7 @@ fn on_free_balance_zero_stash_removes_validator() {
|
||||
let _ = Balances::slash(&10, u64::max_value());
|
||||
|
||||
// Check the balance of the stash account has not been touched
|
||||
assert_eq!(Balances::free_balance(&11), 256000);
|
||||
assert_eq!(Balances::free_balance(11), 256000);
|
||||
// Check these two accounts are still bonded
|
||||
assert_eq!(Staking::bonded(&11), Some(10));
|
||||
|
||||
@@ -1476,9 +1476,9 @@ fn on_free_balance_zero_stash_removes_nominator() {
|
||||
// Check that account 10 is a nominator
|
||||
assert!(<Nominators<Test>>::exists(11));
|
||||
// Check the balance of the nominator account
|
||||
assert_eq!(Balances::free_balance(&10), 256);
|
||||
assert_eq!(Balances::free_balance(10), 256);
|
||||
// Check the balance of the stash account
|
||||
assert_eq!(Balances::free_balance(&11), 256000);
|
||||
assert_eq!(Balances::free_balance(11), 256000);
|
||||
|
||||
// Set payee information
|
||||
assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Stash));
|
||||
@@ -1495,7 +1495,7 @@ fn on_free_balance_zero_stash_removes_nominator() {
|
||||
assert_eq!(Balances::total_balance(&10), 0);
|
||||
|
||||
// Check the balance of the stash account has not been touched
|
||||
assert_eq!(Balances::free_balance(&11), 256000);
|
||||
assert_eq!(Balances::free_balance(11), 256000);
|
||||
// Check these two accounts are still bonded
|
||||
assert_eq!(Staking::bonded(&11), Some(10));
|
||||
|
||||
@@ -1689,9 +1689,9 @@ fn bond_with_little_staked_value_bounded_by_slot_stake() {
|
||||
assert_eq!(Staking::slot_stake(), 1);
|
||||
|
||||
// Old ones are rewarded.
|
||||
assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_0 / 3);
|
||||
assert_eq!(Balances::free_balance(10), init_balance_10 + total_payout_0 / 3);
|
||||
// no rewards paid to 2. This was initial election.
|
||||
assert_eq!(Balances::free_balance(&2), init_balance_2);
|
||||
assert_eq!(Balances::free_balance(2), init_balance_2);
|
||||
|
||||
let total_payout_1 = current_total_payout_for_duration(3000);
|
||||
assert!(total_payout_1 > 100); // Test is meaningfull if reward something
|
||||
@@ -1701,7 +1701,7 @@ fn bond_with_little_staked_value_bounded_by_slot_stake() {
|
||||
assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]);
|
||||
assert_eq!(Staking::slot_stake(), 1);
|
||||
|
||||
assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_1 / 3);
|
||||
assert_eq!(Balances::free_balance(2), init_balance_2 + total_payout_1 / 3);
|
||||
assert_eq!(
|
||||
Balances::free_balance(&10),
|
||||
init_balance_10 + total_payout_0 / 3 + total_payout_1 / 3,
|
||||
@@ -2008,7 +2008,7 @@ fn slashing_performed_according_exposure() {
|
||||
);
|
||||
|
||||
// The stash account should be slashed for 250 (50% of 500).
|
||||
assert_eq!(Balances::free_balance(&11), 1000 - 250);
|
||||
assert_eq!(Balances::free_balance(11), 1000 - 250);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2102,8 +2102,8 @@ fn reporters_receive_their_slice() {
|
||||
// 50% * (10% * initial_balance / 2)
|
||||
let reward = (initial_balance / 20) / 2;
|
||||
let reward_each = reward / 2; // split into two pieces.
|
||||
assert_eq!(Balances::free_balance(&1), 10 + reward_each);
|
||||
assert_eq!(Balances::free_balance(&2), 20 + reward_each);
|
||||
assert_eq!(Balances::free_balance(1), 10 + reward_each);
|
||||
assert_eq!(Balances::free_balance(2), 20 + reward_each);
|
||||
assert_ledger_consistent(11);
|
||||
});
|
||||
}
|
||||
@@ -2132,7 +2132,7 @@ fn subsequent_reports_in_same_span_pay_out_less() {
|
||||
// F1 * (reward_proportion * slash - 0)
|
||||
// 50% * (10% * initial_balance * 20%)
|
||||
let reward = (initial_balance / 5) / 20;
|
||||
assert_eq!(Balances::free_balance(&1), 10 + reward);
|
||||
assert_eq!(Balances::free_balance(1), 10 + reward);
|
||||
|
||||
on_offence_now(
|
||||
&[OffenceDetails {
|
||||
@@ -2150,7 +2150,7 @@ fn subsequent_reports_in_same_span_pay_out_less() {
|
||||
// F1 * (reward_proportion * slash - prior_payout)
|
||||
// 50% * (10% * (initial_balance / 2) - prior_payout)
|
||||
let reward = ((initial_balance / 20) - prior_payout) / 2;
|
||||
assert_eq!(Balances::free_balance(&1), 10 + prior_payout + reward);
|
||||
assert_eq!(Balances::free_balance(1), 10 + prior_payout + reward);
|
||||
assert_ledger_consistent(11);
|
||||
});
|
||||
}
|
||||
@@ -2159,8 +2159,8 @@ fn subsequent_reports_in_same_span_pay_out_less() {
|
||||
fn invulnerables_are_not_slashed() {
|
||||
// For invulnerable validators no slashing is performed.
|
||||
ExtBuilder::default().invulnerables(vec![11]).build().execute_with(|| {
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(&21), 2000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
assert_eq!(Balances::free_balance(21), 2000);
|
||||
|
||||
let exposure = Staking::stakers(&21);
|
||||
let initial_balance = Staking::slashable_balance_of(&21);
|
||||
@@ -2183,9 +2183,9 @@ fn invulnerables_are_not_slashed() {
|
||||
);
|
||||
|
||||
// The validator 11 hasn't been slashed, but 21 has been.
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
// 2000 - (0.2 * initial_balance)
|
||||
assert_eq!(Balances::free_balance(&21), 2000 - (2 * initial_balance / 10));
|
||||
assert_eq!(Balances::free_balance(21), 2000 - (2 * initial_balance / 10));
|
||||
|
||||
// ensure that nominators were slashed as well.
|
||||
for (initial_balance, other) in nominator_balances.into_iter().zip(exposure.others) {
|
||||
@@ -2203,7 +2203,7 @@ fn invulnerables_are_not_slashed() {
|
||||
fn dont_slash_if_fraction_is_zero() {
|
||||
// Don't slash if the fraction is zero.
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
|
||||
on_offence_now(
|
||||
&[OffenceDetails {
|
||||
@@ -2217,7 +2217,7 @@ fn dont_slash_if_fraction_is_zero() {
|
||||
);
|
||||
|
||||
// The validator hasn't been slashed. The new era is not forced.
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
assert_ledger_consistent(11);
|
||||
});
|
||||
}
|
||||
@@ -2225,7 +2225,7 @@ fn dont_slash_if_fraction_is_zero() {
|
||||
#[test]
|
||||
fn only_slash_for_max_in_era() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
|
||||
on_offence_now(
|
||||
&[
|
||||
@@ -2238,7 +2238,7 @@ fn only_slash_for_max_in_era() {
|
||||
);
|
||||
|
||||
// The validator has been slashed and has been force-chilled.
|
||||
assert_eq!(Balances::free_balance(&11), 500);
|
||||
assert_eq!(Balances::free_balance(11), 500);
|
||||
assert_eq!(Staking::force_era(), Forcing::ForceNew);
|
||||
|
||||
on_offence_now(
|
||||
@@ -2252,7 +2252,7 @@ fn only_slash_for_max_in_era() {
|
||||
);
|
||||
|
||||
// The validator has not been slashed additionally.
|
||||
assert_eq!(Balances::free_balance(&11), 500);
|
||||
assert_eq!(Balances::free_balance(11), 500);
|
||||
|
||||
on_offence_now(
|
||||
&[
|
||||
@@ -2265,7 +2265,7 @@ fn only_slash_for_max_in_era() {
|
||||
);
|
||||
|
||||
// The validator got slashed 10% more.
|
||||
assert_eq!(Balances::free_balance(&11), 400);
|
||||
assert_eq!(Balances::free_balance(11), 400);
|
||||
assert_ledger_consistent(11);
|
||||
})
|
||||
}
|
||||
@@ -2273,7 +2273,7 @@ fn only_slash_for_max_in_era() {
|
||||
#[test]
|
||||
fn garbage_collection_after_slashing() {
|
||||
ExtBuilder::default().existential_deposit(1).build().execute_with(|| {
|
||||
assert_eq!(Balances::free_balance(&11), 256_000);
|
||||
assert_eq!(Balances::free_balance(11), 256_000);
|
||||
|
||||
on_offence_now(
|
||||
&[
|
||||
@@ -2285,7 +2285,7 @@ fn garbage_collection_after_slashing() {
|
||||
&[Perbill::from_percent(10)],
|
||||
);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 256_000 - 25_600);
|
||||
assert_eq!(Balances::free_balance(11), 256_000 - 25_600);
|
||||
assert!(<Staking as crate::Store>::SlashingSpans::get(&11).is_some());
|
||||
assert_eq!(<Staking as crate::Store>::SpanSlash::get(&(11, 0)).amount_slashed(), &25_600);
|
||||
|
||||
@@ -2302,7 +2302,7 @@ fn garbage_collection_after_slashing() {
|
||||
// validator and nominator slash in era are garbage-collected by era change,
|
||||
// so we don't test those here.
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 0);
|
||||
assert_eq!(Balances::free_balance(11), 0);
|
||||
assert!(<Staking as crate::Store>::SlashingSpans::get(&11).is_none());
|
||||
assert_eq!(<Staking as crate::Store>::SpanSlash::get(&(11, 0)).amount_slashed(), &0);
|
||||
})
|
||||
@@ -2313,10 +2313,10 @@ fn garbage_collection_on_window_pruning() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
start_era(1);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
|
||||
let exposure = Staking::stakers(&11);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value;
|
||||
|
||||
on_offence_now(
|
||||
@@ -2331,8 +2331,8 @@ fn garbage_collection_on_window_pruning() {
|
||||
|
||||
let now = Staking::current_era();
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 900);
|
||||
assert_eq!(Balances::free_balance(&101), 2000 - (nominated_value / 10));
|
||||
assert_eq!(Balances::free_balance(11), 900);
|
||||
assert_eq!(Balances::free_balance(101), 2000 - (nominated_value / 10));
|
||||
|
||||
assert!(<Staking as crate::Store>::ValidatorSlashInEra::get(&now, &11).is_some());
|
||||
assert!(<Staking as crate::Store>::NominatorSlashInEra::get(&now, &101).is_some());
|
||||
@@ -2357,15 +2357,15 @@ fn slashing_nominators_by_span_max() {
|
||||
start_era(2);
|
||||
start_era(3);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(&21), 2000);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
assert_eq!(Balances::free_balance(21), 2000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
assert_eq!(Staking::slashable_balance_of(&21), 1000);
|
||||
|
||||
|
||||
let exposure_11 = Staking::stakers(&11);
|
||||
let exposure_21 = Staking::stakers(&21);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
let nominated_value_11 = exposure_11.others.iter().find(|o| o.who == 101).unwrap().value;
|
||||
let nominated_value_21 = exposure_21.others.iter().find(|o| o.who == 101).unwrap().value;
|
||||
|
||||
@@ -2380,10 +2380,10 @@ fn slashing_nominators_by_span_max() {
|
||||
2,
|
||||
);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 900);
|
||||
assert_eq!(Balances::free_balance(11), 900);
|
||||
|
||||
let slash_1_amount = Perbill::from_percent(10) * nominated_value_11;
|
||||
assert_eq!(Balances::free_balance(&101), 2000 - slash_1_amount);
|
||||
assert_eq!(Balances::free_balance(101), 2000 - slash_1_amount);
|
||||
|
||||
let expected_spans = vec![
|
||||
slashing::SlashingSpan { index: 1, start: 4, length: None },
|
||||
@@ -2415,14 +2415,14 @@ fn slashing_nominators_by_span_max() {
|
||||
);
|
||||
|
||||
// 11 was not further slashed, but 21 and 101 were.
|
||||
assert_eq!(Balances::free_balance(&11), 900);
|
||||
assert_eq!(Balances::free_balance(&21), 1700);
|
||||
assert_eq!(Balances::free_balance(11), 900);
|
||||
assert_eq!(Balances::free_balance(21), 1700);
|
||||
|
||||
let slash_2_amount = Perbill::from_percent(30) * nominated_value_21;
|
||||
assert!(slash_2_amount > slash_1_amount);
|
||||
|
||||
// only the maximum slash in a single span is taken.
|
||||
assert_eq!(Balances::free_balance(&101), 2000 - slash_2_amount);
|
||||
assert_eq!(Balances::free_balance(101), 2000 - slash_2_amount);
|
||||
|
||||
// third slash: in same era and on same validator as first, higher
|
||||
// in-era value, but lower slash value than slash 2.
|
||||
@@ -2438,15 +2438,15 @@ fn slashing_nominators_by_span_max() {
|
||||
);
|
||||
|
||||
// 11 was further slashed, but 21 and 101 were not.
|
||||
assert_eq!(Balances::free_balance(&11), 800);
|
||||
assert_eq!(Balances::free_balance(&21), 1700);
|
||||
assert_eq!(Balances::free_balance(11), 800);
|
||||
assert_eq!(Balances::free_balance(21), 1700);
|
||||
|
||||
let slash_3_amount = Perbill::from_percent(20) * nominated_value_21;
|
||||
assert!(slash_3_amount < slash_2_amount);
|
||||
assert!(slash_3_amount > slash_1_amount);
|
||||
|
||||
// only the maximum slash in a single span is taken.
|
||||
assert_eq!(Balances::free_balance(&101), 2000 - slash_2_amount);
|
||||
assert_eq!(Balances::free_balance(101), 2000 - slash_2_amount);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2457,7 +2457,7 @@ fn slashes_are_summed_across_spans() {
|
||||
start_era(2);
|
||||
start_era(3);
|
||||
|
||||
assert_eq!(Balances::free_balance(&21), 2000);
|
||||
assert_eq!(Balances::free_balance(21), 2000);
|
||||
assert_eq!(Staking::slashable_balance_of(&21), 1000);
|
||||
|
||||
let get_span = |account| <Staking as crate::Store>::SlashingSpans::get(&account).unwrap();
|
||||
@@ -2478,7 +2478,7 @@ fn slashes_are_summed_across_spans() {
|
||||
];
|
||||
|
||||
assert_eq!(get_span(21).iter().collect::<Vec<_>>(), expected_spans);
|
||||
assert_eq!(Balances::free_balance(&21), 1900);
|
||||
assert_eq!(Balances::free_balance(21), 1900);
|
||||
|
||||
// 21 has been force-chilled. re-signal intent to validate.
|
||||
Staking::validate(Origin::signed(20), Default::default()).unwrap();
|
||||
@@ -2504,7 +2504,7 @@ fn slashes_are_summed_across_spans() {
|
||||
];
|
||||
|
||||
assert_eq!(get_span(21).iter().collect::<Vec<_>>(), expected_spans);
|
||||
assert_eq!(Balances::free_balance(&21), 1810);
|
||||
assert_eq!(Balances::free_balance(21), 1810);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2513,10 +2513,10 @@ fn deferred_slashes_are_deferred() {
|
||||
ExtBuilder::default().slash_defer_duration(2).build().execute_with(|| {
|
||||
start_era(1);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
|
||||
let exposure = Staking::stakers(&11);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value;
|
||||
|
||||
on_offence_now(
|
||||
@@ -2529,25 +2529,25 @@ fn deferred_slashes_are_deferred() {
|
||||
&[Perbill::from_percent(10)],
|
||||
);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
|
||||
start_era(2);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
|
||||
start_era(3);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
|
||||
// at the start of era 4, slashes from era 1 are processed,
|
||||
// after being deferred for at least 2 full eras.
|
||||
start_era(4);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 900);
|
||||
assert_eq!(Balances::free_balance(&101), 2000 - (nominated_value / 10));
|
||||
assert_eq!(Balances::free_balance(11), 900);
|
||||
assert_eq!(Balances::free_balance(101), 2000 - (nominated_value / 10));
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2556,10 +2556,10 @@ fn remove_deferred() {
|
||||
ExtBuilder::default().slash_defer_duration(2).build().execute_with(|| {
|
||||
start_era(1);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
|
||||
let exposure = Staking::stakers(&11);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value;
|
||||
|
||||
on_offence_now(
|
||||
@@ -2572,8 +2572,8 @@ fn remove_deferred() {
|
||||
&[Perbill::from_percent(10)],
|
||||
);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
|
||||
start_era(2);
|
||||
|
||||
@@ -2590,21 +2590,21 @@ fn remove_deferred() {
|
||||
|
||||
Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![0]).unwrap();
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
|
||||
start_era(3);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
|
||||
// at the start of era 4, slashes from era 1 are processed,
|
||||
// after being deferred for at least 2 full eras.
|
||||
start_era(4);
|
||||
|
||||
// the first slash for 10% was cancelled, so no effect.
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
|
||||
start_era(5);
|
||||
|
||||
@@ -2616,8 +2616,8 @@ fn remove_deferred() {
|
||||
let actual_slash = total_slash - initial_slash;
|
||||
|
||||
// 5% slash (15 - 10) processed now.
|
||||
assert_eq!(Balances::free_balance(&11), 950);
|
||||
assert_eq!(Balances::free_balance(&101), 2000 - actual_slash);
|
||||
assert_eq!(Balances::free_balance(11), 950);
|
||||
assert_eq!(Balances::free_balance(101), 2000 - actual_slash);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2626,10 +2626,10 @@ fn remove_multi_deferred() {
|
||||
ExtBuilder::default().slash_defer_duration(2).build().execute_with(|| {
|
||||
start_era(1);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
|
||||
let exposure = Staking::stakers(&11);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
|
||||
on_offence_now(
|
||||
&[
|
||||
@@ -2682,10 +2682,10 @@ fn slash_kicks_validators_not_nominators() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
start_era(1);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
|
||||
let exposure = Staking::stakers(&11);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value;
|
||||
|
||||
on_offence_now(
|
||||
@@ -2698,8 +2698,8 @@ fn slash_kicks_validators_not_nominators() {
|
||||
&[Perbill::from_percent(10)],
|
||||
);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 900);
|
||||
assert_eq!(Balances::free_balance(&101), 2000 - (nominated_value / 10));
|
||||
assert_eq!(Balances::free_balance(11), 900);
|
||||
assert_eq!(Balances::free_balance(101), 2000 - (nominated_value / 10));
|
||||
|
||||
// This is the best way to check that the validator was chilled; `get` will
|
||||
// return default value.
|
||||
@@ -2771,10 +2771,10 @@ fn zero_slash_keeps_nominators() {
|
||||
ExtBuilder::default().build().execute_with(|| {
|
||||
start_era(1);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
|
||||
let exposure = Staking::stakers(&11);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
|
||||
on_offence_now(
|
||||
&[
|
||||
@@ -2786,8 +2786,8 @@ fn zero_slash_keeps_nominators() {
|
||||
&[Perbill::from_percent(0)],
|
||||
);
|
||||
|
||||
assert_eq!(Balances::free_balance(&11), 1000);
|
||||
assert_eq!(Balances::free_balance(&101), 2000);
|
||||
assert_eq!(Balances::free_balance(11), 1000);
|
||||
assert_eq!(Balances::free_balance(101), 2000);
|
||||
|
||||
// This is the best way to check that the validator was chilled; `get` will
|
||||
// return default value.
|
||||
|
||||
@@ -67,7 +67,8 @@ pub mod traits;
|
||||
pub mod weights;
|
||||
|
||||
pub use self::hash::{
|
||||
Twox256, Twox128, Blake2_256, Blake2_128, Twox64Concat, Blake2_128Concat, Hashable
|
||||
Twox256, Twox128, Blake2_256, Blake2_128, Twox64Concat, Blake2_128Concat, Hashable,
|
||||
StorageHasher
|
||||
};
|
||||
pub use self::storage::{
|
||||
StorageValue, StorageMap, StorageLinkedMap, StorageDoubleMap, StoragePrefixedMap
|
||||
|
||||
@@ -64,13 +64,6 @@ pub trait Contains<T: Ord> {
|
||||
fn count() -> usize { Self::sorted_members().len() }
|
||||
}
|
||||
|
||||
/// The account with the given id was killed.
|
||||
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||
pub trait OnFreeBalanceZero<AccountId> {
|
||||
/// The account with the given id was killed.
|
||||
fn on_free_balance_zero(who: &AccountId);
|
||||
}
|
||||
|
||||
/// The account with the given id was reaped.
|
||||
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||
pub trait OnReapAccount<AccountId> {
|
||||
@@ -84,6 +77,12 @@ pub enum UpdateBalanceOutcome {
|
||||
Updated,
|
||||
/// The update led to killing the account.
|
||||
AccountKilled,
|
||||
/// Free balance became zero as a result of this update.
|
||||
FreeBalanceZero,
|
||||
/// Reserved balance became zero as a result of this update.
|
||||
ReservedBalanceZero,
|
||||
/// The account started and ended non-existent.
|
||||
StillDead,
|
||||
}
|
||||
|
||||
/// A trait for finding the author of a block header based on the `PreRuntime` digests contained
|
||||
@@ -376,9 +375,7 @@ pub trait Currency<AccountId> {
|
||||
/// This is the only balance that matters in terms of most operations on tokens. It alone
|
||||
/// is used to determine the balance when in the contract execution environment. When this
|
||||
/// balance falls below the value of `ExistentialDeposit`, then the 'current account' is
|
||||
/// deleted: specifically `FreeBalance`. Further, the `OnFreeBalanceZero` callback
|
||||
/// is invoked, giving a chance to external modules to clean up data associated with
|
||||
/// the deleted account.
|
||||
/// deleted: specifically `FreeBalance`.
|
||||
///
|
||||
/// `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets
|
||||
/// collapsed to zero if it ever becomes less than `ExistentialDeposit`.
|
||||
@@ -581,7 +578,6 @@ pub trait LockableCurrency<AccountId>: Currency<AccountId> {
|
||||
id: LockIdentifier,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
until: Self::Moment,
|
||||
reasons: WithdrawReasons,
|
||||
);
|
||||
|
||||
@@ -592,13 +588,11 @@ pub trait LockableCurrency<AccountId>: Currency<AccountId> {
|
||||
/// applies the most severe constraints of the two, while `set_lock` replaces the lock
|
||||
/// with the new parameters. As in, `extend_lock` will set:
|
||||
/// - maximum `amount`
|
||||
/// - farthest duration (`until`)
|
||||
/// - bitwise mask of all `reasons`
|
||||
fn extend_lock(
|
||||
id: LockIdentifier,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
until: Self::Moment,
|
||||
reasons: WithdrawReasons,
|
||||
);
|
||||
|
||||
@@ -609,13 +603,17 @@ pub trait LockableCurrency<AccountId>: Currency<AccountId> {
|
||||
);
|
||||
}
|
||||
|
||||
/// A currency whose accounts can have balances which vest over time.
|
||||
pub trait VestingCurrency<AccountId>: Currency<AccountId> {
|
||||
/// A vesting schedule over a currency. This allows a particular currency to have vesting limits
|
||||
/// applied to it.
|
||||
pub trait VestingSchedule<AccountId> {
|
||||
/// The quantity used to denote time; usually just a `BlockNumber`.
|
||||
type Moment;
|
||||
|
||||
/// The currency that this schedule applies to.
|
||||
type Currency: Currency<AccountId>;
|
||||
|
||||
/// Get the amount that is currently being vested and cannot be transferred out of this account.
|
||||
fn vesting_balance(who: &AccountId) -> Self::Balance;
|
||||
fn vesting_balance(who: &AccountId) -> <Self::Currency as Currency<AccountId>>::Balance;
|
||||
|
||||
/// Adds a vesting schedule to a given account.
|
||||
///
|
||||
@@ -623,8 +621,8 @@ pub trait VestingCurrency<AccountId>: Currency<AccountId> {
|
||||
/// and nothing is updated.
|
||||
fn add_vesting_schedule(
|
||||
who: &AccountId,
|
||||
locked: Self::Balance,
|
||||
per_block: Self::Balance,
|
||||
locked: <Self::Currency as Currency<AccountId>>::Balance,
|
||||
per_block: <Self::Currency as Currency<AccountId>>::Balance,
|
||||
starting_block: Self::Moment,
|
||||
) -> DispatchResult;
|
||||
|
||||
@@ -644,7 +642,7 @@ bitmask! {
|
||||
TransactionPayment = 0b00000001,
|
||||
/// In order to transfer ownership.
|
||||
Transfer = 0b00000010,
|
||||
/// In order to reserve some funds for a later return or repatriation
|
||||
/// In order to reserve some funds for a later return or repatriation.
|
||||
Reserve = 0b00000100,
|
||||
/// In order to pay some other (higher-level) fees.
|
||||
Fee = 0b00001000,
|
||||
|
||||
@@ -76,7 +76,7 @@ pub trait Trait: frame_system::Trait {
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Balances {
|
||||
NextFeeMultiplier get(fn next_fee_multiplier): Multiplier = Multiplier::from_parts(0);
|
||||
pub NextFeeMultiplier get(fn next_fee_multiplier): Multiplier = Multiplier::from_parts(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,9 +178,7 @@ impl<T: Trait + Send + Sync> ChargeTransactionPayment<T> {
|
||||
let adjusted_fee = targeted_fee_adjustment.saturated_multiply_accumulate(adjustable_fee);
|
||||
|
||||
let base_fee = T::TransactionBaseFee::get();
|
||||
let final_fee = base_fee.saturating_add(adjusted_fee).saturating_add(tip);
|
||||
|
||||
final_fee
|
||||
base_fee.saturating_add(adjusted_fee).saturating_add(tip)
|
||||
} else {
|
||||
tip
|
||||
}
|
||||
@@ -307,21 +305,18 @@ mod tests {
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
}
|
||||
|
||||
impl pallet_balances::Trait for Runtime {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type OnNewAccount = ();
|
||||
type Event = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
|
||||
@@ -407,7 +402,6 @@ mod tests {
|
||||
(5, 50 * self.balance_factor),
|
||||
(6, 60 * self.balance_factor)
|
||||
],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
t.into()
|
||||
}
|
||||
@@ -432,14 +426,14 @@ mod tests {
|
||||
.pre_dispatch(&1, CALL, info_from_weight(5), len)
|
||||
.is_ok()
|
||||
);
|
||||
assert_eq!(Balances::free_balance(&1), 100 - 5 - 5 - 10);
|
||||
assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10);
|
||||
|
||||
assert!(
|
||||
ChargeTransactionPayment::<Runtime>::from(5 /* tipped */)
|
||||
.pre_dispatch(&2, CALL, info_from_weight(3), len)
|
||||
.is_ok()
|
||||
);
|
||||
assert_eq!(Balances::free_balance(&2), 200 - 5 - 10 - 3 - 5);
|
||||
assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 3 - 5);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -474,7 +468,7 @@ mod tests {
|
||||
.execute_with(||
|
||||
{
|
||||
// 1 ain't have a penny.
|
||||
assert_eq!(Balances::free_balance(&1), 0);
|
||||
assert_eq!(Balances::free_balance(1), 0);
|
||||
|
||||
let len = 100;
|
||||
|
||||
@@ -521,7 +515,7 @@ mod tests {
|
||||
.pre_dispatch(&1, CALL, info_from_weight(3), len)
|
||||
.is_ok()
|
||||
);
|
||||
assert_eq!(Balances::free_balance(&1), 100 - 10 - 5 - (10 + 3) * 3 / 2);
|
||||
assert_eq!(Balances::free_balance(1), 100 - 10 - 5 - (10 + 3) * 3 / 2);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -759,19 +759,16 @@ mod tests {
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnNewAccount = ();
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type Event = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
pub struct TenToFourteen;
|
||||
@@ -818,7 +815,6 @@ mod tests {
|
||||
pallet_balances::GenesisConfig::<Test>{
|
||||
// Total issuance will be 200 with treasury account initialized at ED.
|
||||
balances: vec![(0, 100), (1, 98), (2, 1)],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
GenesisConfig::default().assimilate_storage::<Test>(&mut t).unwrap();
|
||||
t.into()
|
||||
@@ -853,8 +849,8 @@ mod tests {
|
||||
new_test_ext().execute_with(|| {
|
||||
Balances::make_free_balance_be(&Treasury::account_id(), 101);
|
||||
assert_ok!(Treasury::report_awesome(Origin::signed(0), b"awesome.dot".to_vec(), 3));
|
||||
assert_eq!(Balances::reserved_balance(&0), 12);
|
||||
assert_eq!(Balances::free_balance(&0), 88);
|
||||
assert_eq!(Balances::reserved_balance(0), 12);
|
||||
assert_eq!(Balances::free_balance(0), 88);
|
||||
|
||||
// other reports don't count.
|
||||
assert_noop!(
|
||||
@@ -869,9 +865,9 @@ mod tests {
|
||||
assert_noop!(Treasury::tip(Origin::signed(9), h.clone(), 10), BadOrigin);
|
||||
System::set_block_number(2);
|
||||
assert_ok!(Treasury::close_tip(Origin::signed(100), h.into()));
|
||||
assert_eq!(Balances::reserved_balance(&0), 0);
|
||||
assert_eq!(Balances::free_balance(&0), 102);
|
||||
assert_eq!(Balances::free_balance(&3), 8);
|
||||
assert_eq!(Balances::reserved_balance(0), 0);
|
||||
assert_eq!(Balances::free_balance(0), 102);
|
||||
assert_eq!(Balances::free_balance(3), 8);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -880,16 +876,16 @@ mod tests {
|
||||
new_test_ext().execute_with(|| {
|
||||
Balances::make_free_balance_be(&Treasury::account_id(), 101);
|
||||
assert_ok!(Treasury::report_awesome(Origin::signed(0), b"awesome.dot".to_vec(), 0));
|
||||
assert_eq!(Balances::reserved_balance(&0), 12);
|
||||
assert_eq!(Balances::free_balance(&0), 88);
|
||||
assert_eq!(Balances::reserved_balance(0), 12);
|
||||
assert_eq!(Balances::free_balance(0), 88);
|
||||
let h = BlakeTwo256::hash_of(&(BlakeTwo256::hash(b"awesome.dot"), 0u64));
|
||||
assert_ok!(Treasury::tip(Origin::signed(10), h.clone(), 10));
|
||||
assert_ok!(Treasury::tip(Origin::signed(11), h.clone(), 10));
|
||||
assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 10));
|
||||
System::set_block_number(2);
|
||||
assert_ok!(Treasury::close_tip(Origin::signed(100), h.into()));
|
||||
assert_eq!(Balances::reserved_balance(&0), 0);
|
||||
assert_eq!(Balances::free_balance(&0), 110);
|
||||
assert_eq!(Balances::reserved_balance(0), 0);
|
||||
assert_eq!(Balances::free_balance(0), 110);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -910,7 +906,7 @@ mod tests {
|
||||
System::set_block_number(2);
|
||||
assert_noop!(Treasury::close_tip(Origin::NONE, h.into()), BadOrigin);
|
||||
assert_ok!(Treasury::close_tip(Origin::signed(0), h.into()));
|
||||
assert_eq!(Balances::free_balance(&3), 10);
|
||||
assert_eq!(Balances::free_balance(3), 10);
|
||||
|
||||
assert_noop!(Treasury::close_tip(Origin::signed(100), h.into()), Error::<Test>::UnknownTip);
|
||||
});
|
||||
@@ -942,7 +938,7 @@ mod tests {
|
||||
assert_ok!(Treasury::tip(Origin::signed(12), h.clone(), 1000000));
|
||||
System::set_block_number(2);
|
||||
assert_ok!(Treasury::close_tip(Origin::signed(0), h.into()));
|
||||
assert_eq!(Balances::free_balance(&3), 10);
|
||||
assert_eq!(Balances::free_balance(3), 10);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -961,7 +957,7 @@ mod tests {
|
||||
assert_ok!(Treasury::tip(Origin::signed(10), h.clone(), 10));
|
||||
System::set_block_number(2);
|
||||
assert_ok!(Treasury::close_tip(Origin::signed(0), h.into()));
|
||||
assert_eq!(Balances::free_balance(&3), 10);
|
||||
assert_eq!(Balances::free_balance(3), 10);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -978,8 +974,8 @@ mod tests {
|
||||
fn spend_proposal_takes_min_deposit() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3));
|
||||
assert_eq!(Balances::free_balance(&0), 99);
|
||||
assert_eq!(Balances::reserved_balance(&0), 1);
|
||||
assert_eq!(Balances::free_balance(0), 99);
|
||||
assert_eq!(Balances::reserved_balance(0), 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -987,8 +983,8 @@ mod tests {
|
||||
fn spend_proposal_takes_proportional_deposit() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3));
|
||||
assert_eq!(Balances::free_balance(&0), 95);
|
||||
assert_eq!(Balances::reserved_balance(&0), 5);
|
||||
assert_eq!(Balances::free_balance(0), 95);
|
||||
assert_eq!(Balances::reserved_balance(0), 5);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1011,7 +1007,7 @@ mod tests {
|
||||
assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0));
|
||||
|
||||
<Treasury as OnFinalize<u64>>::on_finalize(1);
|
||||
assert_eq!(Balances::free_balance(&3), 0);
|
||||
assert_eq!(Balances::free_balance(3), 0);
|
||||
assert_eq!(Treasury::pot(), 100);
|
||||
});
|
||||
}
|
||||
@@ -1038,7 +1034,7 @@ mod tests {
|
||||
assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0));
|
||||
|
||||
<Treasury as OnFinalize<u64>>::on_finalize(2);
|
||||
assert_eq!(Balances::free_balance(&3), 0);
|
||||
assert_eq!(Balances::free_balance(3), 0);
|
||||
assert_eq!(Treasury::pot(), 50);
|
||||
});
|
||||
}
|
||||
@@ -1089,7 +1085,7 @@ mod tests {
|
||||
assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0));
|
||||
|
||||
<Treasury as OnFinalize<u64>>::on_finalize(2);
|
||||
assert_eq!(Balances::free_balance(&3), 100);
|
||||
assert_eq!(Balances::free_balance(3), 100);
|
||||
assert_eq!(Treasury::pot(), 0);
|
||||
});
|
||||
}
|
||||
@@ -1108,7 +1104,7 @@ mod tests {
|
||||
|
||||
let _ = Balances::deposit_into_existing(&Treasury::account_id(), 100).unwrap();
|
||||
<Treasury as OnFinalize<u64>>::on_finalize(4);
|
||||
assert_eq!(Balances::free_balance(&3), 150); // Fund has been spent
|
||||
assert_eq!(Balances::free_balance(3), 150); // Fund has been spent
|
||||
assert_eq!(Treasury::pot(), 25); // Pot has finally changed
|
||||
});
|
||||
}
|
||||
@@ -1133,7 +1129,7 @@ mod tests {
|
||||
|
||||
<Treasury as OnFinalize<u64>>::on_finalize(4);
|
||||
assert_eq!(Treasury::pot(), 0); // Pot is emptied
|
||||
assert_eq!(Balances::free_balance(&Treasury::account_id()), 1); // but the account is still there
|
||||
assert_eq!(Balances::free_balance(Treasury::account_id()), 1); // but the account is still there
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1144,13 +1140,12 @@ mod tests {
|
||||
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
||||
pallet_balances::GenesisConfig::<Test>{
|
||||
balances: vec![(0, 100), (1, 99), (2, 1)],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
// Treasury genesis config is not build thus treasury account does not exist
|
||||
let mut t: sp_io::TestExternalities = t.into();
|
||||
|
||||
t.execute_with(|| {
|
||||
assert_eq!(Balances::free_balance(&Treasury::account_id()), 0); // Account does not exist
|
||||
assert_eq!(Balances::free_balance(Treasury::account_id()), 0); // Account does not exist
|
||||
assert_eq!(Treasury::pot(), 0); // Pot is empty
|
||||
|
||||
assert_ok!(Treasury::propose_spend(Origin::signed(0), 99, 3));
|
||||
@@ -1159,16 +1154,16 @@ mod tests {
|
||||
assert_ok!(Treasury::approve_proposal(Origin::ROOT, 1));
|
||||
<Treasury as OnFinalize<u64>>::on_finalize(2);
|
||||
assert_eq!(Treasury::pot(), 0); // Pot hasn't changed
|
||||
assert_eq!(Balances::free_balance(&3), 0); // Balance of `3` hasn't changed
|
||||
assert_eq!(Balances::free_balance(3), 0); // Balance of `3` hasn't changed
|
||||
|
||||
Balances::make_free_balance_be(&Treasury::account_id(), 100);
|
||||
assert_eq!(Treasury::pot(), 99); // Pot now contains funds
|
||||
assert_eq!(Balances::free_balance(&Treasury::account_id()), 100); // Account does exist
|
||||
assert_eq!(Balances::free_balance(Treasury::account_id()), 100); // Account does exist
|
||||
|
||||
<Treasury as OnFinalize<u64>>::on_finalize(4);
|
||||
|
||||
assert_eq!(Treasury::pot(), 0); // Pot has changed
|
||||
assert_eq!(Balances::free_balance(&3), 99); // Balance of `3` has changed
|
||||
assert_eq!(Balances::free_balance(3), 99); // Balance of `3` has changed
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,19 +703,16 @@ mod tests {
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnReapAccount = System;
|
||||
type OnNewAccount = ();
|
||||
type Event = TestEvent;
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
parameter_types! {
|
||||
@@ -742,7 +739,6 @@ mod tests {
|
||||
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
||||
pallet_balances::GenesisConfig::<Test> {
|
||||
balances: vec![(1, 10), (2, 10), (3, 10), (4, 10), (5, 10)],
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
t.into()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
[package]
|
||||
name = "pallet-vesting"
|
||||
version = "2.0.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.101", optional = true }
|
||||
codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] }
|
||||
enumflags2 = { version = "0.6.2" }
|
||||
sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" }
|
||||
sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" }
|
||||
sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" }
|
||||
frame-support = { version = "2.0.0", default-features = false, path = "../support" }
|
||||
frame-system = { version = "2.0.0", default-features = false, path = "../system" }
|
||||
|
||||
[dev-dependencies]
|
||||
sp-core = { version = "2.0.0", path = "../../primitives/core" }
|
||||
pallet-balances = { version = "2.0.0", path = "../balances" }
|
||||
sp-storage = { version = "2.0.0", path = "../../primitives/storage" }
|
||||
hex-literal = "0.2.1"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"serde",
|
||||
"codec/std",
|
||||
"sp-std/std",
|
||||
"sp-io/std",
|
||||
"sp-runtime/std",
|
||||
"frame-support/std",
|
||||
"frame-system/std",
|
||||
]
|
||||
@@ -0,0 +1,610 @@
|
||||
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! # Vesting Module
|
||||
//!
|
||||
//! - [`vesting::Trait`](./trait.Trait.html)
|
||||
//! - [`Call`](./enum.Call.html)
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! 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.
|
||||
//!
|
||||
//! 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
|
||||
//! equivalent to the amount remaining to be vested. This is done through a dispatchable function,
|
||||
//! either `vest` (in typical case where the sender is calling on their own behalf) or `vest_other`
|
||||
//! in case the sender is calling on another account's behalf.
|
||||
//!
|
||||
//! ## Interface
|
||||
//!
|
||||
//! This module implements the `VestingSchedule` trait.
|
||||
//!
|
||||
//! ### Dispatchable Functions
|
||||
//!
|
||||
//! - `vest` - Update the lock, reducing it in line with the amount "vested" so far.
|
||||
//! - `vest_other` - Update the lock of another account, reducing it in line with the amount
|
||||
//! "vested" so far.
|
||||
//!
|
||||
//! [`Call`]: ./enum.Call.html
|
||||
//! [`Trait`]: ./trait.Trait.html
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use sp_std::fmt::Debug;
|
||||
use codec::{Encode, Decode};
|
||||
use sp_runtime::{DispatchResult, RuntimeDebug, traits::{
|
||||
StaticLookup, Zero, SimpleArithmetic, MaybeSerializeDeserialize, Saturating, Convert
|
||||
}};
|
||||
use frame_support::{decl_module, decl_event, decl_storage, ensure, decl_error};
|
||||
use frame_support::traits::{
|
||||
Currency, LockableCurrency, VestingSchedule, WithdrawReason, LockIdentifier
|
||||
};
|
||||
use frame_system::{self as system, ensure_signed};
|
||||
|
||||
type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;
|
||||
|
||||
pub trait Trait: frame_system::Trait {
|
||||
/// The overarching event type.
|
||||
type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
|
||||
|
||||
/// The currency trait.
|
||||
type Currency: LockableCurrency<Self::AccountId>;
|
||||
|
||||
/// Convert the block number into a balance.
|
||||
type BlockNumberToBalance: Convert<Self::BlockNumber, BalanceOf<Self>>;
|
||||
}
|
||||
|
||||
const VESTING_ID: LockIdentifier = *b"vesting ";
|
||||
|
||||
/// Struct to encode the vesting schedule of an individual account.
|
||||
#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug)]
|
||||
pub struct VestingInfo<Balance, BlockNumber> {
|
||||
/// Locked amount at genesis.
|
||||
pub locked: Balance,
|
||||
/// Amount that gets unlocked every block after `starting_block`.
|
||||
pub per_block: Balance,
|
||||
/// Starting block for unlocking(vesting).
|
||||
pub starting_block: BlockNumber,
|
||||
}
|
||||
|
||||
impl<
|
||||
Balance: SimpleArithmetic + Copy,
|
||||
BlockNumber: SimpleArithmetic + Copy,
|
||||
> VestingInfo<Balance, BlockNumber> {
|
||||
/// Amount locked at block `n`.
|
||||
pub fn locked_at<
|
||||
BlockNumberToBalance: Convert<BlockNumber, Balance>
|
||||
>(&self, n: BlockNumber) -> Balance {
|
||||
// Number of blocks that count toward vesting
|
||||
// Saturating to 0 when n < starting_block
|
||||
let vested_block_count = n.saturating_sub(self.starting_block);
|
||||
let vested_block_count = BlockNumberToBalance::convert(vested_block_count);
|
||||
// Return amount that is still locked in vesting
|
||||
let maybe_balance = vested_block_count.checked_mul(&self.per_block);
|
||||
if let Some(balance) = maybe_balance {
|
||||
self.locked.saturating_sub(balance)
|
||||
} else {
|
||||
Zero::zero()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Vesting {
|
||||
/// Information regarding the vesting of a given account.
|
||||
pub Vesting get(fn vesting):
|
||||
map hasher(blake2_256) T::AccountId => Option<VestingInfo<BalanceOf<T>, T::BlockNumber>>;
|
||||
}
|
||||
add_extra_genesis {
|
||||
config(vesting): Vec<(T::AccountId, T::BlockNumber, T::BlockNumber, BalanceOf<T>)>;
|
||||
build(|config: &GenesisConfig<T>| {
|
||||
// Generate initial vesting configuration
|
||||
// * who - Account which we are generating vesting configuration for
|
||||
// * begin - Block when the account will start to vest
|
||||
// * length - Number of blocks from `begin` until fully vested
|
||||
// * liquid - Number of units which can be spent before vesting begins
|
||||
for &(ref who, begin, length, liquid) in config.vesting.iter() {
|
||||
let balance = T::Currency::free_balance(who);
|
||||
assert!(!balance.is_zero(), "Currencies must be init'd before vesting");
|
||||
// Total genesis `balance` minus `liquid` equals funds locked for vesting
|
||||
let locked = balance.saturating_sub(liquid);
|
||||
let length_as_balance = T::BlockNumberToBalance::convert(length);
|
||||
let per_block = locked / length_as_balance.max(sp_runtime::traits::One::one());
|
||||
|
||||
Vesting::<T>::insert(who, VestingInfo {
|
||||
locked: locked,
|
||||
per_block: per_block,
|
||||
starting_block: begin
|
||||
});
|
||||
let reasons = WithdrawReason::Transfer | WithdrawReason::Reserve;
|
||||
T::Currency::set_lock(VESTING_ID, who, locked, reasons);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
decl_event!(
|
||||
pub enum Event<T> where AccountId = <T as frame_system::Trait>::AccountId, Balance = BalanceOf<T> {
|
||||
/// The amount vested has been updated. This could indicate more funds are available. The
|
||||
/// balance given is the amount which is left unvested (and thus locked).
|
||||
VestingUpdated(AccountId, Balance),
|
||||
/// An account (given) has become fully vested. No further vesting can happen.
|
||||
VestingCompleted(AccountId),
|
||||
}
|
||||
);
|
||||
|
||||
decl_error! {
|
||||
/// Error for the vesting module.
|
||||
pub enum Error for Module<T: Trait> {
|
||||
/// The account given is not vesting.
|
||||
NotVesting,
|
||||
/// An existing vesting schedule already exists for this account that cannot be clobbered.
|
||||
ExistingVestingSchedule,
|
||||
}
|
||||
}
|
||||
|
||||
decl_module! {
|
||||
// Simple declaration of the `Module` type. Lets the macro know what it's working on.
|
||||
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
||||
type Error = Error<T>;
|
||||
|
||||
fn deposit_event() = default;
|
||||
|
||||
/// Unlock any vested funds of the sender account.
|
||||
///
|
||||
/// The dispatch origin for this call must be _Signed_ and the sender must have funds still
|
||||
/// locked under this module.
|
||||
///
|
||||
/// Emits either `VestingCompleted` or `VestingUpdated`.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - `O(1)`.
|
||||
/// - One balance-lock operation.
|
||||
/// - One storage read (codec `O(1)`) and up to one removal.
|
||||
/// - One event.
|
||||
/// # </weight>
|
||||
fn vest(origin) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
Self::update_lock(who)
|
||||
}
|
||||
|
||||
/// Unlock any vested funds of a `target` account.
|
||||
///
|
||||
/// The dispatch origin for this call must be _Signed_.
|
||||
///
|
||||
/// - `target`: The account whose vested funds should be unlocked. Must have funds still
|
||||
/// locked under this module.
|
||||
///
|
||||
/// Emits either `VestingCompleted` or `VestingUpdated`.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - `O(1)`.
|
||||
/// - Up to one account lookup.
|
||||
/// - One balance-lock operation.
|
||||
/// - One storage read (codec `O(1)`) and up to one removal.
|
||||
/// - One event.
|
||||
/// # </weight>
|
||||
fn vest_other(origin, target: <T::Lookup as StaticLookup>::Source) -> DispatchResult {
|
||||
ensure_signed(origin)?;
|
||||
Self::update_lock(T::Lookup::lookup(target)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
/// (Re)set or remove the module's currency lock on `who`'s account in accordance with their
|
||||
/// current unvested amount.
|
||||
fn update_lock(who: T::AccountId) -> DispatchResult {
|
||||
ensure!(Vesting::<T>::exists(&who), Error::<T>::NotVesting);
|
||||
let unvested = Self::vesting_balance(&who);
|
||||
if unvested.is_zero() {
|
||||
T::Currency::remove_lock(VESTING_ID, &who);
|
||||
Vesting::<T>::remove(&who);
|
||||
Self::deposit_event(RawEvent::VestingCompleted(who));
|
||||
} else {
|
||||
let reasons = WithdrawReason::Transfer | WithdrawReason::Reserve;
|
||||
T::Currency::set_lock(VESTING_ID, &who, unvested, reasons);
|
||||
Self::deposit_event(RawEvent::VestingUpdated(who, unvested));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> VestingSchedule<T::AccountId> for Module<T> where
|
||||
BalanceOf<T>: MaybeSerializeDeserialize + Debug
|
||||
{
|
||||
type Moment = T::BlockNumber;
|
||||
type Currency = T::Currency;
|
||||
|
||||
/// Get the amount that is currently being vested and cannot be transferred out of this account.
|
||||
fn vesting_balance(who: &T::AccountId) -> BalanceOf<T> {
|
||||
if let Some(v) = Self::vesting(who) {
|
||||
let now = <frame_system::Module<T>>::block_number();
|
||||
let locked_now = v.locked_at::<T::BlockNumberToBalance>(now);
|
||||
T::Currency::free_balance(who).min(locked_now)
|
||||
} else {
|
||||
Zero::zero()
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a vesting schedule to a given account.
|
||||
///
|
||||
/// If there already exists a vesting schedule for the given account, an `Err` is returned
|
||||
/// and nothing is updated.
|
||||
///
|
||||
/// Is a no-op if the amount to be vested is zero.
|
||||
fn add_vesting_schedule(
|
||||
who: &T::AccountId,
|
||||
locked: BalanceOf<T>,
|
||||
per_block: BalanceOf<T>,
|
||||
starting_block: T::BlockNumber
|
||||
) -> DispatchResult {
|
||||
if locked.is_zero() { return Ok(()) }
|
||||
if Vesting::<T>::exists(who) {
|
||||
Err(Error::<T>::ExistingVestingSchedule)?
|
||||
}
|
||||
let vesting_schedule = VestingInfo {
|
||||
locked,
|
||||
per_block,
|
||||
starting_block
|
||||
};
|
||||
Vesting::<T>::insert(who, vesting_schedule);
|
||||
// it can't fail, but even if somehow it did, we don't really care.
|
||||
let _ = Self::update_lock(who.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove a vesting schedule for a given account.
|
||||
fn remove_vesting_schedule(who: &T::AccountId) {
|
||||
Vesting::<T>::remove(who);
|
||||
// it can't fail, but even if somehow it did, we don't really care.
|
||||
let _ = Self::update_lock(who.clone());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use frame_support::{
|
||||
assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight,
|
||||
traits::Get
|
||||
};
|
||||
use sp_core::H256;
|
||||
// The testing primitives are very useful for avoiding having to work with signatures
|
||||
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required.
|
||||
use sp_runtime::{
|
||||
Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup, Identity, OnInitialize},
|
||||
};
|
||||
use sp_storage::Storage;
|
||||
|
||||
impl_outer_origin! {
|
||||
pub enum Origin for Test where system = frame_system {}
|
||||
}
|
||||
|
||||
// For testing the module, we construct most of a mock runtime. This means
|
||||
// first constructing a configuration type (`Test`) which `impl`s each of the
|
||||
// configuration traits of modules we want to use.
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct Test;
|
||||
parameter_types! {
|
||||
pub const BlockHashCount: u64 = 250;
|
||||
pub const MaximumBlockWeight: Weight = 1024;
|
||||
pub const MaximumBlockLength: u32 = 2 * 1024;
|
||||
pub const AvailableBlockRatio: Perbill = Perbill::one();
|
||||
}
|
||||
impl frame_system::Trait for Test {
|
||||
type Origin = Origin;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
type Call = ();
|
||||
type Hashing = BlakeTwo256;
|
||||
type AccountId = u64;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
type BlockHashCount = BlockHashCount;
|
||||
type MaximumBlockWeight = MaximumBlockWeight;
|
||||
type MaximumBlockLength = MaximumBlockLength;
|
||||
type AvailableBlockRatio = AvailableBlockRatio;
|
||||
type Version = ();
|
||||
type ModuleToIndex = ();
|
||||
}
|
||||
parameter_types! {
|
||||
pub const CreationFee: u64 = 0;
|
||||
}
|
||||
impl pallet_balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnReapAccount = System;
|
||||
type OnNewAccount = ();
|
||||
type Event = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type CreationFee = CreationFee;
|
||||
}
|
||||
impl Trait for Test {
|
||||
type Event = ();
|
||||
type Currency = Balances;
|
||||
type BlockNumberToBalance = Identity;
|
||||
}
|
||||
type System = frame_system::Module<Test>;
|
||||
type Balances = pallet_balances::Module<Test>;
|
||||
type Vesting = Module<Test>;
|
||||
|
||||
thread_local! {
|
||||
static EXISTENTIAL_DEPOSIT: RefCell<u64> = RefCell::new(0);
|
||||
}
|
||||
pub struct ExistentialDeposit;
|
||||
impl Get<u64> for ExistentialDeposit {
|
||||
fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) }
|
||||
}
|
||||
|
||||
pub struct ExtBuilder {
|
||||
existential_deposit: u64,
|
||||
}
|
||||
impl Default for ExtBuilder {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
existential_deposit: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ExtBuilder {
|
||||
pub fn existential_deposit(mut self, existential_deposit: u64) -> Self {
|
||||
self.existential_deposit = existential_deposit;
|
||||
self
|
||||
}
|
||||
pub fn build(self) -> sp_io::TestExternalities {
|
||||
EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit);
|
||||
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
||||
pallet_balances::GenesisConfig::<Test> {
|
||||
balances: vec![
|
||||
(1, 10 * self.existential_deposit),
|
||||
(2, 20 * self.existential_deposit),
|
||||
(3, 30 * self.existential_deposit),
|
||||
(4, 40 * self.existential_deposit),
|
||||
(12, 10 * self.existential_deposit)
|
||||
],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
GenesisConfig::<Test> {
|
||||
vesting: vec![
|
||||
(1, 0, 10, 5 * self.existential_deposit),
|
||||
(2, 10, 20, 0),
|
||||
(12, 10, 20, 5 * self.existential_deposit)
|
||||
],
|
||||
}.assimilate_storage(&mut t).unwrap();
|
||||
t.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vesting_info_via_migration_should_work() {
|
||||
let mut s = Storage::default();
|
||||
use hex_literal::hex;
|
||||
// A dump of data from the previous version for which we know account 6 vests 30 of its 60
|
||||
// over 5 blocks from block 3.
|
||||
let data = vec![
|
||||
(hex!["26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac"].to_vec(), hex!["0100000000000000"].to_vec()),
|
||||
(hex!["26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850"].to_vec(), hex!["02000000"].to_vec()),
|
||||
(hex!["26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7"].to_vec(), hex!["08000000000000000000000000"].to_vec()),
|
||||
(hex!["26aa394eea5630e07c48ae0c9558cef78a42f33323cb5ced3b44dd825fda9fcc"].to_vec(), hex!["4545454545454545454545454545454545454545454545454545454545454545"].to_vec()),
|
||||
(hex!["26aa394eea5630e07c48ae0c9558cef7a44704b568d21667356a5a050c11874681e47a19e6b29b0a65b9591762ce5143ed30d0261e5d24a3201752506b20f15c"].to_vec(), hex!["4545454545454545454545454545454545454545454545454545454545454545"].to_vec()),
|
||||
(hex!["3a636f6465"].to_vec(), hex![""].to_vec()),
|
||||
(hex!["3a65787472696e7369635f696e646578"].to_vec(), hex!["00000000"].to_vec()),
|
||||
(hex!["3a686561707061676573"].to_vec(), hex!["0800000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc61dbd7d0b561a41d23c2a469ad42fbd70d5438bae826f6fd607413190c37c363b"].to_vec(), hex!["046d697363202020200300000000000000ffffffffffffffff04"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc66cddb367afbd583bb48f9bbd7d5ba3b1d0738b4881b1cddd38169526d8158137"].to_vec(), hex!["0474786665657320200300000000000000ffffffffffffffff01"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f218f26c73add634897550b4003b26bc6e88b43fded6323ef02ffeffbd8c40846ee09bf316271bd22369659c959dd733a"].to_vec(), hex!["08616c6c20202020200300000000000000ffffffffffffffff1f64656d6f63726163ffffffffffffffff030000000000000002"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f3c22813def93ef32c365b55cb92f10f91dbd7d0b561a41d23c2a469ad42fbd70d5438bae826f6fd607413190c37c363b"].to_vec(), hex!["0500000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80"].to_vec(), hex!["d200000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f5f27b51b5ec208ee9cb25b55d8728243b8788bb218b185b63e3e92653953f29b6b143fb8cf5159fc908632e6fe490501"].to_vec(), hex!["1e0000000000000006000000000000000200000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b41dbd7d0b561a41d23c2a469ad42fbd70d5438bae826f6fd607413190c37c363b"].to_vec(), hex!["0500000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b46cddb367afbd583bb48f9bbd7d5ba3b1d0738b4881b1cddd38169526d8158137"].to_vec(), hex!["1e00000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b4b8788bb218b185b63e3e92653953f29b6b143fb8cf5159fc908632e6fe490501"].to_vec(), hex!["3c00000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b4e88b43fded6323ef02ffeffbd8c40846ee09bf316271bd22369659c959dd733a"].to_vec(), hex!["1400000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b4e96760d274653a39b429a87ebaae9d3aa4fdf58b9096cf0bebc7c4e5a4c2ed8d"].to_vec(), hex!["2800000000000000"].to_vec()),
|
||||
(hex!["c2261276cc9d1f8598ea4b6a74b15c2f6482b9ade7bc6657aaca787ba1add3b4effb728943197fd12e694cbf3f3ede28fbf7498b0370c6dfa0013874b417c178"].to_vec(), hex!["3200000000000000"].to_vec()),
|
||||
(hex!["f2794c22e353e9a839f12faab03a911b7f17cdfbfa73331856cca0acddd7842e"].to_vec(), hex!["00000000"].to_vec()),
|
||||
(hex!["f2794c22e353e9a839f12faab03a911bbdcb0c5143a8617ed38ae3810dd45bc6"].to_vec(), hex!["00000000"].to_vec()),
|
||||
(hex!["f2794c22e353e9a839f12faab03a911be2f6cb0456905c189bcb0458f9440f13"].to_vec(), hex!["00000000"].to_vec()),
|
||||
];
|
||||
s.top = data.into_iter().collect();
|
||||
sp_io::TestExternalities::new(s).execute_with(|| {
|
||||
Balances::on_initialize(1);
|
||||
assert_eq!(Balances::free_balance(6), 60);
|
||||
assert_eq!(Balances::usable_balance(&6), 30);
|
||||
System::set_block_number(2);
|
||||
assert_ok!(Vesting::vest(Origin::signed(6)));
|
||||
assert_eq!(Balances::usable_balance(&6), 30);
|
||||
System::set_block_number(3);
|
||||
assert_ok!(Vesting::vest(Origin::signed(6)));
|
||||
assert_eq!(Balances::usable_balance(&6), 36);
|
||||
System::set_block_number(4);
|
||||
assert_ok!(Vesting::vest(Origin::signed(6)));
|
||||
assert_eq!(Balances::usable_balance(&6), 42);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_vesting_status() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(256)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
let user1_free_balance = Balances::free_balance(&1);
|
||||
let user2_free_balance = Balances::free_balance(&2);
|
||||
let user12_free_balance = Balances::free_balance(&12);
|
||||
assert_eq!(user1_free_balance, 256 * 10); // Account 1 has free balance
|
||||
assert_eq!(user2_free_balance, 256 * 20); // Account 2 has free balance
|
||||
assert_eq!(user12_free_balance, 256 * 10); // Account 12 has free balance
|
||||
let user1_vesting_schedule = VestingInfo {
|
||||
locked: 256 * 5,
|
||||
per_block: 128, // Vesting over 10 blocks
|
||||
starting_block: 0,
|
||||
};
|
||||
let user2_vesting_schedule = VestingInfo {
|
||||
locked: 256 * 20,
|
||||
per_block: 256, // Vesting over 20 blocks
|
||||
starting_block: 10,
|
||||
};
|
||||
let user12_vesting_schedule = VestingInfo {
|
||||
locked: 256 * 5,
|
||||
per_block: 64, // Vesting over 20 blocks
|
||||
starting_block: 10,
|
||||
};
|
||||
assert_eq!(Vesting::vesting(&1), Some(user1_vesting_schedule)); // Account 1 has a vesting schedule
|
||||
assert_eq!(Vesting::vesting(&2), Some(user2_vesting_schedule)); // Account 2 has a vesting schedule
|
||||
assert_eq!(Vesting::vesting(&12), Some(user12_vesting_schedule)); // Account 12 has a vesting schedule
|
||||
|
||||
// Account 1 has only 128 units vested from their illiquid 256 * 5 units at block 1
|
||||
assert_eq!(Vesting::vesting_balance(&1), 128 * 9);
|
||||
// Account 2 has their full balance locked
|
||||
assert_eq!(Vesting::vesting_balance(&2), user2_free_balance);
|
||||
// Account 12 has only their illiquid funds locked
|
||||
assert_eq!(Vesting::vesting_balance(&12), user12_free_balance - 256 * 5);
|
||||
|
||||
System::set_block_number(10);
|
||||
assert_eq!(System::block_number(), 10);
|
||||
|
||||
// Account 1 has fully vested by block 10
|
||||
assert_eq!(Vesting::vesting_balance(&1), 0);
|
||||
// Account 2 has started vesting by block 10
|
||||
assert_eq!(Vesting::vesting_balance(&2), user2_free_balance);
|
||||
// Account 12 has started vesting by block 10
|
||||
assert_eq!(Vesting::vesting_balance(&12), user12_free_balance - 256 * 5);
|
||||
|
||||
System::set_block_number(30);
|
||||
assert_eq!(System::block_number(), 30);
|
||||
|
||||
assert_eq!(Vesting::vesting_balance(&1), 0); // Account 1 is still fully vested, and not negative
|
||||
assert_eq!(Vesting::vesting_balance(&2), 0); // Account 2 has fully vested by block 30
|
||||
assert_eq!(Vesting::vesting_balance(&12), 0); // Account 2 has fully vested by block 30
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unvested_balance_should_not_transfer() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(10)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
let user1_free_balance = Balances::free_balance(&1);
|
||||
assert_eq!(user1_free_balance, 100); // Account 1 has free balance
|
||||
// Account 1 has only 5 units vested at block 1 (plus 50 unvested)
|
||||
assert_eq!(Vesting::vesting_balance(&1), 45);
|
||||
assert_noop!(
|
||||
Balances::transfer(Some(1).into(), 2, 56),
|
||||
pallet_balances::Error::<Test, _>::LiquidityRestrictions,
|
||||
); // Account 1 cannot send more than vested amount
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vested_balance_should_transfer() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(10)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
let user1_free_balance = Balances::free_balance(&1);
|
||||
assert_eq!(user1_free_balance, 100); // Account 1 has free balance
|
||||
// Account 1 has only 5 units vested at block 1 (plus 50 unvested)
|
||||
assert_eq!(Vesting::vesting_balance(&1), 45);
|
||||
assert_ok!(Vesting::vest(Some(1).into()));
|
||||
assert_ok!(Balances::transfer(Some(1).into(), 2, 55));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vested_balance_should_transfer_using_vest_other() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(10)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
let user1_free_balance = Balances::free_balance(&1);
|
||||
assert_eq!(user1_free_balance, 100); // Account 1 has free balance
|
||||
// Account 1 has only 5 units vested at block 1 (plus 50 unvested)
|
||||
assert_eq!(Vesting::vesting_balance(&1), 45);
|
||||
assert_ok!(Vesting::vest_other(Some(2).into(), 1));
|
||||
assert_ok!(Balances::transfer(Some(1).into(), 2, 55));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extra_balance_should_transfer() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(10)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
assert_ok!(Balances::transfer(Some(3).into(), 1, 100));
|
||||
assert_ok!(Balances::transfer(Some(3).into(), 2, 100));
|
||||
|
||||
let user1_free_balance = Balances::free_balance(&1);
|
||||
assert_eq!(user1_free_balance, 200); // Account 1 has 100 more free balance than normal
|
||||
|
||||
let user2_free_balance = Balances::free_balance(&2);
|
||||
assert_eq!(user2_free_balance, 300); // Account 2 has 100 more free balance than normal
|
||||
|
||||
// Account 1 has only 5 units vested at block 1 (plus 150 unvested)
|
||||
assert_eq!(Vesting::vesting_balance(&1), 45);
|
||||
assert_ok!(Vesting::vest(Some(1).into()));
|
||||
assert_ok!(Balances::transfer(Some(1).into(), 3, 155)); // Account 1 can send extra units gained
|
||||
|
||||
// Account 2 has no units vested at block 1, but gained 100
|
||||
assert_eq!(Vesting::vesting_balance(&2), 200);
|
||||
assert_ok!(Vesting::vest(Some(2).into()));
|
||||
assert_ok!(Balances::transfer(Some(2).into(), 3, 100)); // Account 2 can send extra units gained
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn liquid_funds_should_transfer_with_delayed_vesting() {
|
||||
ExtBuilder::default()
|
||||
.existential_deposit(256)
|
||||
.build()
|
||||
.execute_with(|| {
|
||||
assert_eq!(System::block_number(), 1);
|
||||
let user12_free_balance = Balances::free_balance(&12);
|
||||
|
||||
assert_eq!(user12_free_balance, 2560); // Account 12 has free balance
|
||||
// Account 12 has liquid funds
|
||||
assert_eq!(Vesting::vesting_balance(&12), user12_free_balance - 256 * 5);
|
||||
|
||||
// Account 12 has delayed vesting
|
||||
let user12_vesting_schedule = VestingInfo {
|
||||
locked: 256 * 5,
|
||||
per_block: 64, // Vesting over 20 blocks
|
||||
starting_block: 10,
|
||||
};
|
||||
assert_eq!(Vesting::vesting(&12), Some(user12_vesting_schedule));
|
||||
|
||||
// Account 12 can still send liquid funds
|
||||
assert_ok!(Balances::transfer(Some(12).into(), 3, 256 * 5));
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user