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:
David Craven
2019-07-02 12:52:58 +02:00
committed by GitHub
parent b2622b611e
commit cf036f685e
23 changed files with 943 additions and 597 deletions
+14 -1
View File
@@ -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![],
}),
+14 -87
View File
@@ -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,
+2 -2
View File
@@ -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();
+72 -177
View File
@@ -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);
});
}
+3
View File
@@ -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;
+116 -23
View File
@@ -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,
}
+72 -21
View File
@@ -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,
+48 -6
View File
@@ -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 {
+3 -3
View File
@@ -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(),
+4 -3
View File
@@ -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);
+150 -49
View File
@@ -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(),
}
}
}
+5 -5
View File
@@ -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.
+81 -26
View File
@@ -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);
}
);
}
+68 -19
View File
@@ -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)
+108 -50
View File
@@ -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),
+19 -5
View File
@@ -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);
+13 -1
View File
@@ -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 = ();
+19 -11
View File
@@ -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![], },
},
+42 -44
View File
@@ -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 {
+3
View File
@@ -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>;
+25 -6
View File
@@ -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 };
+62 -53
View File
@@ -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);
});