mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-29 16:07:57 +00:00
Turn storage items into parameters (#2883)
* balances: Turn storage items into parameters. * contract: Turn storage items into parameters. * council: Turn storage items into parameters. * finality-tracker: Turn storage items into parameters. * treasury: Turn storage items into parameters. * democracy: Fix tests. * example: Fix tests. * executive: Fix tests. * staking: Fix tests. * Update runtime. * Update template-node. * Update runtime version. * Fix executor tests. * Fix node cli tests. * Address grumbles. * Add removed default values to docs. * Make gas price a storage item. * Set associated consts must be callable outside of build. * Fix not enough gas to pay for transfer fee. * Fix build. * Emit metadata. * Fix build. * Add default values for all parameter types. * Fix build. * Fix build. * Fix build. * Fix build.
This commit is contained in:
@@ -30,7 +30,7 @@ pub use timestamp::Call as TimestampCall;
|
||||
pub use balances::Call as BalancesCall;
|
||||
pub use runtime_primitives::{Permill, Perbill};
|
||||
pub use timestamp::BlockPeriod;
|
||||
pub use support::{StorageValue, construct_runtime};
|
||||
pub use support::{StorageValue, construct_runtime, parameter_types};
|
||||
|
||||
/// Alias to the signature scheme used for Aura authority signatures.
|
||||
pub type AuraSignature = ed25519::Signature;
|
||||
@@ -151,6 +151,14 @@ impl timestamp::Trait for Runtime {
|
||||
type OnTimestampSet = Aura;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u128 = 500;
|
||||
pub const TransferFee: u128 = 0;
|
||||
pub const CreationFee: u128 = 0;
|
||||
pub const TransactionBaseFee: u128 = 1;
|
||||
pub const TransactionByteFee: u128 = 0;
|
||||
}
|
||||
|
||||
impl balances::Trait for Runtime {
|
||||
/// The type for recording an account's balance.
|
||||
type Balance = u128;
|
||||
@@ -164,6 +172,11 @@ impl balances::Trait for Runtime {
|
||||
type TransactionPayment = ();
|
||||
type DustRemoval = ();
|
||||
type TransferPayment = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
}
|
||||
|
||||
impl sudo::Trait for Runtime {
|
||||
|
||||
@@ -104,11 +104,6 @@ fn testnet_genesis(initial_authorities: Vec<AuthorityId>, endowed_accounts: Vec<
|
||||
ids: endowed_accounts.clone(),
|
||||
}),
|
||||
balances: Some(BalancesConfig {
|
||||
transaction_base_fee: 1,
|
||||
transaction_byte_fee: 0,
|
||||
existential_deposit: 500,
|
||||
transfer_fee: 0,
|
||||
creation_fee: 0,
|
||||
balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(),
|
||||
vesting: vec![],
|
||||
}),
|
||||
|
||||
@@ -17,10 +17,14 @@
|
||||
//! Substrate chain configurations.
|
||||
|
||||
use primitives::{ed25519, sr25519, Pair, crypto::UncheckedInto};
|
||||
use node_primitives::{AccountId, AuraId};
|
||||
use node_runtime::{CouncilSeatsConfig, AuraConfig, DemocracyConfig, SystemConfig,
|
||||
SessionConfig, StakingConfig, StakerStatus, TimestampConfig, BalancesConfig, TreasuryConfig,
|
||||
SudoConfig, ContractsConfig, GrandpaConfig, IndicesConfig, Permill, Perbill, SessionKeys};
|
||||
use node_primitives::{AccountId, AuraId, Balance};
|
||||
use node_runtime::{
|
||||
AuraConfig, BalancesConfig, ContractsConfig, CouncilSeatsConfig, DemocracyConfig,
|
||||
GrandpaConfig, IndicesConfig, SessionConfig, StakingConfig, SudoConfig,
|
||||
SystemConfig, TimestampConfig,
|
||||
Perbill, SessionKeys, StakerStatus,
|
||||
DAYS, DOLLARS, MILLICENTS, SECS_PER_BLOCK,
|
||||
};
|
||||
pub use node_runtime::GenesisConfig;
|
||||
use substrate_service;
|
||||
use hex_literal::hex;
|
||||
@@ -88,17 +92,8 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
|
||||
hex!["9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809"].unchecked_into(),
|
||||
];
|
||||
|
||||
const MILLICENTS: u128 = 1_000_000_000;
|
||||
const CENTS: u128 = 1_000 * MILLICENTS; // assume this is worth about a cent.
|
||||
const DOLLARS: u128 = 100 * CENTS;
|
||||
|
||||
const SECS_PER_BLOCK: u64 = 6;
|
||||
const MINUTES: u64 = 60 / SECS_PER_BLOCK;
|
||||
const HOURS: u64 = MINUTES * 60;
|
||||
const DAYS: u64 = HOURS * 24;
|
||||
|
||||
const ENDOWMENT: u128 = 10_000_000 * DOLLARS;
|
||||
const STASH: u128 = 100 * DOLLARS;
|
||||
const ENDOWMENT: Balance = 10_000_000 * DOLLARS;
|
||||
const STASH: Balance = 100 * DOLLARS;
|
||||
|
||||
GenesisConfig {
|
||||
system: Some(SystemConfig {
|
||||
@@ -106,15 +101,10 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
|
||||
changes_trie_config: Default::default(),
|
||||
}),
|
||||
balances: Some(BalancesConfig {
|
||||
transaction_base_fee: 1 * CENTS,
|
||||
transaction_byte_fee: 10 * MILLICENTS,
|
||||
balances: endowed_accounts.iter().cloned()
|
||||
.map(|k| (k, ENDOWMENT))
|
||||
.chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
|
||||
.collect(),
|
||||
existential_deposit: 1 * DOLLARS,
|
||||
transfer_fee: 1 * CENTS,
|
||||
creation_fee: 1 * CENTS,
|
||||
vesting: vec![],
|
||||
}),
|
||||
indices: Some(IndicesConfig {
|
||||
@@ -140,47 +130,16 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
|
||||
democracy: Some(DemocracyConfig::default()),
|
||||
council_seats: Some(CouncilSeatsConfig {
|
||||
active_council: vec![],
|
||||
candidacy_bond: 10 * DOLLARS,
|
||||
voter_bond: 1 * DOLLARS,
|
||||
voting_fee: 2 * DOLLARS,
|
||||
present_slash_per_voter: 1 * CENTS,
|
||||
carry_count: 6,
|
||||
presentation_duration: 1 * DAYS,
|
||||
approval_voting_period: 2 * DAYS,
|
||||
term_duration: 28 * DAYS,
|
||||
desired_seats: 0,
|
||||
decay_ratio: 0,
|
||||
inactive_grace_period: 1, // one additional vote should go by before an inactive voter can be reaped.
|
||||
}),
|
||||
timestamp: Some(TimestampConfig {
|
||||
minimum_period: SECS_PER_BLOCK / 2, // due to the nature of aura the slots are 2*period
|
||||
}),
|
||||
treasury: Some(TreasuryConfig {
|
||||
proposal_bond: Permill::from_percent(5),
|
||||
proposal_bond_minimum: 1 * DOLLARS,
|
||||
spend_period: 1 * DAYS,
|
||||
burn: Permill::from_percent(50),
|
||||
}),
|
||||
contracts: Some(ContractsConfig {
|
||||
signed_claim_handicap: 2,
|
||||
rent_byte_price: 4,
|
||||
rent_deposit_offset: 1000,
|
||||
storage_size_offset: 8,
|
||||
surcharge_reward: 150,
|
||||
tombstone_deposit: 16,
|
||||
transaction_base_fee: 1 * CENTS,
|
||||
transaction_byte_fee: 10 * MILLICENTS,
|
||||
transfer_fee: 1 * CENTS,
|
||||
creation_fee: 1 * CENTS,
|
||||
contract_fee: 1 * CENTS,
|
||||
current_schedule: Default::default(),
|
||||
gas_price: 1 * MILLICENTS,
|
||||
max_depth: 1024,
|
||||
block_gas_limit: 10_000_000,
|
||||
current_schedule: contracts::Schedule {
|
||||
call_base_cost: 1000,
|
||||
instantiate_base_cost: 1000,
|
||||
..Default::default()
|
||||
},
|
||||
}),
|
||||
sudo: Some(SudoConfig {
|
||||
key: endowed_accounts[0].clone(),
|
||||
@@ -264,8 +223,8 @@ pub fn testnet_genesis(
|
||||
]
|
||||
});
|
||||
|
||||
const STASH: u128 = 1 << 20;
|
||||
const ENDOWMENT: u128 = 1 << 20;
|
||||
const ENDOWMENT: Balance = 10_000_000 * DOLLARS;
|
||||
const STASH: Balance = 100 * DOLLARS;
|
||||
|
||||
let council_desired_seats = (endowed_accounts.len() / 2 - initial_authorities.len()) as u32;
|
||||
|
||||
@@ -278,11 +237,6 @@ pub fn testnet_genesis(
|
||||
ids: endowed_accounts.clone(),
|
||||
}),
|
||||
balances: Some(BalancesConfig {
|
||||
transaction_base_fee: 1,
|
||||
transaction_byte_fee: 0,
|
||||
existential_deposit: 500,
|
||||
transfer_fee: 0,
|
||||
creation_fee: 0,
|
||||
balances: endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect(),
|
||||
vesting: vec![],
|
||||
}),
|
||||
@@ -306,46 +260,19 @@ pub fn testnet_genesis(
|
||||
active_council: endowed_accounts.iter()
|
||||
.filter(|&endowed| initial_authorities.iter().find(|&(_, controller, ..)| controller == endowed).is_none())
|
||||
.map(|a| (a.clone(), 1000000)).collect(),
|
||||
candidacy_bond: 10,
|
||||
voter_bond: 2,
|
||||
voting_fee: 5,
|
||||
present_slash_per_voter: 1,
|
||||
carry_count: 4,
|
||||
presentation_duration: 10,
|
||||
approval_voting_period: 20,
|
||||
term_duration: 1000000,
|
||||
desired_seats: council_desired_seats,
|
||||
decay_ratio: council_desired_seats / 3,
|
||||
inactive_grace_period: 1,
|
||||
}),
|
||||
timestamp: Some(TimestampConfig {
|
||||
minimum_period: 2, // 2*2=4 second block time.
|
||||
}),
|
||||
treasury: Some(TreasuryConfig {
|
||||
proposal_bond: Permill::from_percent(5),
|
||||
proposal_bond_minimum: 1_000_000,
|
||||
spend_period: 12 * 60 * 24,
|
||||
burn: Permill::from_percent(50),
|
||||
}),
|
||||
contracts: Some(ContractsConfig {
|
||||
signed_claim_handicap: 2,
|
||||
rent_byte_price: 4,
|
||||
rent_deposit_offset: 1000,
|
||||
storage_size_offset: 8,
|
||||
surcharge_reward: 150,
|
||||
tombstone_deposit: 16,
|
||||
transaction_base_fee: 1,
|
||||
transaction_byte_fee: 0,
|
||||
transfer_fee: 0,
|
||||
creation_fee: 0,
|
||||
contract_fee: 21,
|
||||
gas_price: 1,
|
||||
max_depth: 1024,
|
||||
block_gas_limit: 10_000_000,
|
||||
current_schedule: contracts::Schedule {
|
||||
enable_println, // this should only be enabled on development chains
|
||||
..Default::default()
|
||||
},
|
||||
gas_price: 1 * MILLICENTS,
|
||||
}),
|
||||
sudo: Some(SudoConfig {
|
||||
key: root_key,
|
||||
|
||||
@@ -218,7 +218,7 @@ mod tests {
|
||||
use consensus::CompatibleDigestItem;
|
||||
use consensus_common::{Environment, Proposer, ImportBlock, BlockOrigin, ForkChoiceStrategy};
|
||||
use node_primitives::DigestItem;
|
||||
use node_runtime::{Call, BalancesCall, UncheckedExtrinsic};
|
||||
use node_runtime::{BalancesCall, Call, CENTS, UncheckedExtrinsic};
|
||||
use parity_codec::{Compact, Encode, Decode};
|
||||
use primitives::{
|
||||
crypto::Pair as CryptoPair, ed25519::Pair, blake2_256,
|
||||
@@ -350,7 +350,7 @@ mod tests {
|
||||
|
||||
let mut index = 0;
|
||||
let extrinsic_factory = |service: &SyncService<<Factory as ServiceFactory>::FullService>| {
|
||||
let amount = 1000;
|
||||
let amount = 5 * CENTS;
|
||||
let to = AddressPublic::from_raw(bob.public().0);
|
||||
let from = AddressPublic::from_raw(charlie.public().0);
|
||||
let genesis_hash = service.get().client().block_hash(0).unwrap().unwrap();
|
||||
|
||||
@@ -49,12 +49,15 @@ mod tests {
|
||||
use node_primitives::{Hash, BlockNumber, AccountId};
|
||||
use runtime_primitives::traits::{Header as HeaderT, Hash as HashT};
|
||||
use runtime_primitives::{generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill};
|
||||
use {balances, indices, system, staking, timestamp, treasury, contracts};
|
||||
use {balances, contracts, indices, staking, system, timestamp};
|
||||
use contracts::ContractAddressFor;
|
||||
use system::{EventRecord, Phase};
|
||||
use node_runtime::{Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances,
|
||||
BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, System,
|
||||
SystemConfig, GrandpaConfig, IndicesConfig, Event, SessionKeys, Treasury};
|
||||
use node_runtime::{
|
||||
Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances,
|
||||
BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig,
|
||||
System, SystemConfig, GrandpaConfig, IndicesConfig, ContractsConfig, Event,
|
||||
SessionKeys, Treasury, CENTS, DOLLARS, MILLICENTS
|
||||
};
|
||||
use wabt;
|
||||
use primitives::map;
|
||||
|
||||
@@ -77,6 +80,8 @@ mod tests {
|
||||
|
||||
const GENESIS_HASH: [u8; 32] = [69u8; 32];
|
||||
|
||||
const TX_FEE: u128 = 3 * CENTS + 460 * MILLICENTS;
|
||||
|
||||
type TestExternalities<H> = CoreTestExternalities<H, u64>;
|
||||
|
||||
fn alice() -> AccountId {
|
||||
@@ -131,7 +136,7 @@ mod tests {
|
||||
fn xt() -> UncheckedExtrinsic {
|
||||
sign(CheckedExtrinsic {
|
||||
signed: Some((alice(), 0)),
|
||||
function: Call::Balances(balances::Call::transfer::<Runtime>(bob().into(), 69)),
|
||||
function: Call::Balances(balances::Call::transfer::<Runtime>(bob().into(), 69 * DOLLARS)),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -147,18 +152,9 @@ mod tests {
|
||||
fn panic_execution_with_foreign_code_gives_error() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(BLOATY_CODE, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<indices::NextEnumSet<Runtime>>::key()).to_vec() => {
|
||||
@@ -166,12 +162,6 @@ mod tests {
|
||||
},
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => {
|
||||
vec![0u8; 32]
|
||||
},
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => {
|
||||
vec![70u8; 16]
|
||||
},
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -198,18 +188,9 @@ mod tests {
|
||||
fn bad_extrinsic_with_native_equivalent_code_gives_error() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<indices::NextEnumSet<Runtime>>::key()).to_vec() => {
|
||||
@@ -217,12 +198,6 @@ mod tests {
|
||||
},
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => {
|
||||
vec![0u8; 32]
|
||||
},
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => {
|
||||
vec![70u8; 16]
|
||||
},
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => {
|
||||
vec![0u8; 16]
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -249,18 +224,13 @@ mod tests {
|
||||
fn successful_execution_with_native_equivalent_code_gives_ok() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
(111 * DOLLARS).encode()
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
(111 * DOLLARS).encode()
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<indices::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 16]
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
@@ -281,8 +251,8 @@ mod tests {
|
||||
assert!(r.is_ok());
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Balances::total_balance(&alice()), 42);
|
||||
assert_eq!(Balances::total_balance(&bob()), 69);
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * TX_FEE);
|
||||
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -290,18 +260,13 @@ mod tests {
|
||||
fn successful_execution_with_foreign_code_gives_ok() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(BLOATY_CODE, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
(111 * DOLLARS).encode()
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
(111 * DOLLARS).encode()
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<indices::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 16]
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
@@ -322,8 +287,8 @@ mod tests {
|
||||
assert!(r.is_ok());
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Balances::total_balance(&alice()), 42);
|
||||
assert_eq!(Balances::total_balance(&bob()), 69);
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * TX_FEE);
|
||||
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -346,19 +311,14 @@ mod tests {
|
||||
ids: vec![alice(), bob(), charlie(), dave(), eve(), ferdie()],
|
||||
}),
|
||||
balances: Some(BalancesConfig {
|
||||
transaction_base_fee: 1,
|
||||
transaction_byte_fee: 0,
|
||||
balances: vec![
|
||||
(alice(), 111),
|
||||
(bob(), 100),
|
||||
(charlie(), 100_000_000),
|
||||
(dave(), 111),
|
||||
(eve(), 101),
|
||||
(ferdie(), 100),
|
||||
(alice(), 111 * DOLLARS),
|
||||
(bob(), 100 * DOLLARS),
|
||||
(charlie(), 100_000_000 * DOLLARS),
|
||||
(dave(), 111 * DOLLARS),
|
||||
(eve(), 101 * DOLLARS),
|
||||
(ferdie(), 100 * DOLLARS),
|
||||
],
|
||||
existential_deposit: 0,
|
||||
transfer_fee: 0,
|
||||
creation_fee: 0,
|
||||
vesting: vec![],
|
||||
}),
|
||||
session: Some(SessionConfig {
|
||||
@@ -372,9 +332,9 @@ mod tests {
|
||||
staking: Some(StakingConfig {
|
||||
current_era: 0,
|
||||
stakers: vec![
|
||||
(dave(), alice(), 111, staking::StakerStatus::Validator),
|
||||
(eve(), bob(), 100, staking::StakerStatus::Validator),
|
||||
(ferdie(), charlie(), 100, staking::StakerStatus::Validator)
|
||||
(dave(), alice(), 111 * DOLLARS, staking::StakerStatus::Validator),
|
||||
(eve(), bob(), 100 * DOLLARS, staking::StakerStatus::Validator),
|
||||
(ferdie(), charlie(), 100 * DOLLARS, staking::StakerStatus::Validator)
|
||||
],
|
||||
validator_count: 3,
|
||||
minimum_validator_count: 0,
|
||||
@@ -387,8 +347,10 @@ mod tests {
|
||||
democracy: Some(Default::default()),
|
||||
council_seats: Some(Default::default()),
|
||||
timestamp: Some(Default::default()),
|
||||
treasury: Some(Default::default()),
|
||||
contracts: Some(Default::default()),
|
||||
contracts: Some(ContractsConfig {
|
||||
current_schedule: Default::default(),
|
||||
gas_price: 1 * MILLICENTS,
|
||||
}),
|
||||
sudo: Some(Default::default()),
|
||||
grandpa: Some(GrandpaConfig {
|
||||
authorities: vec![],
|
||||
@@ -469,7 +431,7 @@ mod tests {
|
||||
},
|
||||
CheckedExtrinsic {
|
||||
signed: Some((alice(), 0)),
|
||||
function: Call::Balances(balances::Call::transfer(bob().into(), 69)),
|
||||
function: Call::Balances(balances::Call::transfer(bob().into(), 69 * DOLLARS)),
|
||||
},
|
||||
]
|
||||
)
|
||||
@@ -491,7 +453,7 @@ mod tests {
|
||||
},
|
||||
CheckedExtrinsic {
|
||||
signed: Some((alice(), 0)),
|
||||
function: Call::Balances(balances::Call::transfer(bob().into(), 69)),
|
||||
function: Call::Balances(balances::Call::transfer(bob().into(), 69 * DOLLARS)),
|
||||
},
|
||||
]
|
||||
);
|
||||
@@ -506,11 +468,11 @@ mod tests {
|
||||
},
|
||||
CheckedExtrinsic {
|
||||
signed: Some((bob(), 0)),
|
||||
function: Call::Balances(balances::Call::transfer(alice().into(), 5)),
|
||||
function: Call::Balances(balances::Call::transfer(alice().into(), 5 * DOLLARS)),
|
||||
},
|
||||
CheckedExtrinsic {
|
||||
signed: Some((alice(), 1)),
|
||||
function: Call::Balances(balances::Call::transfer(bob().into(), 15)),
|
||||
function: Call::Balances(balances::Call::transfer(bob().into(), 15 * DOLLARS)),
|
||||
}
|
||||
]
|
||||
);
|
||||
@@ -558,49 +520,21 @@ mod tests {
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
// block1 transfers from alice 69 to bob.
|
||||
// -1 is the default fee
|
||||
assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1);
|
||||
assert_eq!(Balances::total_balance(&bob()), 100 + 69);
|
||||
assert_eq!(System::events(), vec![
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * TX_FEE);
|
||||
assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS);
|
||||
let events = vec![
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: Event::system(system::Event::ExtrinsicSuccess),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(1),
|
||||
event: Event::indices(
|
||||
indices::RawEvent::NewAccountIndex(Treasury::account_id(), 6)
|
||||
),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(1),
|
||||
event: Event::balances(
|
||||
balances::RawEvent::NewAccount(Treasury::account_id(), 0)
|
||||
),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(1),
|
||||
event: Event::indices(
|
||||
indices::RawEvent::NewAccountIndex(Default::default(), 7)
|
||||
),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(1),
|
||||
event: Event::balances(
|
||||
balances::RawEvent::NewAccount(Default::default(), 1)
|
||||
),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(1),
|
||||
event: Event::balances(balances::RawEvent::Transfer(
|
||||
alice().into(),
|
||||
bob().into(),
|
||||
69,
|
||||
0
|
||||
69 * DOLLARS,
|
||||
1 * CENTS
|
||||
)),
|
||||
topics: vec![],
|
||||
},
|
||||
@@ -609,22 +543,8 @@ mod tests {
|
||||
event: Event::system(system::Event::ExtrinsicSuccess),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::Finalization,
|
||||
event: Event::treasury(treasury::RawEvent::Spending(0)),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::Finalization,
|
||||
event: Event::treasury(treasury::RawEvent::Burnt(0)),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::Finalization,
|
||||
event: Event::treasury(treasury::RawEvent::Rollover(0)),
|
||||
topics: vec![],
|
||||
},
|
||||
]);
|
||||
];
|
||||
assert_eq!(System::events(), events);
|
||||
});
|
||||
|
||||
executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
@@ -637,11 +557,11 @@ mod tests {
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
// bob sends 5, alice sends 15 | bob += 10, alice -= 10
|
||||
// 111 - 69 - 1 - 10 - 1 = 30
|
||||
assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1 - 10 - 1);
|
||||
// 100 + 69 + 10 - 1 = 178
|
||||
assert_eq!(Balances::total_balance(&bob()), 100 + 69 + 10 - 1);
|
||||
assert_eq!(System::events(), vec![
|
||||
// 111 - 69 - 10 = 32
|
||||
assert_eq!(Balances::total_balance(&alice()), 32 * DOLLARS - 2 * TX_FEE);
|
||||
// 100 + 69 + 10 = 179
|
||||
assert_eq!(Balances::total_balance(&bob()), 179 * DOLLARS - 1 * TX_FEE);
|
||||
let events = vec![
|
||||
EventRecord {
|
||||
phase: Phase::ApplyExtrinsic(0),
|
||||
event: Event::system(system::Event::ExtrinsicSuccess),
|
||||
@@ -653,8 +573,8 @@ mod tests {
|
||||
balances::RawEvent::Transfer(
|
||||
bob().into(),
|
||||
alice().into(),
|
||||
5,
|
||||
0
|
||||
5 * DOLLARS,
|
||||
1 * CENTS,
|
||||
)
|
||||
),
|
||||
topics: vec![],
|
||||
@@ -670,8 +590,8 @@ mod tests {
|
||||
balances::RawEvent::Transfer(
|
||||
alice().into(),
|
||||
bob().into(),
|
||||
15,
|
||||
0
|
||||
15 * DOLLARS,
|
||||
1 * CENTS,
|
||||
)
|
||||
),
|
||||
topics: vec![],
|
||||
@@ -681,22 +601,8 @@ mod tests {
|
||||
event: Event::system(system::Event::ExtrinsicSuccess),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::Finalization,
|
||||
event: Event::treasury(treasury::RawEvent::Spending(0)),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::Finalization,
|
||||
event: Event::treasury(treasury::RawEvent::Burnt(0)),
|
||||
topics: vec![],
|
||||
},
|
||||
EventRecord {
|
||||
phase: Phase::Finalization,
|
||||
event: Event::treasury(treasury::RawEvent::Rollover(0)),
|
||||
topics: vec![],
|
||||
},
|
||||
]);
|
||||
];
|
||||
assert_eq!(System::events(), events);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -710,19 +616,18 @@ mod tests {
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
// block1 transfers from alice 69 to bob.
|
||||
// -1 is the default fee
|
||||
assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1);
|
||||
assert_eq!(Balances::total_balance(&bob()), 100 + 69);
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * TX_FEE);
|
||||
assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS);
|
||||
});
|
||||
|
||||
WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block2.0).unwrap();
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
// bob sends 5, alice sends 15 | bob += 10, alice -= 10
|
||||
// 111 - 69 - 1 - 10 - 1 = 30
|
||||
assert_eq!(Balances::total_balance(&alice()), 111 - 69 - 1 - 10 - 1);
|
||||
// 100 + 69 + 10 - 1 = 178
|
||||
assert_eq!(Balances::total_balance(&bob()), 100 + 69 + 10 - 1);
|
||||
// 111 - 69 - 10 = 32
|
||||
assert_eq!(Balances::total_balance(&alice()), 32 * DOLLARS - 2 * TX_FEE);
|
||||
// 100 + 69 + 10 = 179
|
||||
assert_eq!(Balances::total_balance(&bob()), 179 * DOLLARS - 1 * TX_FEE);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -848,7 +753,7 @@ mod tests {
|
||||
CheckedExtrinsic {
|
||||
signed: Some((charlie(), 1)),
|
||||
function: Call::Contracts(
|
||||
contracts::Call::create::<Runtime>(10, 10_000, transfer_ch, Vec::new())
|
||||
contracts::Call::create::<Runtime>(1 * DOLLARS, 10_000, transfer_ch, Vec::new())
|
||||
),
|
||||
},
|
||||
CheckedExtrinsic {
|
||||
@@ -928,18 +833,13 @@ mod tests {
|
||||
fn panic_execution_gives_error() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(BLOATY_CODE, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
vec![0u8; 16]
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<indices::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![70u8; 16],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 16]
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = WasmExecutor::new()
|
||||
@@ -955,18 +855,13 @@ mod tests {
|
||||
fn successful_execution_gives_ok() {
|
||||
let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, map![
|
||||
blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
(111 * DOLLARS).encode()
|
||||
},
|
||||
twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => {
|
||||
vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
(111 * DOLLARS).encode()
|
||||
},
|
||||
twox_128(<balances::ExistentialDeposit<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::CreationFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransferFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<indices::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32],
|
||||
twox_128(<balances::TransactionBaseFee<Runtime>>::key()).to_vec() => vec![0u8; 16],
|
||||
twox_128(<balances::TransactionByteFee<Runtime>>::key()).to_vec() => vec![0u8; 16]
|
||||
blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = WasmExecutor::new()
|
||||
@@ -978,8 +873,8 @@ mod tests {
|
||||
assert_eq!(r, Ok(ApplyOutcome::Success));
|
||||
|
||||
runtime_io::with_externalities(&mut t, || {
|
||||
assert_eq!(Balances::total_balance(&alice()), 42);
|
||||
assert_eq!(Balances::total_balance(&bob()), 69);
|
||||
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * TX_FEE);
|
||||
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,9 @@ pub type AccountIndex = u32;
|
||||
/// Balance of an account.
|
||||
pub type Balance = u128;
|
||||
|
||||
/// Type used for expressing timestamp.
|
||||
pub type Moment = u64;
|
||||
|
||||
/// Alias to the signature scheme used for Aura authority signatures.
|
||||
pub type AuraSignature = primitives::ed25519::Signature;
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ use support::{
|
||||
};
|
||||
use substrate_primitives::u32_trait::{_1, _2, _3, _4};
|
||||
use node_primitives::{
|
||||
AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, Signature, AuraId
|
||||
AccountId, AccountIndex, AuraId, Balance, BlockNumber, Hash, Index,
|
||||
Moment, Signature,
|
||||
};
|
||||
use grandpa::fg_primitives::{self, ScheduledChange};
|
||||
use client::{
|
||||
@@ -39,18 +40,20 @@ use runtime_primitives::traits::{
|
||||
BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, Convert,
|
||||
};
|
||||
use version::RuntimeVersion;
|
||||
use council::{motions as council_motions};
|
||||
use council::{motions as council_motions, VoteIndex};
|
||||
#[cfg(feature = "std")]
|
||||
use council::seats as council_seats;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
use version::NativeVersion;
|
||||
use substrate_primitives::OpaqueMetadata;
|
||||
use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight};
|
||||
use finality_tracker::{DEFAULT_REPORT_LATENCY, DEFAULT_WINDOW_SIZE};
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub use runtime_primitives::BuildStorage;
|
||||
pub use timestamp::Call as TimestampCall;
|
||||
pub use balances::Call as BalancesCall;
|
||||
pub use contracts::Gas;
|
||||
pub use runtime_primitives::{Permill, Perbill, impl_opaque_keys};
|
||||
pub use support::StorageValue;
|
||||
pub use staking::StakerStatus;
|
||||
@@ -60,8 +63,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
spec_name: create_runtime_str!("node"),
|
||||
impl_name: create_runtime_str!("substrate-node"),
|
||||
authoring_version: 10,
|
||||
spec_version: 100,
|
||||
impl_version: 100,
|
||||
spec_version: 101,
|
||||
impl_version: 101,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
};
|
||||
|
||||
@@ -74,6 +77,10 @@ pub fn native_version() -> NativeVersion {
|
||||
}
|
||||
}
|
||||
|
||||
pub const MILLICENTS: Balance = 1_000_000_000;
|
||||
pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent.
|
||||
pub const DOLLARS: Balance = 100 * CENTS;
|
||||
|
||||
type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
|
||||
|
||||
pub struct Author;
|
||||
@@ -91,19 +98,10 @@ pub type DealWithFees = SplitTwoWays<
|
||||
_1, Author, // 1 part (20%) goes to the block author.
|
||||
>;
|
||||
|
||||
pub struct CurrencyToVoteHandler;
|
||||
|
||||
impl CurrencyToVoteHandler {
|
||||
fn factor() -> u128 { (Balances::total_issuance() / u64::max_value() as u128).max(1) }
|
||||
}
|
||||
|
||||
impl Convert<u128, u64> for CurrencyToVoteHandler {
|
||||
fn convert(x: u128) -> u64 { (x / Self::factor()) as u64 }
|
||||
}
|
||||
|
||||
impl Convert<u128, u128> for CurrencyToVoteHandler {
|
||||
fn convert(x: u128) -> u128 { x * Self::factor() }
|
||||
}
|
||||
pub const SECS_PER_BLOCK: Moment = 6;
|
||||
pub const MINUTES: Moment = 60 / SECS_PER_BLOCK;
|
||||
pub const HOURS: Moment = MINUTES * 60;
|
||||
pub const DAYS: Moment = HOURS * 24;
|
||||
|
||||
impl system::Trait for Runtime {
|
||||
type Origin = Origin;
|
||||
@@ -129,6 +127,14 @@ impl indices::Trait for Runtime {
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: Balance = 1 * DOLLARS;
|
||||
pub const TransferFee: Balance = 1 * CENTS;
|
||||
pub const CreationFee: Balance = 1 * CENTS;
|
||||
pub const TransactionBaseFee: Balance = 1 * CENTS;
|
||||
pub const TransactionByteFee: Balance = 10 * MILLICENTS;
|
||||
}
|
||||
|
||||
impl balances::Trait for Runtime {
|
||||
type Balance = Balance;
|
||||
type OnFreeBalanceZero = ((Staking, Contracts), Session);
|
||||
@@ -137,10 +143,15 @@ impl balances::Trait for Runtime {
|
||||
type TransactionPayment = DealWithFees;
|
||||
type DustRemoval = ();
|
||||
type TransferPayment = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
}
|
||||
|
||||
impl timestamp::Trait for Runtime {
|
||||
type Moment = u64;
|
||||
type Moment = Moment;
|
||||
type OnTimestampSet = Aura;
|
||||
}
|
||||
|
||||
@@ -185,6 +196,20 @@ parameter_types! {
|
||||
pub const BondingDuration: staking::EraIndex = 24 * 28;
|
||||
}
|
||||
|
||||
pub struct CurrencyToVoteHandler;
|
||||
|
||||
impl CurrencyToVoteHandler {
|
||||
fn factor() -> u128 { (Balances::total_issuance() / u64::max_value() as u128).max(1) }
|
||||
}
|
||||
|
||||
impl Convert<u128, u64> for CurrencyToVoteHandler {
|
||||
fn convert(x: u128) -> u64 { (x / Self::factor()) as u64 }
|
||||
}
|
||||
|
||||
impl Convert<u128, u128> for CurrencyToVoteHandler {
|
||||
fn convert(x: u128) -> u128 { x * Self::factor() }
|
||||
}
|
||||
|
||||
impl staking::Trait for Runtime {
|
||||
type Currency = Balances;
|
||||
type CurrencyToVote = CurrencyToVoteHandler;
|
||||
@@ -196,14 +221,11 @@ impl staking::Trait for Runtime {
|
||||
type BondingDuration = BondingDuration;
|
||||
}
|
||||
|
||||
const MINUTES: BlockNumber = 6;
|
||||
const BUCKS: Balance = 1_000_000_000_000;
|
||||
|
||||
parameter_types! {
|
||||
pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
|
||||
pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
|
||||
pub const EmergencyVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES;
|
||||
pub const MinimumDeposit: Balance = 100 * BUCKS;
|
||||
pub const MinimumDeposit: Balance = 100 * DOLLARS;
|
||||
pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES;
|
||||
pub const CooloffPeriod: BlockNumber = 30 * 24 * 60 * MINUTES;
|
||||
}
|
||||
@@ -225,6 +247,18 @@ impl democracy::Trait for Runtime {
|
||||
type CooloffPeriod = CooloffPeriod;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const CandidacyBond: Balance = 10 * DOLLARS;
|
||||
pub const VotingBond: Balance = 1 * DOLLARS;
|
||||
pub const VotingFee: Balance = 2 * DOLLARS;
|
||||
pub const PresentSlashPerVoter: Balance = 1 * CENTS;
|
||||
pub const CarryCount: u32 = 6;
|
||||
// one additional vote should go by before an inactive voter can be reaped.
|
||||
pub const InactiveGracePeriod: VoteIndex = 1;
|
||||
pub const CouncilVotingPeriod: BlockNumber = 2 * DAYS;
|
||||
pub const DecayRatio: u32 = 0;
|
||||
}
|
||||
|
||||
impl council::Trait for Runtime {
|
||||
type Event = Event;
|
||||
type BadPresentation = ();
|
||||
@@ -232,6 +266,14 @@ impl council::Trait for Runtime {
|
||||
type BadVoterIndex = ();
|
||||
type LoserCandidate = ();
|
||||
type OnMembersChanged = CouncilMotions;
|
||||
type CandidacyBond = CandidacyBond;
|
||||
type VotingBond = VotingBond;
|
||||
type VotingFee = VotingFee;
|
||||
type PresentSlashPerVoter = PresentSlashPerVoter;
|
||||
type CarryCount = CarryCount;
|
||||
type InactiveGracePeriod = InactiveGracePeriod;
|
||||
type CouncilVotingPeriod = CouncilVotingPeriod;
|
||||
type DecayRatio = DecayRatio;
|
||||
}
|
||||
|
||||
impl council::motions::Trait for Runtime {
|
||||
@@ -240,6 +282,13 @@ impl council::motions::Trait for Runtime {
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const ProposalBond: Permill = Permill::from_percent(5);
|
||||
pub const ProposalBondMinimum: Balance = 1 * DOLLARS;
|
||||
pub const SpendPeriod: BlockNumber = 1 * DAYS;
|
||||
pub const Burn: Permill = Permill::from_percent(50);
|
||||
}
|
||||
|
||||
impl treasury::Trait for Runtime {
|
||||
type Currency = Balances;
|
||||
type ApproveOrigin = council_motions::EnsureMembers<_4, AccountId>;
|
||||
@@ -247,6 +296,28 @@ impl treasury::Trait for Runtime {
|
||||
type Event = Event;
|
||||
type MintedForSpending = ();
|
||||
type ProposalRejection = ();
|
||||
type ProposalBond = ProposalBond;
|
||||
type ProposalBondMinimum = ProposalBondMinimum;
|
||||
type SpendPeriod = SpendPeriod;
|
||||
type Burn = Burn;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const SignedClaimHandicap: BlockNumber = 2;
|
||||
pub const TombstoneDeposit: Balance = 16;
|
||||
pub const StorageSizeOffset: u32 = 8;
|
||||
pub const RentByteFee: Balance = 4;
|
||||
pub const RentDepositOffset: Balance = 1000;
|
||||
pub const SurchargeReward: Balance = 150;
|
||||
pub const ContractTransferFee: Balance = 1 * CENTS;
|
||||
pub const ContractCreationFee: Balance = 1 * CENTS;
|
||||
pub const ContractTransactionBaseFee: Balance = 1 * CENTS;
|
||||
pub const ContractTransactionByteFee: Balance = 10 * MILLICENTS;
|
||||
pub const ContractFee: Balance = 1 * CENTS;
|
||||
pub const CallBaseFee: Gas = 1000;
|
||||
pub const CreateBaseFee: Gas = 1000;
|
||||
pub const MaxDepth: u32 = 1024;
|
||||
pub const BlockGasLimit: Gas = 10_000_000;
|
||||
}
|
||||
|
||||
impl contracts::Trait for Runtime {
|
||||
@@ -257,6 +328,21 @@ impl contracts::Trait for Runtime {
|
||||
type ComputeDispatchFee = contracts::DefaultDispatchFeeComputor<Runtime>;
|
||||
type TrieIdGenerator = contracts::TrieIdFromParentCounter<Runtime>;
|
||||
type GasPayment = ();
|
||||
type SignedClaimHandicap = SignedClaimHandicap;
|
||||
type TombstoneDeposit = TombstoneDeposit;
|
||||
type StorageSizeOffset = StorageSizeOffset;
|
||||
type RentByteFee = RentByteFee;
|
||||
type RentDepositOffset = RentDepositOffset;
|
||||
type SurchargeReward = SurchargeReward;
|
||||
type TransferFee = ContractTransferFee;
|
||||
type CreationFee = ContractCreationFee;
|
||||
type TransactionBaseFee = ContractTransactionBaseFee;
|
||||
type TransactionByteFee = ContractTransactionByteFee;
|
||||
type ContractFee = ContractFee;
|
||||
type CallBaseFee = CallBaseFee;
|
||||
type CreateBaseFee = CreateBaseFee;
|
||||
type MaxDepth = MaxDepth;
|
||||
type BlockGasLimit = BlockGasLimit;
|
||||
}
|
||||
|
||||
impl sudo::Trait for Runtime {
|
||||
@@ -268,8 +354,15 @@ impl grandpa::Trait for Runtime {
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const WindowSize: BlockNumber = DEFAULT_WINDOW_SIZE.into();
|
||||
pub const ReportLatency: BlockNumber = DEFAULT_REPORT_LATENCY.into();
|
||||
}
|
||||
|
||||
impl finality_tracker::Trait for Runtime {
|
||||
type OnFinalizationStalled = Grandpa;
|
||||
type WindowSize = WindowSize;
|
||||
type ReportLatency = ReportLatency;
|
||||
}
|
||||
|
||||
construct_runtime!(
|
||||
@@ -292,7 +385,7 @@ construct_runtime!(
|
||||
CouncilSeats: council_seats::{Config<T>},
|
||||
FinalityTracker: finality_tracker::{Module, Call, Inherent},
|
||||
Grandpa: grandpa::{Module, Call, Storage, Config, Event},
|
||||
Treasury: treasury,
|
||||
Treasury: treasury::{Module, Call, Storage, Event<T>},
|
||||
Contracts: contracts,
|
||||
Sudo: sudo,
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ use srml_support::traits::{
|
||||
WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement,
|
||||
Imbalance, SignedImbalance, ReservableCurrency
|
||||
};
|
||||
use srml_support::dispatch::Result;
|
||||
use srml_support::{dispatch::Result, traits::Get};
|
||||
use primitives::traits::{
|
||||
Zero, SimpleArithmetic, StaticLookup, Member, CheckedAdd, CheckedSub,
|
||||
MaybeSerializeDebug, Saturating, Bounded
|
||||
@@ -170,6 +170,12 @@ mod tests;
|
||||
|
||||
pub use self::imbalances::{PositiveImbalance, NegativeImbalance};
|
||||
|
||||
pub const DEFAULT_EXISTENTIAL_DEPOSIT: u32 = 0;
|
||||
pub const DEFAULT_TRANSFER_FEE: u32 = 0;
|
||||
pub const DEFAULT_CREATION_FEE: u32 = 0;
|
||||
pub const DEFAULT_TRANSACTION_BASE_FEE: u32 = 0;
|
||||
pub const DEFAULT_TRANSACTION_BYTE_FEE: u32 = 0;
|
||||
|
||||
pub trait Subtrait<I: Instance = DefaultInstance>: system::Trait {
|
||||
/// The balance of an account.
|
||||
type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy +
|
||||
@@ -183,6 +189,21 @@ pub trait Subtrait<I: Instance = DefaultInstance>: system::Trait {
|
||||
|
||||
/// Handler for when a new account is created.
|
||||
type OnNewAccount: OnNewAccount<Self::AccountId>;
|
||||
|
||||
/// The minimum amount required to keep an account open.
|
||||
type ExistentialDeposit: Get<Self::Balance>;
|
||||
|
||||
/// The fee required to make a transfer.
|
||||
type TransferFee: Get<Self::Balance>;
|
||||
|
||||
/// The fee required to create an account.
|
||||
type CreationFee: Get<Self::Balance>;
|
||||
|
||||
/// The fee to be paid for making a transaction; the base.
|
||||
type TransactionBaseFee: Get<Self::Balance>;
|
||||
|
||||
/// The fee to be paid for making a transaction; the per-byte portion.
|
||||
type TransactionByteFee: Get<Self::Balance>;
|
||||
}
|
||||
|
||||
pub trait Trait<I: Instance = DefaultInstance>: system::Trait {
|
||||
@@ -211,12 +232,32 @@ pub trait Trait<I: Instance = DefaultInstance>: system::Trait {
|
||||
|
||||
/// The overarching event type.
|
||||
type Event: From<Event<Self, I>> + Into<<Self as system::Trait>::Event>;
|
||||
|
||||
/// The minimum amount required to keep an account open.
|
||||
type ExistentialDeposit: Get<Self::Balance>;
|
||||
|
||||
/// The fee required to make a transfer.
|
||||
type TransferFee: Get<Self::Balance>;
|
||||
|
||||
/// The fee required to create an account.
|
||||
type CreationFee: Get<Self::Balance>;
|
||||
|
||||
/// The fee to be paid for making a transaction; the base.
|
||||
type TransactionBaseFee: Get<Self::Balance>;
|
||||
|
||||
/// The fee to be paid for making a transaction; the per-byte portion.
|
||||
type TransactionByteFee: Get<Self::Balance>;
|
||||
}
|
||||
|
||||
impl<T: Trait<I>, I: Instance> Subtrait<I> for T {
|
||||
type Balance = T::Balance;
|
||||
type OnFreeBalanceZero = T::OnFreeBalanceZero;
|
||||
type OnNewAccount = T::OnNewAccount;
|
||||
type ExistentialDeposit = T::ExistentialDeposit;
|
||||
type TransferFee = T::TransferFee;
|
||||
type CreationFee = T::CreationFee;
|
||||
type TransactionBaseFee = T::TransactionBaseFee;
|
||||
type TransactionByteFee = T::TransactionByteFee;
|
||||
}
|
||||
|
||||
decl_event!(
|
||||
@@ -271,16 +312,6 @@ decl_storage! {
|
||||
pub TotalIssuance get(total_issuance) build(|config: &GenesisConfig<T, I>| {
|
||||
config.balances.iter().fold(Zero::zero(), |acc: T::Balance, &(_, n)| acc + n)
|
||||
}): T::Balance;
|
||||
/// The minimum amount required to keep an account open.
|
||||
pub ExistentialDeposit get(existential_deposit) config(): T::Balance;
|
||||
/// The fee required to make a transfer.
|
||||
pub TransferFee get(transfer_fee) config(): T::Balance;
|
||||
/// The fee required to create an account.
|
||||
pub CreationFee get(creation_fee) config(): T::Balance;
|
||||
/// The fee to be paid for making a transaction; the base.
|
||||
pub TransactionBaseFee get(transaction_base_fee) config(): T::Balance;
|
||||
/// The fee to be paid for making a transaction; the per-byte portion.
|
||||
pub TransactionByteFee get(transaction_byte_fee) config(): T::Balance;
|
||||
|
||||
/// Information regarding the vesting of a given account.
|
||||
pub Vesting get(vesting) build(|config: &GenesisConfig<T, I>| {
|
||||
@@ -341,6 +372,21 @@ decl_storage! {
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait<I>, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {
|
||||
/// The minimum amount required to keep an account open.
|
||||
const ExistentialDeposit: T::Balance = T::ExistentialDeposit::get();
|
||||
|
||||
/// The fee required to make a transfer.
|
||||
const TransferFee: T::Balance = T::TransferFee::get();
|
||||
|
||||
/// The fee required to create an account.
|
||||
const CreationFee: T::Balance = T::CreationFee::get();
|
||||
|
||||
/// The fee to be paid for making a transaction; the base.
|
||||
const TransactionBaseFee: T::Balance = T::TransactionBaseFee::get();
|
||||
|
||||
/// The fee to be paid for making a transaction; the per-byte portion.
|
||||
const TransactionByteFee: T::Balance = T::TransactionByteFee::get();
|
||||
|
||||
fn deposit_event<T, I>() = default;
|
||||
|
||||
/// Transfer some liquid free balance to another account.
|
||||
@@ -440,7 +486,7 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
|
||||
/// NOTE: LOW-LEVEL: This will not attempt to maintain total issuance. It is expected that
|
||||
/// the caller will do this.
|
||||
fn set_reserved_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome {
|
||||
if balance < Self::existential_deposit() {
|
||||
if balance < T::ExistentialDeposit::get() {
|
||||
<ReservedBalance<T, I>>::insert(who, balance);
|
||||
Self::on_reserved_too_low(who);
|
||||
UpdateBalanceOutcome::AccountKilled
|
||||
@@ -461,8 +507,8 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
|
||||
fn set_free_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome {
|
||||
// Commented out for now - but consider it instructive.
|
||||
// assert!(!Self::total_balance(who).is_zero());
|
||||
// assert!(Self::free_balance(who) > Self::existential_deposit());
|
||||
if balance < Self::existential_deposit() {
|
||||
// assert!(Self::free_balance(who) > T::ExistentialDeposit::get());
|
||||
if balance < T::ExistentialDeposit::get() {
|
||||
<FreeBalance<T, I>>::insert(who, balance);
|
||||
Self::on_free_too_low(who);
|
||||
UpdateBalanceOutcome::AccountKilled
|
||||
@@ -707,6 +753,11 @@ impl<T: Subtrait<I>, I: Instance> Trait<I> for ElevatedTrait<T, I> {
|
||||
type TransactionPayment = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = T::ExistentialDeposit;
|
||||
type TransferFee = T::TransferFee;
|
||||
type CreationFee = T::CreationFee;
|
||||
type TransactionBaseFee = T::TransactionBaseFee;
|
||||
type TransactionByteFee = T::TransactionByteFee;
|
||||
}
|
||||
|
||||
impl<T: Trait<I>, I: Instance> Currency<T::AccountId> for Module<T, I>
|
||||
@@ -730,7 +781,7 @@ where
|
||||
}
|
||||
|
||||
fn minimum_balance() -> Self::Balance {
|
||||
Self::existential_deposit()
|
||||
T::ExistentialDeposit::get()
|
||||
}
|
||||
|
||||
fn free_balance(who: &T::AccountId) -> Self::Balance {
|
||||
@@ -795,7 +846,7 @@ where
|
||||
let from_balance = Self::free_balance(transactor);
|
||||
let to_balance = Self::free_balance(dest);
|
||||
let would_create = to_balance.is_zero();
|
||||
let fee = if would_create { Self::creation_fee() } else { Self::transfer_fee() };
|
||||
let fee = if would_create { T::CreationFee::get() } else { T::TransferFee::get() };
|
||||
let liability = match value.checked_add(&fee) {
|
||||
Some(l) => l,
|
||||
None => return Err("got overflow after adding a fee to value"),
|
||||
@@ -805,7 +856,7 @@ where
|
||||
None => return Err("balance too low to send value"),
|
||||
Some(b) => b,
|
||||
};
|
||||
if would_create && value < Self::existential_deposit() {
|
||||
if would_create && value < T::ExistentialDeposit::get() {
|
||||
return Err("value too low to create account");
|
||||
}
|
||||
Self::ensure_can_withdraw(transactor, value, WithdrawReason::Transfer, new_from_balance)?;
|
||||
@@ -837,7 +888,7 @@ where
|
||||
liveness: ExistenceRequirement,
|
||||
) -> result::Result<Self::NegativeImbalance, &'static str> {
|
||||
if let Some(new_balance) = Self::free_balance(who).checked_sub(&value) {
|
||||
if liveness == ExistenceRequirement::KeepAlive && new_balance < Self::existential_deposit() {
|
||||
if liveness == ExistenceRequirement::KeepAlive && new_balance < T::ExistentialDeposit::get() {
|
||||
return Err("payment would kill account")
|
||||
}
|
||||
Self::ensure_can_withdraw(who, value, reason, new_balance)?;
|
||||
@@ -899,7 +950,7 @@ where
|
||||
UpdateBalanceOutcome
|
||||
) {
|
||||
let original = Self::free_balance(who);
|
||||
if balance < Self::existential_deposit() && original.is_zero() {
|
||||
if balance < T::ExistentialDeposit::get() && original.is_zero() {
|
||||
// If we're attempting to set an existing account to less than ED, then
|
||||
// bypass the entire operation. It's a no-op if you follow it through, but
|
||||
// since this is an instance where we might account for a negative imbalance
|
||||
@@ -925,7 +976,7 @@ where
|
||||
// Free balance can never be less than ED. If that happens, it gets reduced to zero
|
||||
// and the account information relevant to this subsystem is deleted (i.e. the
|
||||
// account is reaped).
|
||||
let outcome = if balance < <Module<T, I>>::existential_deposit() {
|
||||
let outcome = if balance < T::ExistentialDeposit::get() {
|
||||
Self::set_free_balance(who, balance);
|
||||
UpdateBalanceOutcome::AccountKilled
|
||||
} else {
|
||||
@@ -1079,7 +1130,7 @@ where
|
||||
impl<T: Trait<I>, I: Instance> MakePayment<T::AccountId> for Module<T, I> {
|
||||
fn make_payment(transactor: &T::AccountId, encoded_len: usize) -> Result {
|
||||
let encoded_len = T::Balance::from(encoded_len as u32);
|
||||
let transaction_fee = Self::transaction_base_fee() + Self::transaction_byte_fee() * encoded_len;
|
||||
let transaction_fee = T::TransactionBaseFee::get() + T::TransactionByteFee::get() * encoded_len;
|
||||
let imbalance = Self::withdraw(
|
||||
transactor,
|
||||
transaction_fee,
|
||||
|
||||
@@ -21,13 +21,47 @@
|
||||
use primitives::{traits::{IdentityLookup}, testing::Header};
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
use runtime_io;
|
||||
use srml_support::impl_outer_origin;
|
||||
use srml_support::{impl_outer_origin, traits::Get};
|
||||
use std::cell::RefCell;
|
||||
use crate::{GenesisConfig, Module, Trait};
|
||||
|
||||
impl_outer_origin!{
|
||||
pub enum Origin for Runtime {}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static EXISTENTIAL_DEPOSIT: RefCell<u64> = RefCell::new(0);
|
||||
static TRANSFER_FEE: RefCell<u64> = RefCell::new(0);
|
||||
static CREATION_FEE: RefCell<u64> = RefCell::new(0);
|
||||
static TRANSACTION_BASE_FEE: RefCell<u64> = RefCell::new(0);
|
||||
static TRANSACTION_BYTE_FEE: RefCell<u64> = RefCell::new(0);
|
||||
}
|
||||
|
||||
pub struct ExistentialDeposit;
|
||||
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()) }
|
||||
}
|
||||
|
||||
pub struct TransactionBaseFee;
|
||||
impl Get<u64> for TransactionBaseFee {
|
||||
fn get() -> u64 { TRANSACTION_BASE_FEE.with(|v| *v.borrow()) }
|
||||
}
|
||||
|
||||
pub struct TransactionByteFee;
|
||||
impl Get<u64> for TransactionByteFee {
|
||||
fn get() -> u64 { TRANSACTION_BYTE_FEE.with(|v| *v.borrow()) }
|
||||
}
|
||||
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Runtime;
|
||||
@@ -50,6 +84,11 @@ impl Trait for Runtime {
|
||||
type TransactionPayment = ();
|
||||
type DustRemoval = ();
|
||||
type TransferPayment = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
}
|
||||
|
||||
pub struct ExtBuilder {
|
||||
@@ -104,19 +143,22 @@ impl ExtBuilder {
|
||||
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);
|
||||
TRANSACTION_BASE_FEE.with(|v| *v.borrow_mut() = self.transaction_base_fee);
|
||||
TRANSACTION_BYTE_FEE.with(|v| *v.borrow_mut() = self.transaction_byte_fee);
|
||||
}
|
||||
pub fn build(self) -> runtime_io::TestExternalities<Blake2Hasher> {
|
||||
self.set_associated_consts();
|
||||
let mut t = system::GenesisConfig::default().build_storage::<Runtime>().unwrap().0;
|
||||
t.extend(GenesisConfig::<Runtime> {
|
||||
transaction_base_fee: self.transaction_base_fee,
|
||||
transaction_byte_fee: self.transaction_byte_fee,
|
||||
balances: if self.monied {
|
||||
vec![(1, 10 * self.existential_deposit), (2, 20 * self.existential_deposit), (3, 30 * self.existential_deposit), (4, 40 * self.existential_deposit)]
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
existential_deposit: self.existential_deposit,
|
||||
transfer_fee: self.transfer_fee,
|
||||
creation_fee: self.creation_fee,
|
||||
vesting: if self.vesting && self.monied {
|
||||
vec![(1, 0, 10), (2, 10, 20)]
|
||||
} else {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Auxilliaries to help with managing partial changes to accounts state.
|
||||
|
||||
use super::{
|
||||
AliveContractInfo, BalanceOf, CodeHash, ContractInfo, ContractInfoOf, Module, Trait, TrieId,
|
||||
AliveContractInfo, BalanceOf, CodeHash, ContractInfo, ContractInfoOf, Trait, TrieId,
|
||||
TrieIdGenerator,
|
||||
};
|
||||
use crate::exec::StorageKey;
|
||||
@@ -26,7 +26,7 @@ use rstd::collections::btree_map::{BTreeMap, Entry};
|
||||
use rstd::prelude::*;
|
||||
use runtime_io::blake2_256;
|
||||
use runtime_primitives::traits::{Bounded, Zero};
|
||||
use srml_support::traits::{Currency, Imbalance, SignedImbalance, UpdateBalanceOutcome};
|
||||
use srml_support::traits::{Currency, Get, Imbalance, SignedImbalance, UpdateBalanceOutcome};
|
||||
use srml_support::{storage::child, StorageMap};
|
||||
use system;
|
||||
|
||||
@@ -125,7 +125,7 @@ impl<T: Trait> AccountDb<T> for DirectAccountDb {
|
||||
} else if let Some(code_hash) = changed.code_hash {
|
||||
AliveContractInfo::<T> {
|
||||
code_hash,
|
||||
storage_size: <Module<T>>::storage_size_offset(),
|
||||
storage_size: T::StorageSizeOffset::get(),
|
||||
trie_id: <T as Trait>::TrieIdGenerator::trie_id(&address),
|
||||
deduct_block: <system::Module<T>>::block_number(),
|
||||
rent_allowance: <BalanceOf<T>>::max_value(),
|
||||
|
||||
@@ -18,7 +18,8 @@ use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf};
|
||||
use rstd::convert::TryFrom;
|
||||
use runtime_primitives::BLOCK_FULL;
|
||||
use runtime_primitives::traits::{CheckedMul, Zero, SaturatedConversion, SimpleArithmetic, UniqueSaturatedInto};
|
||||
use srml_support::{StorageValue, traits::{OnUnbalanced, ExistenceRequirement, WithdrawReason, Currency, Imbalance}};
|
||||
use srml_support::StorageValue;
|
||||
use srml_support::traits::{Currency, ExistenceRequirement, Get, Imbalance, OnUnbalanced, WithdrawReason};
|
||||
|
||||
#[cfg(test)]
|
||||
use std::{any::Any, fmt::Debug};
|
||||
@@ -200,8 +201,8 @@ pub fn buy_gas<T: Trait>(
|
||||
gas_limit: Gas,
|
||||
) -> Result<(GasMeter<T>, NegativeImbalanceOf<T>), &'static str> {
|
||||
// Check if the specified amount of gas is available in the current block.
|
||||
// This cannot underflow since `gas_spent` is never greater than `block_gas_limit`.
|
||||
let gas_available = <Module<T>>::block_gas_limit() - <Module<T>>::gas_spent();
|
||||
// This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`.
|
||||
let gas_available = T::BlockGasLimit::get() - <Module<T>>::gas_spent();
|
||||
if gas_limit > gas_available {
|
||||
// gas limit reached, revert the transaction and retry again in the future
|
||||
return Err(BLOCK_FULL);
|
||||
|
||||
@@ -90,7 +90,7 @@ mod tests;
|
||||
|
||||
use crate::exec::ExecutionContext;
|
||||
use crate::account_db::{AccountDb, DirectAccountDb};
|
||||
use crate::gas::Gas;
|
||||
pub use crate::gas::Gas;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use serde::{Serialize, Deserialize};
|
||||
@@ -105,7 +105,7 @@ use srml_support::dispatch::{Result, Dispatchable};
|
||||
use srml_support::{
|
||||
Parameter, StorageMap, StorageValue, decl_module, decl_event, decl_storage, storage::child
|
||||
};
|
||||
use srml_support::traits::{OnFreeBalanceZero, OnUnbalanced, Currency};
|
||||
use srml_support::traits::{OnFreeBalanceZero, OnUnbalanced, Currency, Get};
|
||||
use system::{ensure_signed, RawOrigin};
|
||||
use substrate_primitives::storage::well_known_keys::CHILD_STORAGE_KEY_PREFIX;
|
||||
use timestamp;
|
||||
@@ -279,6 +279,22 @@ pub type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::Trait>
|
||||
pub type NegativeImbalanceOf<T> =
|
||||
<<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::NegativeImbalance;
|
||||
|
||||
pub const DEFAULT_SIGNED_CLAIM_HANDICAP: u32 = 0;
|
||||
pub const DEFAULT_TOMBSTONE_DEPOSIT: u32 = 0;
|
||||
pub const DEFAULT_STORAGE_SIZE_OFFSET: u32 = 0;
|
||||
pub const DEFAULT_RENT_BYTE_FEE: u32 = 0;
|
||||
pub const DEFAULT_RENT_DEPOSIT_OFFSET: u32 = 0;
|
||||
pub const DEFAULT_SURCHARGE_REWARD: u32 = 0;
|
||||
pub const DEFAULT_TRANSFER_FEE: u32 = 0;
|
||||
pub const DEFAULT_CREATION_FEE: u32 = 0;
|
||||
pub const DEFAULT_TRANSACTION_BASE_FEE: u32 = 0;
|
||||
pub const DEFAULT_TRANSACTION_BYTE_FEE: u32 = 0;
|
||||
pub const DEFAULT_CONTRACT_FEE: u32 = 21;
|
||||
pub const DEFAULT_CALL_BASE_FEE: u32 = 135;
|
||||
pub const DEFAULT_CREATE_BASE_FEE: u32 = 175;
|
||||
pub const DEFAULT_MAX_DEPTH: u32 = 100;
|
||||
pub const DEFAULT_BLOCK_GAS_LIMIT: u32 = 10_000_000;
|
||||
|
||||
pub trait Trait: timestamp::Trait {
|
||||
type Currency: Currency<Self::AccountId>;
|
||||
|
||||
@@ -302,6 +318,67 @@ pub trait Trait: timestamp::Trait {
|
||||
|
||||
/// Handler for the unbalanced reduction when making a gas payment.
|
||||
type GasPayment: OnUnbalanced<NegativeImbalanceOf<Self>>;
|
||||
|
||||
/// Number of block delay an extrinsic claim surcharge has.
|
||||
///
|
||||
/// When claim surchage is called by an extrinsic the rent is checked
|
||||
/// for current_block - delay
|
||||
type SignedClaimHandicap: Get<Self::BlockNumber>;
|
||||
|
||||
/// The minimum amount required to generate a tombstone.
|
||||
type TombstoneDeposit: Get<BalanceOf<Self>>;
|
||||
|
||||
/// Size of a contract at the time of creation. This is a simple way to ensure
|
||||
/// that empty contracts eventually gets deleted.
|
||||
type StorageSizeOffset: Get<u32>;
|
||||
|
||||
/// Price of a byte of storage per one block interval. Should be greater than 0.
|
||||
type RentByteFee: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The amount of funds a contract should deposit in order to offset
|
||||
/// the cost of one byte.
|
||||
///
|
||||
/// Let's suppose the deposit is 1,000 BU (balance units)/byte and the rent is 1 BU/byte/day,
|
||||
/// then a contract with 1,000,000 BU that uses 1,000 bytes of storage would pay no rent.
|
||||
/// But if the balance reduced to 500,000 BU and the storage stayed the same at 1,000,
|
||||
/// then it would pay 500 BU/day.
|
||||
type RentDepositOffset: Get<BalanceOf<Self>>;
|
||||
|
||||
/// Reward that is received by the party whose touch has led
|
||||
/// 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>>;
|
||||
|
||||
/// The fee to be paid for making a transaction; the base.
|
||||
type TransactionBaseFee: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The fee to be paid for making a transaction; the per-byte portion.
|
||||
type TransactionByteFee: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The fee required to create a contract instance. A reasonable default value
|
||||
/// is 21.
|
||||
type ContractFee: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The base fee charged for calling into a contract. A reasonable default
|
||||
/// value is 135.
|
||||
type CallBaseFee: Get<Gas>;
|
||||
|
||||
/// The base fee charged for creating a contract. A reasonable default value
|
||||
/// is 175.
|
||||
type CreateBaseFee: Get<Gas>;
|
||||
|
||||
/// The maximum nesting level of a call/create stack. A reasonable default
|
||||
/// value is 100.
|
||||
type MaxDepth: Get<u32>;
|
||||
|
||||
/// The maximum amount of gas that could be expended per block. A reasonable
|
||||
/// default value is 10_000_000.
|
||||
type BlockGasLimit: Get<Gas>;
|
||||
}
|
||||
|
||||
/// Simple contract address determiner.
|
||||
@@ -333,8 +410,8 @@ pub struct DefaultDispatchFeeComputor<T: Trait>(PhantomData<T>);
|
||||
impl<T: Trait> ComputeDispatchFee<T::Call, BalanceOf<T>> for DefaultDispatchFeeComputor<T> {
|
||||
fn compute_dispatch_fee(call: &T::Call) -> BalanceOf<T> {
|
||||
let encoded_len = call.using_encoded(|encoded| encoded.len() as u32);
|
||||
let base_fee = <Module<T>>::transaction_base_fee();
|
||||
let byte_fee = <Module<T>>::transaction_byte_fee();
|
||||
let base_fee = T::TransactionBaseFee::get();
|
||||
let byte_fee = T::TransactionByteFee::get();
|
||||
base_fee + byte_fee * encoded_len.into()
|
||||
}
|
||||
}
|
||||
@@ -342,6 +419,67 @@ impl<T: Trait> ComputeDispatchFee<T::Call, BalanceOf<T>> for DefaultDispatchFeeC
|
||||
decl_module! {
|
||||
/// Contracts module.
|
||||
pub struct Module<T: Trait> for enum Call where origin: <T as system::Trait>::Origin {
|
||||
/// Number of block delay an extrinsic claim surcharge has.
|
||||
///
|
||||
/// When claim surchage is called by an extrinsic the rent is checked
|
||||
/// for current_block - delay
|
||||
const SignedClaimHandicap: T::BlockNumber = T::SignedClaimHandicap::get();
|
||||
|
||||
/// The minimum amount required to generate a tombstone.
|
||||
const TombstoneDeposit: BalanceOf<T> = T::TombstoneDeposit::get();
|
||||
|
||||
/// Size of a contract at the time of creation. This is a simple way to ensure
|
||||
/// that empty contracts eventually gets deleted.
|
||||
const StorageSizeOffset: u32 = T::StorageSizeOffset::get();
|
||||
|
||||
/// Price of a byte of storage per one block interval. Should be greater than 0.
|
||||
const RentByteFee: BalanceOf<T> = T::RentByteFee::get();
|
||||
|
||||
/// The amount of funds a contract should deposit in order to offset
|
||||
/// the cost of one byte.
|
||||
///
|
||||
/// Let's suppose the deposit is 1,000 BU (balance units)/byte and the rent is 1 BU/byte/day,
|
||||
/// then a contract with 1,000,000 BU that uses 1,000 bytes of storage would pay no rent.
|
||||
/// But if the balance reduced to 500,000 BU and the storage stayed the same at 1,000,
|
||||
/// then it would pay 500 BU/day.
|
||||
const RentDepositOffset: BalanceOf<T> = T::RentDepositOffset::get();
|
||||
|
||||
/// Reward that is received by the party whose touch has led
|
||||
/// 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();
|
||||
|
||||
/// The fee to be paid for making a transaction; the base.
|
||||
const TransactionBaseFee: BalanceOf<T> = T::TransactionBaseFee::get();
|
||||
|
||||
/// The fee to be paid for making a transaction; the per-byte portion.
|
||||
const TransactionByteFee: BalanceOf<T> = T::TransactionByteFee::get();
|
||||
|
||||
/// The fee required to create a contract instance. A reasonable default value
|
||||
/// is 21.
|
||||
const ContractFee: BalanceOf<T> = T::ContractFee::get();
|
||||
|
||||
/// The base fee charged for calling into a contract. A reasonable default
|
||||
/// value is 135.
|
||||
const CallBaseFee: Gas = T::CallBaseFee::get();
|
||||
|
||||
/// The base fee charged for creating a contract. A reasonable default value
|
||||
/// is 175.
|
||||
const CreateBaseFee: Gas = T::CreateBaseFee::get();
|
||||
|
||||
/// The maximum nesting level of a call/create stack. A reasonable default
|
||||
/// value is 100.
|
||||
const MaxDepth: u32 = T::MaxDepth::get();
|
||||
|
||||
/// The maximum amount of gas that could be expended per block. A reasonable
|
||||
/// default value is 10_000_000.
|
||||
const BlockGasLimit: Gas = T::BlockGasLimit::get();
|
||||
|
||||
fn deposit_event<T>() = default;
|
||||
|
||||
/// Updates the schedule for metering contracts.
|
||||
@@ -519,14 +657,14 @@ decl_module! {
|
||||
// adding a handicap: for signed extrinsics we use a slightly older block number
|
||||
// for the eviction check. This can be viewed as if we pushed regular users back in past.
|
||||
let handicap = if signed {
|
||||
<Module<T>>::signed_claim_handicap()
|
||||
T::SignedClaimHandicap::get()
|
||||
} else {
|
||||
Zero::zero()
|
||||
};
|
||||
|
||||
// If poking the contract has lead to eviction of the contract, give out the rewards.
|
||||
if rent::try_evict::<T>(&dest, handicap) == rent::RentOutcome::Evicted {
|
||||
T::Currency::deposit_into_existing(rewarded, Self::surcharge_reward())?;
|
||||
T::Currency::deposit_into_existing(rewarded, T::SurchargeReward::get())?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,45 +782,6 @@ decl_event! {
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Contract {
|
||||
/// Number of block delay an extrinsic claim surcharge has.
|
||||
///
|
||||
/// When claim surchage is called by an extrinsic the rent is checked
|
||||
/// for current_block - delay
|
||||
SignedClaimHandicap get(signed_claim_handicap) config(): T::BlockNumber;
|
||||
/// The minimum amount required to generate a tombstone.
|
||||
TombstoneDeposit get(tombstone_deposit) config(): BalanceOf<T>;
|
||||
/// Size of a contract at the time of creation. This is a simple way to ensure
|
||||
/// that empty contracts eventually gets deleted.
|
||||
StorageSizeOffset get(storage_size_offset) config(): u32;
|
||||
/// Price of a byte of storage per one block interval. Should be greater than 0.
|
||||
RentByteFee get(rent_byte_price) config(): BalanceOf<T>;
|
||||
/// The amount of funds a contract should deposit in order to offset
|
||||
/// the cost of one byte.
|
||||
///
|
||||
/// Let's suppose the deposit is 1,000 BU (balance units)/byte and the rent is 1 BU/byte/day,
|
||||
/// then a contract with 1,000,000 BU that uses 1,000 bytes of storage would pay no rent.
|
||||
/// But if the balance reduced to 500,000 BU and the storage stayed the same at 1,000,
|
||||
/// then it would pay 500 BU/day.
|
||||
RentDepositOffset get(rent_deposit_offset) config(): BalanceOf<T>;
|
||||
/// Reward that is received by the party whose touch has led
|
||||
/// to removal of a contract.
|
||||
SurchargeReward get(surcharge_reward) config(): BalanceOf<T>;
|
||||
/// The fee required to make a transfer.
|
||||
TransferFee get(transfer_fee) config(): BalanceOf<T>;
|
||||
/// The fee required to create an account.
|
||||
CreationFee get(creation_fee) config(): BalanceOf<T>;
|
||||
/// The fee to be paid for making a transaction; the base.
|
||||
TransactionBaseFee get(transaction_base_fee) config(): BalanceOf<T>;
|
||||
/// The fee to be paid for making a transaction; the per-byte portion.
|
||||
TransactionByteFee get(transaction_byte_fee) config(): BalanceOf<T>;
|
||||
/// The fee required to create a contract instance.
|
||||
ContractFee get(contract_fee) config(): BalanceOf<T> = 21.into();
|
||||
/// The price of one unit of gas.
|
||||
GasPrice get(gas_price) config(): BalanceOf<T> = 1.into();
|
||||
/// The maximum nesting level of a call/create stack.
|
||||
MaxDepth get(max_depth) config(): u32 = 100;
|
||||
/// The maximum amount of gas that could be expended per block.
|
||||
BlockGasLimit get(block_gas_limit) config(): Gas = 10_000_000;
|
||||
/// Gas spent so far in this block.
|
||||
GasSpent get(gas_spent): Gas;
|
||||
/// Current cost schedule for contracts.
|
||||
@@ -695,6 +794,8 @@ decl_storage! {
|
||||
pub AccountCounter: u64 = 0;
|
||||
/// The code associated with a given account.
|
||||
pub ContractInfoOf: map T::AccountId => Option<ContractInfo<T>>;
|
||||
/// The price of one unit of gas.
|
||||
GasPrice get(gas_price) config(): BalanceOf<T> = 1.into();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -725,10 +826,10 @@ impl<T: Trait> Config<T> {
|
||||
Config {
|
||||
schedule: <Module<T>>::current_schedule(),
|
||||
existential_deposit: T::Currency::minimum_balance(),
|
||||
max_depth: <Module<T>>::max_depth(),
|
||||
contract_account_instantiate_fee: <Module<T>>::contract_fee(),
|
||||
account_create_fee: <Module<T>>::creation_fee(),
|
||||
transfer_fee: <Module<T>>::transfer_fee(),
|
||||
max_depth: T::MaxDepth::get(),
|
||||
contract_account_instantiate_fee: T::ContractFee::get(),
|
||||
account_create_fee: T::CreationFee::get(),
|
||||
transfer_fee: T::TransferFee::get(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{BalanceOf, ContractInfo, ContractInfoOf, Module, TombstoneContractInfo, Trait};
|
||||
use crate::{BalanceOf, ContractInfo, ContractInfoOf, TombstoneContractInfo, Trait};
|
||||
use runtime_primitives::traits::{Bounded, CheckedDiv, CheckedMul, Saturating, Zero,
|
||||
SaturatedConversion};
|
||||
use srml_support::traits::{Currency, ExistenceRequirement, WithdrawReason};
|
||||
use srml_support::traits::{Currency, ExistenceRequirement, Get, WithdrawReason};
|
||||
use srml_support::StorageMap;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||
@@ -75,14 +75,14 @@ fn try_evict_or_and_pay_rent<T: Trait>(
|
||||
// An amount of funds to charge per block for storage taken up by the contract.
|
||||
let fee_per_block = {
|
||||
let free_storage = balance
|
||||
.checked_div(&<Module<T>>::rent_deposit_offset())
|
||||
.checked_div(&T::RentDepositOffset::get())
|
||||
.unwrap_or_else(Zero::zero);
|
||||
|
||||
let effective_storage_size =
|
||||
<BalanceOf<T>>::from(contract.storage_size).saturating_sub(free_storage);
|
||||
|
||||
effective_storage_size
|
||||
.checked_mul(&<Module<T>>::rent_byte_price())
|
||||
.checked_mul(&T::RentByteFee::get())
|
||||
.unwrap_or(<BalanceOf<T>>::max_value())
|
||||
};
|
||||
|
||||
@@ -93,7 +93,7 @@ fn try_evict_or_and_pay_rent<T: Trait>(
|
||||
}
|
||||
|
||||
// The minimal amount of funds required for a contract not to be evicted.
|
||||
let subsistence_threshold = T::Currency::minimum_balance() + <Module<T>>::tombstone_deposit();
|
||||
let subsistence_threshold = T::Currency::minimum_balance() + T::TombstoneDeposit::get();
|
||||
|
||||
if balance < subsistence_threshold {
|
||||
// The contract cannot afford to leave a tombstone, so remove the contract info altogether.
|
||||
|
||||
@@ -33,9 +33,10 @@ use runtime_primitives::testing::{Digest, DigestItem, Header, UintAuthorityId, H
|
||||
use runtime_primitives::traits::{BlakeTwo256, IdentityLookup};
|
||||
use runtime_primitives::BuildStorage;
|
||||
use srml_support::{
|
||||
assert_ok, assert_err, impl_outer_dispatch, impl_outer_event, impl_outer_origin, storage::child,
|
||||
traits::Currency, StorageMap, StorageValue
|
||||
assert_ok, assert_err, impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types,
|
||||
storage::child, StorageMap, StorageValue, traits::{Currency, Get},
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use substrate_primitives::storage::well_known_keys;
|
||||
use substrate_primitives::Blake2Hasher;
|
||||
@@ -64,6 +65,33 @@ impl_outer_dispatch! {
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static EXISTENTIAL_DEPOSIT: RefCell<u64> = RefCell::new(0);
|
||||
static TRANSFER_FEE: RefCell<u64> = RefCell::new(0);
|
||||
static CREATION_FEE: RefCell<u64> = RefCell::new(0);
|
||||
static BLOCK_GAS_LIMIT: RefCell<u64> = RefCell::new(0);
|
||||
}
|
||||
|
||||
pub struct ExistentialDeposit;
|
||||
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()) }
|
||||
}
|
||||
|
||||
pub struct BlockGasLimit;
|
||||
impl Get<u64> for BlockGasLimit {
|
||||
fn get() -> u64 { BLOCK_GAS_LIMIT.with(|v| *v.borrow()) }
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Debug)]
|
||||
pub struct Test;
|
||||
impl system::Trait for Test {
|
||||
@@ -77,6 +105,10 @@ impl system::Trait for Test {
|
||||
type Header = Header;
|
||||
type Event = MetaEvent;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const BalancesTransactionBaseFee: u64 = 0;
|
||||
pub const BalancesTransactionByteFee: u64 = 0;
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = Contract;
|
||||
@@ -85,11 +117,30 @@ impl balances::Trait for Test {
|
||||
type TransactionPayment = ();
|
||||
type DustRemoval = ();
|
||||
type TransferPayment = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = BalancesTransactionBaseFee;
|
||||
type TransactionByteFee = BalancesTransactionByteFee;
|
||||
}
|
||||
impl timestamp::Trait for Test {
|
||||
type Moment = u64;
|
||||
type OnTimestampSet = ();
|
||||
}
|
||||
parameter_types! {
|
||||
pub const SignedClaimHandicap: u64 = 2;
|
||||
pub const TombstoneDeposit: u64 = 16;
|
||||
pub const StorageSizeOffset: u32 = 8;
|
||||
pub const RentByteFee: u64 = 4;
|
||||
pub const RentDepositOffset: u64 = 10_000;
|
||||
pub const SurchargeReward: u64 = 150;
|
||||
pub const TransactionBaseFee: u64 = 2;
|
||||
pub const TransactionByteFee: u64 = 6;
|
||||
pub const ContractFee: u64 = 21;
|
||||
pub const CallBaseFee: u64 = 135;
|
||||
pub const CreateBaseFee: u64 = 175;
|
||||
pub const MaxDepth: u32 = 100;
|
||||
}
|
||||
impl Trait for Test {
|
||||
type Currency = Balances;
|
||||
type Call = Call;
|
||||
@@ -98,6 +149,21 @@ impl Trait for Test {
|
||||
type ComputeDispatchFee = DummyComputeDispatchFee;
|
||||
type TrieIdGenerator = DummyTrieIdGenerator;
|
||||
type GasPayment = ();
|
||||
type SignedClaimHandicap = SignedClaimHandicap;
|
||||
type TombstoneDeposit = TombstoneDeposit;
|
||||
type StorageSizeOffset = StorageSizeOffset;
|
||||
type RentByteFee = RentByteFee;
|
||||
type RentDepositOffset = RentDepositOffset;
|
||||
type SurchargeReward = SurchargeReward;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
type ContractFee = ContractFee;
|
||||
type CallBaseFee = CallBaseFee;
|
||||
type CreateBaseFee = CreateBaseFee;
|
||||
type MaxDepth = MaxDepth;
|
||||
type BlockGasLimit = BlockGasLimit;
|
||||
}
|
||||
|
||||
type Balances = balances::Module<Test>;
|
||||
@@ -182,16 +248,18 @@ impl ExtBuilder {
|
||||
self.creation_fee = creation_fee;
|
||||
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);
|
||||
BLOCK_GAS_LIMIT.with(|v| *v.borrow_mut() = self.block_gas_limit);
|
||||
}
|
||||
pub fn build(self) -> runtime_io::TestExternalities<Blake2Hasher> {
|
||||
self.set_associated_consts();
|
||||
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0;
|
||||
t.extend(
|
||||
balances::GenesisConfig::<Test> {
|
||||
transaction_base_fee: 0,
|
||||
transaction_byte_fee: 0,
|
||||
balances: vec![],
|
||||
existential_deposit: self.existential_deposit,
|
||||
transfer_fee: self.transfer_fee,
|
||||
creation_fee: self.creation_fee,
|
||||
vesting: vec![],
|
||||
}
|
||||
.build_storage()
|
||||
@@ -200,21 +268,8 @@ impl ExtBuilder {
|
||||
);
|
||||
t.extend(
|
||||
GenesisConfig::<Test> {
|
||||
signed_claim_handicap: 2,
|
||||
rent_byte_price: 4,
|
||||
rent_deposit_offset: 10_000,
|
||||
storage_size_offset: 8,
|
||||
surcharge_reward: 150,
|
||||
tombstone_deposit: 16,
|
||||
transaction_base_fee: 2,
|
||||
transaction_byte_fee: 6,
|
||||
transfer_fee: self.transfer_fee,
|
||||
creation_fee: self.creation_fee,
|
||||
contract_fee: 21,
|
||||
gas_price: self.gas_price,
|
||||
max_depth: 100,
|
||||
block_gas_limit: self.block_gas_limit,
|
||||
current_schedule: Default::default(),
|
||||
gas_price: self.gas_price,
|
||||
}
|
||||
.build_storage()
|
||||
.unwrap()
|
||||
@@ -253,7 +308,7 @@ fn account_removal_removes_storage() {
|
||||
Balances::deposit_creating(&1, 110);
|
||||
ContractInfoOf::<Test>::insert(1, &ContractInfo::Alive(RawAliveContractInfo {
|
||||
trie_id: trie_id1.clone(),
|
||||
storage_size: Contract::storage_size_offset(),
|
||||
storage_size: <Test as Trait>::StorageSizeOffset::get(),
|
||||
deduct_block: System::block_number(),
|
||||
code_hash: H256::repeat_byte(1),
|
||||
rent_allowance: 40,
|
||||
@@ -268,7 +323,7 @@ fn account_removal_removes_storage() {
|
||||
Balances::deposit_creating(&2, 110);
|
||||
ContractInfoOf::<Test>::insert(2, &ContractInfo::Alive(RawAliveContractInfo {
|
||||
trie_id: trie_id2.clone(),
|
||||
storage_size: Contract::storage_size_offset(),
|
||||
storage_size: <Test as Trait>::StorageSizeOffset::get(),
|
||||
deduct_block: System::block_number(),
|
||||
code_hash: H256::repeat_byte(2),
|
||||
rent_allowance: 40,
|
||||
@@ -795,15 +850,15 @@ fn storage_size() {
|
||||
<Test as balances::Trait>::Balance::from(1_000u32).encode() // rent allowance
|
||||
));
|
||||
let bob_contract = ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap();
|
||||
assert_eq!(bob_contract.storage_size, Contract::storage_size_offset() + 4);
|
||||
assert_eq!(bob_contract.storage_size, <Test as Trait>::StorageSizeOffset::get() + 4);
|
||||
|
||||
assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::set_storage_4_byte()));
|
||||
let bob_contract = ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap();
|
||||
assert_eq!(bob_contract.storage_size, Contract::storage_size_offset() + 4 + 4);
|
||||
assert_eq!(bob_contract.storage_size, <Test as Trait>::StorageSizeOffset::get() + 4 + 4);
|
||||
|
||||
assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::remove_storage_4_byte()));
|
||||
let bob_contract = ContractInfoOf::<Test>::get(BOB).unwrap().get_alive().unwrap();
|
||||
assert_eq!(bob_contract.storage_size, Contract::storage_size_offset() + 4);
|
||||
assert_eq!(bob_contract.storage_size, <Test as Trait>::StorageSizeOffset::get() + 4);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
//! Council system: Handles the voting in and maintenance of council members.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![recursion_limit="128"]
|
||||
|
||||
pub mod motions;
|
||||
pub mod seats;
|
||||
@@ -39,11 +40,12 @@ mod tests {
|
||||
pub use super::*;
|
||||
pub use runtime_io::with_externalities;
|
||||
use srml_support::{impl_outer_origin, impl_outer_event, impl_outer_dispatch, parameter_types};
|
||||
use srml_support::traits::Get;
|
||||
pub use substrate_primitives::{H256, Blake2Hasher, u32_trait::{_1, _2, _3, _4}};
|
||||
pub use primitives::{
|
||||
traits::{BlakeTwo256, IdentityLookup}, testing::{Digest, DigestItem, Header}
|
||||
};
|
||||
pub use primitives::traits::{BlakeTwo256, IdentityLookup};
|
||||
pub use primitives::testing::{Digest, DigestItem, Header};
|
||||
pub use {seats, motions};
|
||||
use std::cell::RefCell;
|
||||
|
||||
impl_outer_origin! {
|
||||
pub enum Origin for Test {
|
||||
@@ -64,6 +66,33 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static VOTER_BOND: RefCell<u64> = RefCell::new(0);
|
||||
static VOTING_FEE: RefCell<u64> = RefCell::new(0);
|
||||
static PRESENT_SLASH_PER_VOTER: RefCell<u64> = RefCell::new(0);
|
||||
static DECAY_RATIO: RefCell<u32> = RefCell::new(0);
|
||||
}
|
||||
|
||||
pub struct VotingBond;
|
||||
impl Get<u64> for VotingBond {
|
||||
fn get() -> u64 { VOTER_BOND.with(|v| *v.borrow()) }
|
||||
}
|
||||
|
||||
pub struct VotingFee;
|
||||
impl Get<u64> for VotingFee {
|
||||
fn get() -> u64 { VOTING_FEE.with(|v| *v.borrow()) }
|
||||
}
|
||||
|
||||
pub struct PresentSlashPerVoter;
|
||||
impl Get<u64> for PresentSlashPerVoter {
|
||||
fn get() -> u64 { PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow()) }
|
||||
}
|
||||
|
||||
pub struct DecayRatio;
|
||||
impl Get<u32> for DecayRatio {
|
||||
fn get() -> u32 { DECAY_RATIO.with(|v| *v.borrow()) }
|
||||
}
|
||||
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
||||
#[derive(Clone, Eq, PartialEq, Debug)]
|
||||
pub struct Test;
|
||||
@@ -78,14 +107,26 @@ mod tests {
|
||||
type Header = Header;
|
||||
type Event = Event;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
pub const TransactionBaseFee: u64 = 0;
|
||||
pub const TransactionByteFee: u64 = 0;
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
type OnNewAccount = ();
|
||||
type OnFreeBalanceZero = ();
|
||||
type Event = Event;
|
||||
type TransactionPayment = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const LaunchPeriod: u64 = 1;
|
||||
@@ -110,6 +151,12 @@ mod tests {
|
||||
type VetoOrigin = motions::EnsureMember<u64>;
|
||||
type CooloffPeriod = CooloffPeriod;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const CandidacyBond: u64 = 3;
|
||||
pub const CarryCount: u32 = 2;
|
||||
pub const InactiveGracePeriod: u32 = 1;
|
||||
pub const CouncilVotingPeriod: u64 = 4;
|
||||
}
|
||||
impl seats::Trait for Test {
|
||||
type Event = Event;
|
||||
type BadPresentation = ();
|
||||
@@ -117,6 +164,14 @@ mod tests {
|
||||
type BadVoterIndex = ();
|
||||
type LoserCandidate = ();
|
||||
type OnMembersChanged = CouncilMotions;
|
||||
type CandidacyBond = CandidacyBond;
|
||||
type VotingBond = VotingBond;
|
||||
type VotingFee = VotingFee;
|
||||
type PresentSlashPerVoter = PresentSlashPerVoter;
|
||||
type CarryCount = CarryCount;
|
||||
type InactiveGracePeriod = InactiveGracePeriod;
|
||||
type CouncilVotingPeriod = CouncilVotingPeriod;
|
||||
type DecayRatio = DecayRatio;
|
||||
}
|
||||
impl motions::Trait for Test {
|
||||
type Origin = Origin;
|
||||
@@ -171,11 +226,16 @@ mod tests {
|
||||
self.voter_bond = fee;
|
||||
self
|
||||
}
|
||||
pub fn set_associated_consts(&self) {
|
||||
VOTER_BOND.with(|v| *v.borrow_mut() = self.voter_bond);
|
||||
VOTING_FEE.with(|v| *v.borrow_mut() = self.voting_fee);
|
||||
PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow_mut() = self.bad_presentation_punishment);
|
||||
DECAY_RATIO.with(|v| *v.borrow_mut() = self.decay_ratio);
|
||||
}
|
||||
pub fn build(self) -> runtime_io::TestExternalities<Blake2Hasher> {
|
||||
self.set_associated_consts();
|
||||
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0;
|
||||
t.extend(balances::GenesisConfig::<Test> {
|
||||
transaction_base_fee: 0,
|
||||
transaction_byte_fee: 0,
|
||||
t.extend(balances::GenesisConfig::<Test>{
|
||||
balances: vec![
|
||||
(1, 10 * self.balance_factor),
|
||||
(2, 20 * self.balance_factor),
|
||||
@@ -184,27 +244,16 @@ mod tests {
|
||||
(5, 50 * self.balance_factor),
|
||||
(6, 60 * self.balance_factor)
|
||||
],
|
||||
existential_deposit: 0,
|
||||
transfer_fee: 0,
|
||||
creation_fee: 0,
|
||||
vesting: vec![],
|
||||
}.build_storage().unwrap().0);
|
||||
t.extend(seats::GenesisConfig::<Test> {
|
||||
candidacy_bond: 3,
|
||||
voter_bond: self.voter_bond,
|
||||
present_slash_per_voter: self.bad_presentation_punishment,
|
||||
carry_count: 2,
|
||||
inactive_grace_period: 1,
|
||||
active_council: if self.with_council { vec![
|
||||
(1, 10),
|
||||
(2, 10),
|
||||
(3, 10)
|
||||
] } else { vec![] },
|
||||
approval_voting_period: 4,
|
||||
presentation_duration: 2,
|
||||
desired_seats: 2,
|
||||
decay_ratio: self.decay_ratio,
|
||||
voting_fee: self.voting_fee,
|
||||
presentation_duration: 2,
|
||||
term_duration: 5,
|
||||
}.build_storage().unwrap().0);
|
||||
runtime_io::TestExternalities::new(t)
|
||||
|
||||
@@ -23,8 +23,8 @@ use srml_support::{
|
||||
StorageValue, StorageMap,
|
||||
dispatch::Result, decl_storage, decl_event, ensure, decl_module,
|
||||
traits::{
|
||||
Currency, ReservableCurrency, OnUnbalanced, LockIdentifier,
|
||||
LockableCurrency, WithdrawReasons, WithdrawReason, ExistenceRequirement
|
||||
Currency, ExistenceRequirement, Get, LockableCurrency, LockIdentifier,
|
||||
OnUnbalanced, ReservableCurrency, WithdrawReason, WithdrawReasons,
|
||||
}
|
||||
};
|
||||
use democracy;
|
||||
@@ -131,6 +131,15 @@ type ApprovalFlag = u32;
|
||||
pub const APPROVAL_FLAG_MASK: ApprovalFlag = 0x8000_0000;
|
||||
pub const APPROVAL_FLAG_LEN: usize = 32;
|
||||
|
||||
pub const DEFAULT_CANDIDACY_BOND: u32 = 9;
|
||||
pub const DEFAULT_VOTING_BOND: u32 = 0;
|
||||
pub const DEFAULT_VOTING_FEE: u32 = 0;
|
||||
pub const DEFAULT_PRESENT_SLASH_PER_VOTER: u32 = 1;
|
||||
pub const DEFAULT_CARRY_COUNT: u32 = 2;
|
||||
pub const DEFAULT_INACTIVE_GRACE_PERIOD: u32 = 1;
|
||||
pub const DEFAULT_COUNCIL_VOTING_PERIOD: u32 = 1000;
|
||||
pub const DEFAULT_DECAY_RATIO: u32 = 24;
|
||||
|
||||
pub trait Trait: democracy::Trait {
|
||||
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
|
||||
|
||||
@@ -147,10 +156,80 @@ pub trait Trait: democracy::Trait {
|
||||
type LoserCandidate: OnUnbalanced<NegativeImbalanceOf<Self>>;
|
||||
/// What to do when the members change.
|
||||
type OnMembersChanged: OnMembersChanged<Self::AccountId>;
|
||||
|
||||
/// How much should be locked up in order to submit one's candidacy. A reasonable
|
||||
/// default value is 9.
|
||||
type CandidacyBond: Get<BalanceOf<Self>>;
|
||||
|
||||
/// How much should be locked up in order to be able to submit votes.
|
||||
type VotingBond: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The amount of fee paid upon each vote submission, unless if they submit a
|
||||
/// _hole_ index and replace it.
|
||||
type VotingFee: Get<BalanceOf<Self>>;
|
||||
|
||||
/// The punishment, per voter, if you provide an invalid presentation. A
|
||||
/// reasonable default value is 1.
|
||||
type PresentSlashPerVoter: Get<BalanceOf<Self>>;
|
||||
|
||||
/// How many runners-up should have their approvals persist until the next
|
||||
/// vote. A reasonable default value is 2.
|
||||
type CarryCount: Get<u32>;
|
||||
|
||||
/// How many vote indices need to go by after a target voter's last vote before
|
||||
/// they can be reaped if their approvals are moot. A reasonable default value
|
||||
/// is 1.
|
||||
type InactiveGracePeriod: Get<VoteIndex>;
|
||||
|
||||
/// How often (in blocks) to check for new votes. A reasonable default value
|
||||
/// is 1000.
|
||||
type CouncilVotingPeriod: Get<Self::BlockNumber>;
|
||||
|
||||
/// Decay factor of weight when being accumulated. It should typically be set to
|
||||
/// __at least__ `council_size -1` to keep the council secure.
|
||||
/// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight
|
||||
/// increment step `t`. 0 will result in no weight being added at all (normal
|
||||
/// approval voting). A reasonable default value is 24.
|
||||
type DecayRatio: Get<u32>;
|
||||
}
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
||||
/// How much should be locked up in order to submit one's candidacy. A reasonable
|
||||
/// default value is 9.
|
||||
const CandidacyBond: BalanceOf<T> = T::CandidacyBond::get();
|
||||
|
||||
/// How much should be locked up in order to be able to submit votes.
|
||||
const VotingBond: BalanceOf<T> = T::VotingBond::get();
|
||||
|
||||
/// The amount of fee paid upon each vote submission, unless if they submit a
|
||||
/// _hole_ index and replace it.
|
||||
const VotingFee: BalanceOf<T> = T::VotingFee::get();
|
||||
|
||||
/// The punishment, per voter, if you provide an invalid presentation. A
|
||||
/// reasonable default value is 1.
|
||||
const PresentSlashPerVoter: BalanceOf<T> = T::PresentSlashPerVoter::get();
|
||||
|
||||
/// How many runners-up should have their approvals persist until the next
|
||||
/// vote. A reasonable default value is 2.
|
||||
const CarryCount: u32 = T::CarryCount::get();
|
||||
|
||||
/// How many vote indices need to go by after a target voter's last vote before
|
||||
/// they can be reaped if their approvals are moot. A reasonable default value
|
||||
/// is 1.
|
||||
const InactiveGracePeriod: VoteIndex = T::InactiveGracePeriod::get();
|
||||
|
||||
/// How often (in blocks) to check for new votes. A reasonable default value
|
||||
/// is 1000.
|
||||
const CouncilVotingPeriod: T::BlockNumber = T::CouncilVotingPeriod::get();
|
||||
|
||||
/// Decay factor of weight when being accumulated. It should typically be set to
|
||||
/// __at least__ `council_size -1` to keep the council secure.
|
||||
/// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight
|
||||
/// increment step `t`. 0 will result in no weight being added at all (normal
|
||||
/// approval voting). A reasonable default value is 24.
|
||||
const DecayRatio: u32 = T::DecayRatio::get();
|
||||
|
||||
fn deposit_event<T>() = default;
|
||||
|
||||
/// Set candidate approvals. Approval slots stay valid as long as candidates in those slots
|
||||
@@ -223,7 +302,7 @@ decl_module! {
|
||||
|
||||
ensure!(assumed_vote_index == Self::vote_index(), "vote index not current");
|
||||
ensure!(
|
||||
assumed_vote_index > last_active+ Self::inactivity_grace_period(),
|
||||
assumed_vote_index > last_active + T::InactiveGracePeriod::get(),
|
||||
"cannot reap during grace period"
|
||||
);
|
||||
|
||||
@@ -259,10 +338,10 @@ decl_module! {
|
||||
if valid {
|
||||
// This only fails if `reporter` doesn't exist, which it clearly must do since its the origin.
|
||||
// Still, it's no more harmful to propagate any error at this point.
|
||||
T::Currency::repatriate_reserved(&who, &reporter, Self::voting_bond())?;
|
||||
T::Currency::repatriate_reserved(&who, &reporter, T::VotingBond::get())?;
|
||||
Self::deposit_event(RawEvent::VoterReaped(who, reporter));
|
||||
} else {
|
||||
let imbalance = T::Currency::slash_reserved(&reporter, Self::voting_bond()).0;
|
||||
let imbalance = T::Currency::slash_reserved(&reporter, T::VotingBond::get()).0;
|
||||
T::BadReaper::on_unbalanced(imbalance);
|
||||
Self::deposit_event(RawEvent::BadReaperSlashed(reporter));
|
||||
}
|
||||
@@ -288,7 +367,7 @@ decl_module! {
|
||||
ensure!(voter == who, "retraction index mismatch");
|
||||
|
||||
Self::remove_voter(&who, index);
|
||||
T::Currency::unreserve(&who, Self::voting_bond());
|
||||
T::Currency::unreserve(&who, T::VotingBond::get());
|
||||
T::Currency::remove_lock(COUNCIL_SEATS_ID, &who);
|
||||
}
|
||||
|
||||
@@ -318,7 +397,7 @@ decl_module! {
|
||||
"invalid candidate slot"
|
||||
);
|
||||
// NOTE: This must be last as it has side-effects.
|
||||
T::Currency::reserve(&who, Self::candidacy_bond())
|
||||
T::Currency::reserve(&who, T::CandidacyBond::get())
|
||||
.map_err(|_| "candidate has not enough funds")?;
|
||||
|
||||
<RegisterInfoOf<T>>::insert(&who, (Self::vote_index(), slot as u32));
|
||||
@@ -356,7 +435,7 @@ decl_module! {
|
||||
ensure!(index == Self::vote_index(), "index not current");
|
||||
let (_, _, expiring) = Self::next_finalize().ok_or("cannot present outside of presentation period")?;
|
||||
let bad_presentation_punishment =
|
||||
Self::present_slash_per_voter()
|
||||
T::PresentSlashPerVoter::get()
|
||||
* BalanceOf::<T>::from(Self::voter_count() as u32);
|
||||
ensure!(
|
||||
T::Currency::can_slash(&who, bad_presentation_punishment),
|
||||
@@ -449,34 +528,13 @@ decl_module! {
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Council {
|
||||
|
||||
// ---- parameters
|
||||
/// How much should be locked up in order to submit one's candidacy.
|
||||
pub CandidacyBond get(candidacy_bond) config(): BalanceOf<T> = 9.into();
|
||||
/// How much should be locked up in order to be able to submit votes.
|
||||
pub VotingBond get(voting_bond) config(voter_bond): BalanceOf<T>;
|
||||
/// The amount of fee paid upon each vote submission, unless if they submit a _hole_ index and replace it.
|
||||
pub VotingFee get(voting_fee) config(voting_fee): BalanceOf<T>;
|
||||
/// The punishment, per voter, if you provide an invalid presentation.
|
||||
pub PresentSlashPerVoter get(present_slash_per_voter) config(): BalanceOf<T> = 1.into();
|
||||
/// How many runners-up should have their approvals persist until the next vote.
|
||||
pub CarryCount get(carry_count) config(): u32 = 2;
|
||||
/// How long to give each top candidate to present themselves after the vote ends.
|
||||
pub PresentationDuration get(presentation_duration) config(): T::BlockNumber = 1000.into();
|
||||
/// How many vote indices need to go by after a target voter's last vote before they can be reaped if their
|
||||
/// approvals are moot.
|
||||
pub InactiveGracePeriod get(inactivity_grace_period) config(inactive_grace_period): VoteIndex = 1;
|
||||
/// How often (in blocks) to check for new votes.
|
||||
pub VotingPeriod get(voting_period) config(approval_voting_period): T::BlockNumber = 1000.into();
|
||||
pub PresentationDuration get(presentation_duration) config(): T::BlockNumber;
|
||||
/// How long each position is active for.
|
||||
pub TermDuration get(term_duration) config(): T::BlockNumber = 5.into();
|
||||
pub TermDuration get(term_duration) config(): T::BlockNumber;
|
||||
/// Number of accounts that should be sitting on the council.
|
||||
pub DesiredSeats get(desired_seats) config(): u32;
|
||||
/// Decay factor of weight when being accumulated. It should typically be set to
|
||||
/// __at least__ `council_size -1` to keep the council secure.
|
||||
/// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight increment step `t`.
|
||||
/// 0 will result in no weight being added at all (normal approval voting).
|
||||
pub DecayRatio get(decay_ratio) config(decay_ratio): u32 = 24;
|
||||
|
||||
// ---- permanent state (always relevant, changes only at the finalization of voting)
|
||||
/// The current council. When there's a vote going on, this should still be used for executive
|
||||
@@ -555,7 +613,7 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
/// Determine the block that a vote can happen on which is no less than `n`.
|
||||
pub fn next_vote_from(n: T::BlockNumber) -> T::BlockNumber {
|
||||
let voting_period = Self::voting_period();
|
||||
let voting_period = T::CouncilVotingPeriod::get();
|
||||
(n + voting_period - One::one()) / voting_period * voting_period
|
||||
}
|
||||
|
||||
@@ -592,7 +650,7 @@ impl<T: Trait> Module<T> {
|
||||
// Private
|
||||
/// Check there's nothing to do this block
|
||||
fn end_block(block_number: T::BlockNumber) -> Result {
|
||||
if (block_number % Self::voting_period()).is_zero() {
|
||||
if (block_number % T::CouncilVotingPeriod::get()).is_zero() {
|
||||
if let Some(number) = Self::next_tally() {
|
||||
if block_number == number {
|
||||
Self::start_tally();
|
||||
@@ -650,7 +708,7 @@ impl<T: Trait> Module<T> {
|
||||
} else {
|
||||
// not yet a voter. Index _could be valid_. Fee might apply. Bond will be reserved O(1).
|
||||
ensure!(
|
||||
T::Currency::free_balance(&who) > Self::voting_bond(),
|
||||
T::Currency::free_balance(&who) > T::VotingBond::get(),
|
||||
"new voter must have sufficient funds to pay the bond"
|
||||
);
|
||||
|
||||
@@ -669,20 +727,20 @@ impl<T: Trait> Module<T> {
|
||||
if set.is_empty() {
|
||||
let imbalance = T::Currency::withdraw(
|
||||
&who,
|
||||
Self::voting_fee(),
|
||||
T::VotingFee::get(),
|
||||
WithdrawReason::Fee,
|
||||
ExistenceRequirement::KeepAlive,
|
||||
)?;
|
||||
T::BadVoterIndex::on_unbalanced(imbalance);
|
||||
// NOTE: this is safe since the `withdraw()` will check this.
|
||||
locked_balance -= Self::voting_fee();
|
||||
locked_balance -= T::VotingFee::get();
|
||||
}
|
||||
Self::checked_push_voter(&mut set, who.clone(), next);
|
||||
<Voters<T>>::insert(next, set);
|
||||
}
|
||||
}
|
||||
|
||||
T::Currency::reserve(&who, Self::voting_bond())?;
|
||||
T::Currency::reserve(&who, T::VotingBond::get())?;
|
||||
VoterCount::mutate(|c| *c = *c + 1);
|
||||
}
|
||||
|
||||
@@ -720,7 +778,7 @@ impl<T: Trait> Module<T> {
|
||||
<NextFinalize<T>>::put((number + Self::presentation_duration(), empty_seats as u32, expiring));
|
||||
|
||||
// initialize leaderboard.
|
||||
let leaderboard_size = empty_seats + Self::carry_count() as usize;
|
||||
let leaderboard_size = empty_seats + T::CarryCount::get() as usize;
|
||||
<Leaderboard<T>>::put(vec![(Zero::zero(), T::AccountId::default()); leaderboard_size]);
|
||||
|
||||
Self::deposit_event(RawEvent::TallyStarted(empty_seats as u32));
|
||||
@@ -738,7 +796,7 @@ impl<T: Trait> Module<T> {
|
||||
let new_expiry = <system::Module<T>>::block_number() + Self::term_duration();
|
||||
|
||||
// return bond to winners.
|
||||
let candidacy_bond = Self::candidacy_bond();
|
||||
let candidacy_bond = T::CandidacyBond::get();
|
||||
let incoming: Vec<_> = leaderboard.iter()
|
||||
.rev()
|
||||
.take_while(|&&(b, _)| !b.is_zero())
|
||||
@@ -994,7 +1052,7 @@ impl<T: Trait> Module<T> {
|
||||
/// to a voter's stake value to get the correct weight. Indeed, zero is
|
||||
/// returned if `t` is zero.
|
||||
fn get_offset(stake: BalanceOf<T>, t: VoteIndex) -> BalanceOf<T> {
|
||||
let decay_ratio: BalanceOf<T> = Self::decay_ratio().into();
|
||||
let decay_ratio: BalanceOf<T> = T::DecayRatio::get().into();
|
||||
if t > 150 { return stake * decay_ratio }
|
||||
let mut offset = stake;
|
||||
let mut r = Zero::zero();
|
||||
@@ -1033,7 +1091,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn bond() -> u64 {
|
||||
Council::voting_bond()
|
||||
<Test as Trait>::VotingBond::get()
|
||||
}
|
||||
|
||||
|
||||
@@ -1090,16 +1148,16 @@ mod tests {
|
||||
assert_eq!(Council::next_vote_from(4), 4);
|
||||
assert_eq!(Council::next_vote_from(5), 8);
|
||||
assert_eq!(Council::vote_index(), 0);
|
||||
assert_eq!(Council::candidacy_bond(), 3);
|
||||
assert_eq!(Council::voting_bond(), 0);
|
||||
assert_eq!(Council::voting_fee(), 0);
|
||||
assert_eq!(Council::present_slash_per_voter(), 1);
|
||||
assert_eq!(<Test as Trait>::CandidacyBond::get(), 3);
|
||||
assert_eq!(<Test as Trait>::VotingBond::get(), 0);
|
||||
assert_eq!(<Test as Trait>::VotingFee::get(), 0);
|
||||
assert_eq!(<Test as Trait>::PresentSlashPerVoter::get(), 1);
|
||||
assert_eq!(Council::presentation_duration(), 2);
|
||||
assert_eq!(Council::inactivity_grace_period(), 1);
|
||||
assert_eq!(Council::voting_period(), 4);
|
||||
assert_eq!(<Test as Trait>::InactiveGracePeriod::get(), 1);
|
||||
assert_eq!(<Test as Trait>::CouncilVotingPeriod::get(), 4);
|
||||
assert_eq!(Council::term_duration(), 5);
|
||||
assert_eq!(Council::desired_seats(), 2);
|
||||
assert_eq!(Council::carry_count(), 2);
|
||||
assert_eq!(<Test as Trait>::CarryCount::get(), 2);
|
||||
|
||||
assert_eq!(Council::active_council(), vec![]);
|
||||
assert_eq!(Council::next_tally(), Some(4));
|
||||
@@ -2269,8 +2327,8 @@ mod tests {
|
||||
assert_ok!(Council::end_block(System::block_number()));
|
||||
|
||||
assert_eq!(Council::vote_index(), 2);
|
||||
assert_eq!(Council::inactivity_grace_period(), 1);
|
||||
assert_eq!(Council::voting_period(), 4);
|
||||
assert_eq!(<Test as Trait>::InactiveGracePeriod::get(), 1);
|
||||
assert_eq!(<Test as Trait>::CouncilVotingPeriod::get(), 4);
|
||||
assert_eq!(Council::voter_info(4), Some(VoterInfo { last_win: 1, last_active: 0, stake: 40, pot: 0 }));
|
||||
|
||||
assert_ok!(Council::reap_inactive_voter(Origin::signed(4),
|
||||
|
||||
@@ -165,6 +165,13 @@ impl Decode for Vote {
|
||||
|
||||
type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
|
||||
|
||||
pub const DEFAULT_ENACTMENT_PERIOD: u32 = 0;
|
||||
pub const DEFAULT_LAUNCH_PERIOD: u32 = 0;
|
||||
pub const DEFAULT_VOTING_PERIOD: u32 = 0;
|
||||
pub const DEFAULT_MINIMUM_DEPOSIT: u32 = 0;
|
||||
pub const DEFAULT_EMERGENCY_VOTING_PERIOD: u32 = 0;
|
||||
pub const DEFAULT_COOLOFF_PERIOD: u32 = 0;
|
||||
|
||||
pub trait Trait: system::Trait + Sized {
|
||||
type Proposal: Parameter + Dispatchable<Origin=Self::Origin> + IsSubType<Module<Self>>;
|
||||
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
|
||||
@@ -972,6 +979,13 @@ mod tests {
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
pub const TransactionBaseFee: u64 = 0;
|
||||
pub const TransactionByteFee: u64 = 0;
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
@@ -980,6 +994,11 @@ mod tests {
|
||||
type TransactionPayment = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const LaunchPeriod: u64 = 2;
|
||||
@@ -1020,12 +1039,7 @@ mod tests {
|
||||
fn new_test_ext() -> runtime_io::TestExternalities<Blake2Hasher> {
|
||||
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0;
|
||||
t.extend(balances::GenesisConfig::<Test>{
|
||||
transaction_base_fee: 0,
|
||||
transaction_byte_fee: 0,
|
||||
balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)],
|
||||
existential_deposit: 0,
|
||||
transfer_fee: 0,
|
||||
creation_fee: 0,
|
||||
vesting: vec![],
|
||||
}.build_storage().unwrap().0);
|
||||
t.extend(GenesisConfig::default().build_storage().unwrap().0);
|
||||
|
||||
@@ -504,7 +504,7 @@ impl<T: Trait> Module<T> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use srml_support::{impl_outer_origin, assert_ok};
|
||||
use srml_support::{assert_ok, impl_outer_origin, parameter_types};
|
||||
use sr_io::with_externalities;
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
// The testing primitives are very useful for avoiding having to work with signatures
|
||||
@@ -533,6 +533,13 @@ mod tests {
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
pub const TransactionBaseFee: u64 = 0;
|
||||
pub const TransactionByteFee: u64 = 0;
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
@@ -541,6 +548,11 @@ mod tests {
|
||||
type TransactionPayment = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
}
|
||||
impl Trait for Test {
|
||||
type Event = ();
|
||||
|
||||
@@ -395,10 +395,11 @@ mod tests {
|
||||
use balances::Call;
|
||||
use runtime_io::with_externalities;
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
use primitives::{
|
||||
traits::{Header as HeaderT, BlakeTwo256, IdentityLookup}, testing::{Digest, Header, Block}
|
||||
};
|
||||
use srml_support::{traits::Currency, impl_outer_origin, impl_outer_event};
|
||||
use primitives::BuildStorage;
|
||||
use primitives::traits::{Header as HeaderT, BlakeTwo256, IdentityLookup};
|
||||
use primitives::testing::{Digest, Header, Block};
|
||||
use srml_support::{impl_outer_event, impl_outer_origin, parameter_types};
|
||||
use srml_support::traits::Currency;
|
||||
use system;
|
||||
use hex_literal::hex;
|
||||
|
||||
@@ -427,6 +428,13 @@ mod tests {
|
||||
type Header = Header;
|
||||
type Event = MetaEvent;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
pub const TransactionBaseFee: u64 = 0;
|
||||
pub const TransactionByteFee: u64 = 0;
|
||||
}
|
||||
impl balances::Trait for Runtime {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = ();
|
||||
@@ -435,6 +443,11 @@ mod tests {
|
||||
type TransactionPayment = ();
|
||||
type DustRemoval = ();
|
||||
type TransferPayment = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
}
|
||||
|
||||
impl ValidateUnsigned for Runtime {
|
||||
@@ -468,12 +481,7 @@ mod tests {
|
||||
fn balance_transfer_dispatch_works() {
|
||||
let mut t = system::GenesisConfig::default().build_storage::<Runtime>().unwrap().0;
|
||||
t.extend(balances::GenesisConfig::<Runtime> {
|
||||
transaction_base_fee: 10,
|
||||
transaction_byte_fee: 0,
|
||||
balances: vec![(1, 111)],
|
||||
existential_deposit: 0,
|
||||
transfer_fee: 0,
|
||||
creation_fee: 0,
|
||||
vesting: vec![],
|
||||
}.build_storage().unwrap().0);
|
||||
let xt = primitives::testing::TestXt(Some(1), 0, Call::transfer(2, 69));
|
||||
@@ -487,7 +495,7 @@ mod tests {
|
||||
Digest::default(),
|
||||
));
|
||||
Executive::apply_extrinsic(xt).unwrap();
|
||||
assert_eq!(<balances::Module<Runtime>>::total_balance(&1), 32);
|
||||
assert_eq!(<balances::Module<Runtime>>::total_balance(&1), 42);
|
||||
assert_eq!(<balances::Module<Runtime>>::total_balance(&2), 69);
|
||||
});
|
||||
}
|
||||
@@ -505,7 +513,7 @@ mod tests {
|
||||
header: Header {
|
||||
parent_hash: [69u8; 32].into(),
|
||||
number: 1,
|
||||
state_root: hex!("5ba497e45e379d80a4524f9509d224e9c175d0fa30f3491481e7e44a6a758adf").into(),
|
||||
state_root: hex!("d75c79776d69123b65e819977b70e102482e05fd7538c1dcae1249a248ba64e4").into(),
|
||||
extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(),
|
||||
digest: Digest { logs: vec![], },
|
||||
},
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate srml_support;
|
||||
|
||||
use inherents::{
|
||||
RuntimeString, InherentIdentifier, ProvideInherent,
|
||||
InherentData, MakeFatalError,
|
||||
@@ -29,14 +26,13 @@ use srml_support::StorageValue;
|
||||
use primitives::traits::{One, Zero, SaturatedConversion};
|
||||
use rstd::{prelude::*, result, cmp, vec};
|
||||
use parity_codec::Decode;
|
||||
use srml_support::{decl_module, decl_storage, for_each_tuple};
|
||||
use srml_support::traits::Get;
|
||||
use srml_system::{ensure_none, Trait as SystemTrait};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use parity_codec::Encode;
|
||||
|
||||
const DEFAULT_WINDOW_SIZE: u32 = 101;
|
||||
const DEFAULT_DELAY: u32 = 1000;
|
||||
|
||||
/// The identifier for the `finalnum` inherent.
|
||||
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"finalnum";
|
||||
|
||||
@@ -85,10 +81,17 @@ impl<F, N: Encode> inherents::ProvideInherentData for InherentDataProvider<F, N>
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_WINDOW_SIZE: u32 = 101;
|
||||
pub const DEFAULT_REPORT_LATENCY: u32 = 1000;
|
||||
|
||||
pub trait Trait: SystemTrait {
|
||||
/// Something which can be notified when the timestamp is set. Set this to `()` if not needed.
|
||||
/// Something which can be notified when the timestamp is set. Set this to `()`
|
||||
/// if not needed.
|
||||
type OnFinalizationStalled: OnFinalizationStalled<Self::BlockNumber>;
|
||||
/// The number of recent samples to keep from this chain. Default is 101.
|
||||
type WindowSize: Get<Self::BlockNumber>;
|
||||
/// The delay after which point things become suspicious. Default is 1000.
|
||||
type ReportLatency: Get<Self::BlockNumber>;
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
@@ -99,10 +102,6 @@ decl_storage! {
|
||||
OrderedHints get(ordered_hints) build(|_| vec![T::BlockNumber::zero()]): Vec<T::BlockNumber>;
|
||||
/// The median.
|
||||
Median get(median) build(|_| T::BlockNumber::zero()): T::BlockNumber;
|
||||
/// The number of recent samples to keep from this chain. Default is n-100
|
||||
pub WindowSize get(window_size) config(window_size): T::BlockNumber = DEFAULT_WINDOW_SIZE.into();
|
||||
/// The delay after which point things become suspicious.
|
||||
pub ReportLatency get(report_latency) config(report_latency): T::BlockNumber = DEFAULT_DELAY.into();
|
||||
|
||||
/// Final hint to apply in the block. `None` means "same as parent".
|
||||
Update: Option<T::BlockNumber>;
|
||||
@@ -114,6 +113,12 @@ decl_storage! {
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
||||
/// The number of recent samples to keep from this chain. Default is 101.
|
||||
const WindowSize: T::BlockNumber = T::WindowSize::get();
|
||||
|
||||
/// The delay after which point things become suspicious. Default is 1000.
|
||||
const ReportLatency: T::BlockNumber = T::ReportLatency::get();
|
||||
|
||||
/// Hint that the author of this block thinks the best finalized
|
||||
/// block is the given number.
|
||||
fn final_hint(origin, #[compact] hint: T::BlockNumber) {
|
||||
@@ -144,7 +149,7 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
let mut recent = Self::recent_hints();
|
||||
let mut ordered = Self::ordered_hints();
|
||||
let window_size = cmp::max(T::BlockNumber::one(), Self::window_size());
|
||||
let window_size = cmp::max(T::BlockNumber::one(), T::WindowSize::get());
|
||||
|
||||
let hint = hint.unwrap_or_else(|| recent.last()
|
||||
.expect("always at least one recent sample; qed").clone()
|
||||
@@ -196,7 +201,7 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
if T::BlockNumber::from(our_window_size) == window_size {
|
||||
let now = srml_system::Module::<T>::block_number();
|
||||
let latency = Self::report_latency();
|
||||
let latency = T::ReportLatency::get();
|
||||
|
||||
// the delay is the latency plus half the window size.
|
||||
let delay = latency + (window_size / two);
|
||||
@@ -261,11 +266,11 @@ mod tests {
|
||||
|
||||
use sr_io::{with_externalities, TestExternalities};
|
||||
use substrate_primitives::H256;
|
||||
use primitives::{
|
||||
traits::{BlakeTwo256, IdentityLookup, OnFinalize, Header as HeaderT}, testing::Header
|
||||
};
|
||||
use srml_support::impl_outer_origin;
|
||||
use primitives::traits::{BlakeTwo256, IdentityLookup, OnFinalize, Header as HeaderT};
|
||||
use primitives::testing::Header;
|
||||
use srml_support::{assert_ok, impl_outer_origin, parameter_types};
|
||||
use srml_system as system;
|
||||
use std::cell::RefCell;
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub struct StallEvent {
|
||||
@@ -280,6 +285,18 @@ mod tests {
|
||||
pub enum Origin for Test {}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static NOTIFICATIONS: RefCell<Vec<StallEvent>> = Default::default();
|
||||
}
|
||||
|
||||
pub struct StallTracker;
|
||||
impl OnFinalizationStalled<u64> for StallTracker {
|
||||
fn on_stalled(further_wait: u64, _median: u64) {
|
||||
let now = System::block_number();
|
||||
NOTIFICATIONS.with(|v| v.borrow_mut().push(StallEvent { at: now, further_wait }));
|
||||
}
|
||||
}
|
||||
|
||||
impl system::Trait for Test {
|
||||
type Origin = Origin;
|
||||
type Index = u64;
|
||||
@@ -291,31 +308,22 @@ mod tests {
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
type System = system::Module<Test>;
|
||||
|
||||
thread_local! {
|
||||
static NOTIFICATIONS: std::cell::RefCell<Vec<StallEvent>> = Default::default();
|
||||
parameter_types! {
|
||||
pub const WindowSize: u64 = 11;
|
||||
pub const ReportLatency: u64 = 100;
|
||||
}
|
||||
|
||||
pub struct StallTracker;
|
||||
impl OnFinalizationStalled<u64> for StallTracker {
|
||||
fn on_stalled(further_wait: u64, _median: u64) {
|
||||
let now = System::block_number();
|
||||
NOTIFICATIONS.with(|n| n.borrow_mut().push(StallEvent { at: now, further_wait }));
|
||||
}
|
||||
}
|
||||
|
||||
impl Trait for Test {
|
||||
type OnFinalizationStalled = StallTracker;
|
||||
type WindowSize = WindowSize;
|
||||
type ReportLatency = ReportLatency;
|
||||
}
|
||||
|
||||
type System = system::Module<Test>;
|
||||
type FinalityTracker = Module<Test>;
|
||||
|
||||
#[test]
|
||||
fn median_works() {
|
||||
let t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0;
|
||||
|
||||
with_externalities(&mut TestExternalities::new(t), || {
|
||||
FinalityTracker::update_hint(Some(500));
|
||||
assert_eq!(FinalityTracker::median(), 250);
|
||||
@@ -325,12 +333,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn notifies_when_stalled() {
|
||||
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0;
|
||||
t.extend(GenesisConfig::<Test> {
|
||||
window_size: 11,
|
||||
report_latency: 100
|
||||
}.build_storage().unwrap().0);
|
||||
|
||||
let t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0;
|
||||
with_externalities(&mut TestExternalities::new(t), || {
|
||||
let mut parent_hash = System::parent_hash();
|
||||
for i in 2..106 {
|
||||
@@ -349,12 +352,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn recent_notifications_prevent_stalling() {
|
||||
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0;
|
||||
t.extend(GenesisConfig::<Test> {
|
||||
window_size: 11,
|
||||
report_latency: 100
|
||||
}.build_storage().unwrap().0);
|
||||
|
||||
let t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0;
|
||||
with_externalities(&mut TestExternalities::new(t), || {
|
||||
let mut parent_hash = System::parent_hash();
|
||||
for i in 2..106 {
|
||||
|
||||
@@ -442,6 +442,9 @@ type ExpoMap<T> = BTreeMap<
|
||||
Exposure<<T as system::Trait>::AccountId, BalanceOf<T>>
|
||||
>;
|
||||
|
||||
pub const DEFAULT_SESSIONS_PER_ERA: u32 = 3;
|
||||
pub const DEFAULT_BONDING_DURATION: u32 = 1;
|
||||
|
||||
pub trait Trait: system::Trait + session::Trait {
|
||||
/// The staking balance.
|
||||
type Currency: LockableCurrency<Self::AccountId, Moment=Self::BlockNumber>;
|
||||
|
||||
@@ -22,7 +22,8 @@ use primitives::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize};
|
||||
use primitives::testing::{Header, UintAuthorityId};
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
use runtime_io;
|
||||
use srml_support::{impl_outer_origin, parameter_types, assert_ok, traits::Currency, EnumerableStorageMap};
|
||||
use srml_support::{assert_ok, impl_outer_origin, parameter_types, EnumerableStorageMap};
|
||||
use srml_support::traits::{Currency, Get};
|
||||
use crate::{EraIndex, GenesisConfig, Module, Trait, StakerStatus,
|
||||
ValidatorPrefs, RewardDestination, Nominators
|
||||
};
|
||||
@@ -45,6 +46,7 @@ impl Convert<u128, u64> for CurrencyToVoteHandler {
|
||||
|
||||
thread_local! {
|
||||
static SESSION: RefCell<(Vec<AccountId>, HashSet<AccountId>)> = RefCell::new(Default::default());
|
||||
static EXISTENTIAL_DEPOSIT: RefCell<u64> = RefCell::new(0);
|
||||
}
|
||||
|
||||
pub struct TestSessionHandler;
|
||||
@@ -69,6 +71,13 @@ pub fn is_disabled(validator: AccountId) -> bool {
|
||||
SESSION.with(|d| d.borrow().1.contains(&validator))
|
||||
}
|
||||
|
||||
pub struct ExistentialDeposit;
|
||||
impl Get<u64> for ExistentialDeposit {
|
||||
fn get() -> u64 {
|
||||
EXISTENTIAL_DEPOSIT.with(|v| *v.borrow())
|
||||
}
|
||||
}
|
||||
|
||||
impl_outer_origin!{
|
||||
pub enum Origin for Test {}
|
||||
}
|
||||
@@ -87,6 +96,12 @@ impl system::Trait for Test {
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
}
|
||||
parameter_types! {
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
pub const TransactionBaseFee: u64 = 0;
|
||||
pub const TransactionByteFee: u64 = 0;
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnFreeBalanceZero = Staking;
|
||||
@@ -95,6 +110,11 @@ impl balances::Trait for Test {
|
||||
type TransactionPayment = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const Period: BlockNumber = 1;
|
||||
@@ -181,7 +201,11 @@ impl ExtBuilder {
|
||||
self.fair = is_fair;
|
||||
self
|
||||
}
|
||||
pub fn set_associated_consts(&self) {
|
||||
EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit);
|
||||
}
|
||||
pub fn build(self) -> runtime_io::TestExternalities<Blake2Hasher> {
|
||||
self.set_associated_consts();
|
||||
let (mut t, mut c) = system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
||||
let balance_factor = if self.existential_deposit > 0 {
|
||||
256
|
||||
@@ -211,11 +235,6 @@ impl ExtBuilder {
|
||||
(100, 2000 * balance_factor),
|
||||
(101, 2000 * balance_factor),
|
||||
],
|
||||
transaction_base_fee: 0,
|
||||
transaction_byte_fee: 0,
|
||||
existential_deposit: self.existential_deposit,
|
||||
transfer_fee: 0,
|
||||
creation_fee: 0,
|
||||
vesting: vec![],
|
||||
}.assimilate_storage(&mut t, &mut c);
|
||||
let stake_21 = if self.fair { 1000 } else { 2000 };
|
||||
|
||||
@@ -72,12 +72,13 @@ use serde::{Serialize, Deserialize};
|
||||
use rstd::prelude::*;
|
||||
use srml_support::{StorageValue, StorageMap, decl_module, decl_storage, decl_event, ensure, print};
|
||||
use srml_support::traits::{
|
||||
Currency, ReservableCurrency, OnDilution, OnUnbalanced, Imbalance, WithdrawReason,
|
||||
ExistenceRequirement
|
||||
Currency, ExistenceRequirement, Get, Imbalance, OnDilution, OnUnbalanced,
|
||||
ReservableCurrency, WithdrawReason
|
||||
};
|
||||
use runtime_primitives::{Permill, ModuleId, traits::{
|
||||
use runtime_primitives::{Permill, ModuleId};
|
||||
use runtime_primitives::traits::{
|
||||
Zero, EnsureOrigin, StaticLookup, CheckedSub, CheckedMul, AccountIdConversion
|
||||
}};
|
||||
};
|
||||
use parity_codec::{Encode, Decode};
|
||||
use system::ensure_signed;
|
||||
|
||||
@@ -87,6 +88,11 @@ type NegativeImbalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::
|
||||
|
||||
const MODULE_ID: ModuleId = ModuleId(*b"py/trsry");
|
||||
|
||||
pub const DEFAULT_PROPOSAL_BOND: u32 = 0;
|
||||
pub const DEFAULT_PROPOSAL_BOND_MINIMUM: u32 = 0;
|
||||
pub const DEFAULT_SPEND_PERIOD: u32 = 0;
|
||||
pub const DEFAULT_BURN: u32 = 0;
|
||||
|
||||
pub trait Trait: system::Trait {
|
||||
/// The staking balance.
|
||||
type Currency: Currency<Self::AccountId> + ReservableCurrency<Self::AccountId>;
|
||||
@@ -105,12 +111,38 @@ pub trait Trait: system::Trait {
|
||||
|
||||
/// Handler for the unbalanced decrease when slashing for a rejected proposal.
|
||||
type ProposalRejection: OnUnbalanced<NegativeImbalanceOf<Self>>;
|
||||
|
||||
/// Fraction of a proposal's value that should be bonded in order to place the proposal.
|
||||
/// An accepted proposal gets these back. A rejected proposal does not.
|
||||
type ProposalBond: Get<Permill>;
|
||||
|
||||
/// Minimum amount of funds that should be placed in a deposit for making a proposal.
|
||||
type ProposalBondMinimum: Get<BalanceOf<Self>>;
|
||||
|
||||
/// Period between successive spends.
|
||||
type SpendPeriod: Get<Self::BlockNumber>;
|
||||
|
||||
/// Percentage of spare funds (if any) that are burnt per spend period.
|
||||
type Burn: Get<Permill>;
|
||||
}
|
||||
|
||||
type ProposalIndex = u32;
|
||||
|
||||
decl_module! {
|
||||
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
||||
/// Fraction of a proposal's value that should be bonded in order to place the proposal.
|
||||
/// An accepted proposal gets these back. A rejected proposal does not.
|
||||
const ProposalBond: Permill = T::ProposalBond::get();
|
||||
|
||||
/// Minimum amount of funds that should be placed in a deposit for making a proposal.
|
||||
const ProposalBondMinimum: BalanceOf<T> = T::ProposalBondMinimum::get();
|
||||
|
||||
/// Period between successive spends.
|
||||
const SpendPeriod: T::BlockNumber = T::SpendPeriod::get();
|
||||
|
||||
/// Percentage of spare funds (if any) that are burnt per spend period.
|
||||
const Burn: Permill = T::Burn::get();
|
||||
|
||||
fn deposit_event<T>() = default;
|
||||
/// Put forward a suggestion for spending. A deposit proportional to the value
|
||||
/// is reserved and slashed if the proposal is rejected. It is returned once the
|
||||
@@ -140,19 +172,6 @@ decl_module! {
|
||||
Self::deposit_event(RawEvent::Proposed(c));
|
||||
}
|
||||
|
||||
/// (Re-)configure this module.
|
||||
fn configure(
|
||||
#[compact] proposal_bond: Permill,
|
||||
#[compact] proposal_bond_minimum: BalanceOf<T>,
|
||||
#[compact] spend_period: T::BlockNumber,
|
||||
#[compact] burn: Permill
|
||||
) {
|
||||
ProposalBond::put(proposal_bond);
|
||||
<ProposalBondMinimum<T>>::put(proposal_bond_minimum);
|
||||
<SpendPeriod<T>>::put(spend_period);
|
||||
Burn::put(burn);
|
||||
}
|
||||
|
||||
/// Reject a proposed spend. The original deposit will be slashed.
|
||||
///
|
||||
/// # <weight>
|
||||
@@ -187,7 +206,7 @@ decl_module! {
|
||||
|
||||
fn on_finalize(n: T::BlockNumber) {
|
||||
// Check to see if we should spend some funds!
|
||||
if (n % Self::spend_period()).is_zero() {
|
||||
if (n % T::SpendPeriod::get()).is_zero() {
|
||||
Self::spend_funds();
|
||||
}
|
||||
}
|
||||
@@ -206,23 +225,6 @@ pub struct Proposal<AccountId, Balance> {
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Treasury {
|
||||
// Config...
|
||||
|
||||
/// Fraction of a proposal's value that should be bonded in order to place the proposal.
|
||||
/// An accepted proposal gets these back. A rejected proposal does not.
|
||||
ProposalBond get(proposal_bond) config(): Permill;
|
||||
|
||||
/// Minimum amount of funds that should be placed in a deposit for making a proposal.
|
||||
ProposalBondMinimum get(proposal_bond_minimum) config(): BalanceOf<T>;
|
||||
|
||||
/// Period between successive spends.
|
||||
SpendPeriod get(spend_period) config(): T::BlockNumber = runtime_primitives::traits::One::one();
|
||||
|
||||
/// Percentage of spare funds (if any) that are burnt per spend period.
|
||||
Burn get(burn) config(): Permill;
|
||||
|
||||
// State...
|
||||
|
||||
/// Number of proposals that have been made.
|
||||
ProposalCount get(proposal_count): ProposalIndex;
|
||||
|
||||
@@ -266,7 +268,7 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
/// The needed bond for a proposal whose spend is `value`.
|
||||
fn calculate_bond(value: BalanceOf<T>) -> BalanceOf<T> {
|
||||
Self::proposal_bond_minimum().max(Self::proposal_bond() * value)
|
||||
T::ProposalBondMinimum::get().max(T::ProposalBond::get() * value)
|
||||
}
|
||||
|
||||
// Spend some money!
|
||||
@@ -304,7 +306,7 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
if !missed_any {
|
||||
// burn some proportion of the remaining budget if we run a surplus.
|
||||
let burn = (Self::burn() * budget_remaining).min(budget_remaining);
|
||||
let burn = (T::Burn::get() * budget_remaining).min(budget_remaining);
|
||||
budget_remaining -= burn;
|
||||
imbalance.subsume(T::Currency::burn(burn));
|
||||
Self::deposit_event(RawEvent::Burnt(burn))
|
||||
@@ -356,7 +358,7 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
use runtime_io::with_externalities;
|
||||
use srml_support::{impl_outer_origin, assert_ok, assert_noop};
|
||||
use srml_support::{assert_noop, assert_ok, impl_outer_origin, parameter_types};
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
use runtime_primitives::{traits::{BlakeTwo256, OnFinalize, IdentityLookup}, testing::Header};
|
||||
|
||||
@@ -377,6 +379,13 @@ mod tests {
|
||||
type Header = Header;
|
||||
type Event = ();
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 0;
|
||||
pub const TransferFee: u64 = 0;
|
||||
pub const CreationFee: u64 = 0;
|
||||
pub const TransactionBaseFee: u64 = 0;
|
||||
pub const TransactionByteFee: u64 = 0;
|
||||
}
|
||||
impl balances::Trait for Test {
|
||||
type Balance = u64;
|
||||
type OnNewAccount = ();
|
||||
@@ -385,6 +394,17 @@ mod tests {
|
||||
type TransactionPayment = ();
|
||||
type TransferPayment = ();
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ExistentialDeposit;
|
||||
type TransferFee = TransferFee;
|
||||
type CreationFee = CreationFee;
|
||||
type TransactionBaseFee = TransactionBaseFee;
|
||||
type TransactionByteFee = TransactionByteFee;
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ProposalBond: Permill = Permill::from_percent(5);
|
||||
pub const ProposalBondMinimum: u64 = 1;
|
||||
pub const SpendPeriod: u64 = 2;
|
||||
pub const Burn: Permill = Permill::from_percent(50);
|
||||
}
|
||||
impl Trait for Test {
|
||||
type Currency = balances::Module<Test>;
|
||||
@@ -393,6 +413,10 @@ mod tests {
|
||||
type Event = ();
|
||||
type MintedForSpending = ();
|
||||
type ProposalRejection = ();
|
||||
type ProposalBond = ProposalBond;
|
||||
type ProposalBondMinimum = ProposalBondMinimum;
|
||||
type SpendPeriod = SpendPeriod;
|
||||
type Burn = Burn;
|
||||
}
|
||||
type Balances = balances::Module<Test>;
|
||||
type Treasury = Module<Test>;
|
||||
@@ -401,29 +425,14 @@ mod tests {
|
||||
let mut t = system::GenesisConfig::default().build_storage::<Test>().unwrap().0;
|
||||
t.extend(balances::GenesisConfig::<Test>{
|
||||
balances: vec![(0, 100), (1, 99), (2, 1)],
|
||||
transaction_base_fee: 0,
|
||||
transaction_byte_fee: 0,
|
||||
transfer_fee: 0,
|
||||
creation_fee: 0,
|
||||
existential_deposit: 0,
|
||||
vesting: vec![],
|
||||
}.build_storage().unwrap().0);
|
||||
t.extend(GenesisConfig::<Test>{
|
||||
proposal_bond: Permill::from_percent(5),
|
||||
proposal_bond_minimum: 1,
|
||||
spend_period: 2,
|
||||
burn: Permill::from_percent(50),
|
||||
}.build_storage().unwrap().0);
|
||||
t.into()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn genesis_config_works() {
|
||||
with_externalities(&mut new_test_ext(), || {
|
||||
assert_eq!(Treasury::proposal_bond(), Permill::from_percent(5));
|
||||
assert_eq!(Treasury::proposal_bond_minimum(), 1);
|
||||
assert_eq!(Treasury::spend_period(), 2);
|
||||
assert_eq!(Treasury::burn(), Permill::from_percent(50));
|
||||
assert_eq!(Treasury::pot(), 0);
|
||||
assert_eq!(Treasury::proposal_count(), 0);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user