diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index 40f4ce8c514d0..cde01ac5fd72d 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -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 { diff --git a/node-template/src/chain_spec.rs b/node-template/src/chain_spec.rs index b8cc7aef32e12..7e226f6ab55e7 100644 --- a/node-template/src/chain_spec.rs +++ b/node-template/src/chain_spec.rs @@ -104,11 +104,6 @@ fn testnet_genesis(initial_authorities: Vec, 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![], }), diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index 63c59688bc8fb..63b1ff2444d7e 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -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, diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index e27baca8e6995..4fe3c7ef9c15a 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -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<::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(); diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index edf99e064e59e..606fa76ca7cf9 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -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 = CoreTestExternalities; fn alice() -> AccountId { @@ -131,7 +136,7 @@ mod tests { fn xt() -> UncheckedExtrinsic { sign(CheckedExtrinsic { signed: Some((alice(), 0)), - function: Call::Balances(balances::Call::transfer::(bob().into(), 69)), + function: Call::Balances(balances::Call::transfer::(bob().into(), 69 * DOLLARS)), }) } @@ -147,18 +152,9 @@ mod tests { fn panic_execution_with_foreign_code_gives_error() { let mut t = TestExternalities::::new_with_code(BLOATY_CODE, map![ blake2_256(&>::key_for(alice())).to_vec() => { - vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - }, - twox_128(>::key()).to_vec() => { - vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - }, - twox_128(>::key()).to_vec() => { vec![0u8; 16] }, - twox_128(>::key()).to_vec() => { - vec![0u8; 16] - }, - twox_128(>::key()).to_vec() => { + twox_128(>::key()).to_vec() => { vec![0u8; 16] }, twox_128(>::key()).to_vec() => { @@ -166,12 +162,6 @@ mod tests { }, blake2_256(&>::key_for(0)).to_vec() => { vec![0u8; 32] - }, - twox_128(>::key()).to_vec() => { - vec![70u8; 16] - }, - twox_128(>::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::::new_with_code(COMPACT_CODE, map![ blake2_256(&>::key_for(alice())).to_vec() => { - vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - }, - twox_128(>::key()).to_vec() => { - vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - }, - twox_128(>::key()).to_vec() => { - vec![0u8; 16] - }, - twox_128(>::key()).to_vec() => { vec![0u8; 16] }, - twox_128(>::key()).to_vec() => { + twox_128(>::key()).to_vec() => { vec![0u8; 16] }, twox_128(>::key()).to_vec() => { @@ -217,12 +198,6 @@ mod tests { }, blake2_256(&>::key_for(0)).to_vec() => { vec![0u8; 32] - }, - twox_128(>::key()).to_vec() => { - vec![70u8; 16] - }, - twox_128(>::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::::new_with_code(COMPACT_CODE, map![ blake2_256(&>::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(>::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(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], - blake2_256(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + blake2_256(&>::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::::new_with_code(BLOATY_CODE, map![ blake2_256(&>::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(>::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(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], - blake2_256(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + blake2_256(&>::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::(10, 10_000, transfer_ch, Vec::new()) + contracts::Call::create::(1 * DOLLARS, 10_000, transfer_ch, Vec::new()) ), }, CheckedExtrinsic { @@ -928,18 +833,13 @@ mod tests { fn panic_execution_gives_error() { let mut t = TestExternalities::::new_with_code(BLOATY_CODE, map![ blake2_256(&>::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(>::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(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], - blake2_256(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![70u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + blake2_256(&>::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::::new_with_code(COMPACT_CODE, map![ blake2_256(&>::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(>::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(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], - blake2_256(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + blake2_256(&>::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); }); } diff --git a/node/primitives/src/lib.rs b/node/primitives/src/lib.rs index 8b7b2521e4000..f6238907d557b 100644 --- a/node/primitives/src/lib.rs +++ b/node/primitives/src/lib.rs @@ -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; diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index f0a5a0acf3411..5bc730ef1b5cf 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -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 = >::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 for CurrencyToVoteHandler { - fn convert(x: u128) -> u64 { (x / Self::factor()) as u64 } -} - -impl Convert 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 for CurrencyToVoteHandler { + fn convert(x: u128) -> u64 { (x / Self::factor()) as u64 } +} + +impl Convert 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; type TrieIdGenerator = contracts::TrieIdFromParentCounter; 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}, FinalityTracker: finality_tracker::{Module, Call, Inherent}, Grandpa: grandpa::{Module, Call, Storage, Config, Event}, - Treasury: treasury, + Treasury: treasury::{Module, Call, Storage, Event}, Contracts: contracts, Sudo: sudo, } diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 94093a587b9ce..a547252d118f8 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -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: system::Trait { /// The balance of an account. type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + @@ -183,6 +189,21 @@ pub trait Subtrait: system::Trait { /// Handler for when a new account is created. type OnNewAccount: OnNewAccount; + + /// The minimum amount required to keep an account open. + type ExistentialDeposit: Get; + + /// The fee required to make a transfer. + type TransferFee: Get; + + /// The fee required to create an account. + type CreationFee: Get; + + /// The fee to be paid for making a transaction; the base. + type TransactionBaseFee: Get; + + /// The fee to be paid for making a transaction; the per-byte portion. + type TransactionByteFee: Get; } pub trait Trait: system::Trait { @@ -211,12 +232,32 @@ pub trait Trait: system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; + + /// The minimum amount required to keep an account open. + type ExistentialDeposit: Get; + + /// The fee required to make a transfer. + type TransferFee: Get; + + /// The fee required to create an account. + type CreationFee: Get; + + /// The fee to be paid for making a transaction; the base. + type TransactionBaseFee: Get; + + /// The fee to be paid for making a transaction; the per-byte portion. + type TransactionByteFee: Get; } impl, I: Instance> Subtrait 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| { 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| { @@ -341,6 +372,21 @@ decl_storage! { decl_module! { pub struct Module, 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() = default; /// Transfer some liquid free balance to another account. @@ -440,7 +486,7 @@ impl, I: Instance> Module { /// 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() { >::insert(who, balance); Self::on_reserved_too_low(who); UpdateBalanceOutcome::AccountKilled @@ -461,8 +507,8 @@ impl, I: Instance> Module { 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() { >::insert(who, balance); Self::on_free_too_low(who); UpdateBalanceOutcome::AccountKilled @@ -707,6 +753,11 @@ impl, I: Instance> Trait for ElevatedTrait { 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, I: Instance> Currency for Module @@ -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 { 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 < >::existential_deposit() { + let outcome = if balance < T::ExistentialDeposit::get() { Self::set_free_balance(who, balance); UpdateBalanceOutcome::AccountKilled } else { @@ -1079,7 +1130,7 @@ where impl, I: Instance> MakePayment for Module { 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, diff --git a/srml/balances/src/mock.rs b/srml/balances/src/mock.rs index 44e046b68192e..1c749d9e351a1 100644 --- a/srml/balances/src/mock.rs +++ b/srml/balances/src/mock.rs @@ -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 = RefCell::new(0); + static TRANSFER_FEE: RefCell = RefCell::new(0); + static CREATION_FEE: RefCell = RefCell::new(0); + static TRANSACTION_BASE_FEE: RefCell = RefCell::new(0); + static TRANSACTION_BYTE_FEE: RefCell = RefCell::new(0); +} + +pub struct ExistentialDeposit; +impl Get for ExistentialDeposit { + fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } +} + +pub struct TransferFee; +impl Get for TransferFee { + fn get() -> u64 { TRANSFER_FEE.with(|v| *v.borrow()) } +} + +pub struct CreationFee; +impl Get for CreationFee { + fn get() -> u64 { CREATION_FEE.with(|v| *v.borrow()) } +} + +pub struct TransactionBaseFee; +impl Get for TransactionBaseFee { + fn get() -> u64 { TRANSACTION_BASE_FEE.with(|v| *v.borrow()) } +} + +pub struct TransactionByteFee; +impl Get 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 { + self.set_associated_consts(); let mut t = system::GenesisConfig::default().build_storage::().unwrap().0; t.extend(GenesisConfig:: { - 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 { diff --git a/srml/contracts/src/account_db.rs b/srml/contracts/src/account_db.rs index 80d5fbe3bba58..264c57aa3f1dd 100644 --- a/srml/contracts/src/account_db.rs +++ b/srml/contracts/src/account_db.rs @@ -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 AccountDb for DirectAccountDb { } else if let Some(code_hash) = changed.code_hash { AliveContractInfo:: { code_hash, - storage_size: >::storage_size_offset(), + storage_size: T::StorageSizeOffset::get(), trie_id: ::TrieIdGenerator::trie_id(&address), deduct_block: >::block_number(), rent_allowance: >::max_value(), diff --git a/srml/contracts/src/gas.rs b/srml/contracts/src/gas.rs index 8f8ebd3604a0c..d941ad46cd6d9 100644 --- a/srml/contracts/src/gas.rs +++ b/srml/contracts/src/gas.rs @@ -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( gas_limit: Gas, ) -> Result<(GasMeter, NegativeImbalanceOf), &'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 = >::block_gas_limit() - >::gas_spent(); + // This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`. + let gas_available = T::BlockGasLimit::get() - >::gas_spent(); if gas_limit > gas_available { // gas limit reached, revert the transaction and retry again in the future return Err(BLOCK_FULL); diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index 93e54320f06b2..ec836419ab02c 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -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 = <::Currency as Currency< pub type NegativeImbalanceOf = <::Currency as Currency<::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; @@ -302,6 +318,67 @@ pub trait Trait: timestamp::Trait { /// Handler for the unbalanced reduction when making a gas payment. type GasPayment: OnUnbalanced>; + + /// 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; + + /// The minimum amount required to generate a tombstone. + type TombstoneDeposit: Get>; + + /// 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; + + /// Price of a byte of storage per one block interval. Should be greater than 0. + type 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. + type RentDepositOffset: Get>; + + /// Reward that is received by the party whose touch has led + /// to removal of a contract. + type SurchargeReward: Get>; + + /// The fee required to make a transfer. + type TransferFee: Get>; + + /// The fee required to create an account. + type CreationFee: Get>; + + /// The fee to be paid for making a transaction; the base. + type TransactionBaseFee: Get>; + + /// The fee to be paid for making a transaction; the per-byte portion. + type TransactionByteFee: Get>; + + /// The fee required to create a contract instance. A reasonable default value + /// is 21. + type ContractFee: Get>; + + /// The base fee charged for calling into a contract. A reasonable default + /// value is 135. + type CallBaseFee: Get; + + /// The base fee charged for creating a contract. A reasonable default value + /// is 175. + type CreateBaseFee: Get; + + /// The maximum nesting level of a call/create stack. A reasonable default + /// value is 100. + type MaxDepth: Get; + + /// The maximum amount of gas that could be expended per block. A reasonable + /// default value is 10_000_000. + type BlockGasLimit: Get; } /// Simple contract address determiner. @@ -333,8 +410,8 @@ pub struct DefaultDispatchFeeComputor(PhantomData); impl ComputeDispatchFee> for DefaultDispatchFeeComputor { fn compute_dispatch_fee(call: &T::Call) -> BalanceOf { let encoded_len = call.using_encoded(|encoded| encoded.len() as u32); - let base_fee = >::transaction_base_fee(); - let byte_fee = >::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 ComputeDispatchFee> for DefaultDispatchFeeC decl_module! { /// Contracts module. pub struct Module for enum Call where origin: ::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::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::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::RentDepositOffset::get(); + + /// Reward that is received by the party whose touch has led + /// to removal of a contract. + const SurchargeReward: BalanceOf = T::SurchargeReward::get(); + + /// The fee required to make a transfer. + const TransferFee: BalanceOf = T::TransferFee::get(); + + /// The fee required to create an account. + const CreationFee: BalanceOf = T::CreationFee::get(); + + /// The fee to be paid for making a transaction; the base. + const TransactionBaseFee: BalanceOf = T::TransactionBaseFee::get(); + + /// The fee to be paid for making a transaction; the per-byte portion. + const TransactionByteFee: BalanceOf = T::TransactionByteFee::get(); + + /// The fee required to create a contract instance. A reasonable default value + /// is 21. + const ContractFee: BalanceOf = 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() = 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 { - >::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::(&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 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; - /// 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; - /// 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; - /// Reward that is received by the party whose touch has led - /// to removal of a contract. - SurchargeReward get(surcharge_reward) config(): BalanceOf; - /// The fee required to make a transfer. - TransferFee get(transfer_fee) config(): BalanceOf; - /// The fee required to create an account. - CreationFee get(creation_fee) config(): BalanceOf; - /// The fee to be paid for making a transaction; the base. - TransactionBaseFee get(transaction_base_fee) config(): BalanceOf; - /// The fee to be paid for making a transaction; the per-byte portion. - TransactionByteFee get(transaction_byte_fee) config(): BalanceOf; - /// The fee required to create a contract instance. - ContractFee get(contract_fee) config(): BalanceOf = 21.into(); - /// The price of one unit of gas. - GasPrice get(gas_price) config(): BalanceOf = 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>; + /// The price of one unit of gas. + GasPrice get(gas_price) config(): BalanceOf = 1.into(); } } @@ -725,10 +826,10 @@ impl Config { Config { schedule: >::current_schedule(), existential_deposit: T::Currency::minimum_balance(), - max_depth: >::max_depth(), - contract_account_instantiate_fee: >::contract_fee(), - account_create_fee: >::creation_fee(), - transfer_fee: >::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(), } } } diff --git a/srml/contracts/src/rent.rs b/srml/contracts/src/rent.rs index 3be39af6aad53..08175a12d97f7 100644 --- a/srml/contracts/src/rent.rs +++ b/srml/contracts/src/rent.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -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( // 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(&>::rent_deposit_offset()) + .checked_div(&T::RentDepositOffset::get()) .unwrap_or_else(Zero::zero); let effective_storage_size = >::from(contract.storage_size).saturating_sub(free_storage); effective_storage_size - .checked_mul(&>::rent_byte_price()) + .checked_mul(&T::RentByteFee::get()) .unwrap_or(>::max_value()) }; @@ -93,7 +93,7 @@ fn try_evict_or_and_pay_rent( } // The minimal amount of funds required for a contract not to be evicted. - let subsistence_threshold = T::Currency::minimum_balance() + >::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. diff --git a/srml/contracts/src/tests.rs b/srml/contracts/src/tests.rs index e4f435817bc43..ab483298f6c38 100644 --- a/srml/contracts/src/tests.rs +++ b/srml/contracts/src/tests.rs @@ -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 = RefCell::new(0); + static TRANSFER_FEE: RefCell = RefCell::new(0); + static CREATION_FEE: RefCell = RefCell::new(0); + static BLOCK_GAS_LIMIT: RefCell = RefCell::new(0); +} + +pub struct ExistentialDeposit; +impl Get for ExistentialDeposit { + fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) } +} + +pub struct TransferFee; +impl Get for TransferFee { + fn get() -> u64 { TRANSFER_FEE.with(|v| *v.borrow()) } +} + +pub struct CreationFee; +impl Get for CreationFee { + fn get() -> u64 { CREATION_FEE.with(|v| *v.borrow()) } +} + +pub struct BlockGasLimit; +impl Get 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; @@ -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 { + self.set_associated_consts(); let mut t = system::GenesisConfig::default().build_storage::().unwrap().0; t.extend( balances::GenesisConfig:: { - 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:: { - 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::::insert(1, &ContractInfo::Alive(RawAliveContractInfo { trie_id: trie_id1.clone(), - storage_size: Contract::storage_size_offset(), + storage_size: ::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::::insert(2, &ContractInfo::Alive(RawAliveContractInfo { trie_id: trie_id2.clone(), - storage_size: Contract::storage_size_offset(), + storage_size: ::StorageSizeOffset::get(), deduct_block: System::block_number(), code_hash: H256::repeat_byte(2), rent_allowance: 40, @@ -795,15 +850,15 @@ fn storage_size() { ::Balance::from(1_000u32).encode() // rent allowance )); let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, Contract::storage_size_offset() + 4); + assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::set_storage_4_byte())); let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, Contract::storage_size_offset() + 4 + 4); + assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4 + 4); assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::remove_storage_4_byte())); let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); - assert_eq!(bob_contract.storage_size, Contract::storage_size_offset() + 4); + assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4); } ); } diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index c319708a31318..496b940cf9e31 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -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 = RefCell::new(0); + static VOTING_FEE: RefCell = RefCell::new(0); + static PRESENT_SLASH_PER_VOTER: RefCell = RefCell::new(0); + static DECAY_RATIO: RefCell = RefCell::new(0); + } + + pub struct VotingBond; + impl Get for VotingBond { + fn get() -> u64 { VOTER_BOND.with(|v| *v.borrow()) } + } + + pub struct VotingFee; + impl Get for VotingFee { + fn get() -> u64 { VOTING_FEE.with(|v| *v.borrow()) } + } + + pub struct PresentSlashPerVoter; + impl Get for PresentSlashPerVoter { + fn get() -> u64 { PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow()) } + } + + pub struct DecayRatio; + impl Get 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; 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 { + self.set_associated_consts(); let mut t = system::GenesisConfig::default().build_storage::().unwrap().0; - t.extend(balances::GenesisConfig:: { - transaction_base_fee: 0, - transaction_byte_fee: 0, + t.extend(balances::GenesisConfig::{ 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:: { - 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) diff --git a/srml/council/src/seats.rs b/srml/council/src/seats.rs index 96097c987fe41..dc84ba7fa77c1 100644 --- a/srml/council/src/seats.rs +++ b/srml/council/src/seats.rs @@ -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> + Into<::Event>; @@ -147,10 +156,80 @@ pub trait Trait: democracy::Trait { type LoserCandidate: OnUnbalanced>; /// What to do when the members change. type OnMembersChanged: OnMembersChanged; + + /// How much should be locked up in order to submit one's candidacy. A reasonable + /// default value is 9. + type CandidacyBond: Get>; + + /// How much should be locked up in order to be able to submit votes. + type VotingBond: Get>; + + /// The amount of fee paid upon each vote submission, unless if they submit a + /// _hole_ index and replace it. + type VotingFee: Get>; + + /// The punishment, per voter, if you provide an invalid presentation. A + /// reasonable default value is 1. + type PresentSlashPerVoter: Get>; + + /// How many runners-up should have their approvals persist until the next + /// vote. A reasonable default value is 2. + type 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. + type InactiveGracePeriod: Get; + + /// How often (in blocks) to check for new votes. A reasonable default value + /// is 1000. + type 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. + type DecayRatio: Get; } decl_module! { pub struct Module 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::CandidacyBond::get(); + + /// How much should be locked up in order to be able to submit votes. + const VotingBond: BalanceOf = 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::VotingFee::get(); + + /// The punishment, per voter, if you provide an invalid presentation. A + /// reasonable default value is 1. + const PresentSlashPerVoter: BalanceOf = 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() = 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")?; >::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::::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 as Council { - // ---- parameters - /// How much should be locked up in order to submit one's candidacy. - pub CandidacyBond get(candidacy_bond) config(): BalanceOf = 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; - /// 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; - /// The punishment, per voter, if you provide an invalid presentation. - pub PresentSlashPerVoter get(present_slash_per_voter) config(): BalanceOf = 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 Module { /// 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 Module { // 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 Module { } 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 Module { 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); >::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 Module { >::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; >::put(vec![(Zero::zero(), T::AccountId::default()); leaderboard_size]); Self::deposit_event(RawEvent::TallyStarted(empty_seats as u32)); @@ -738,7 +796,7 @@ impl Module { let new_expiry = >::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 Module { /// 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: VoteIndex) -> BalanceOf { - let decay_ratio: BalanceOf = Self::decay_ratio().into(); + let decay_ratio: BalanceOf = 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() + ::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!(::CandidacyBond::get(), 3); + assert_eq!(::VotingBond::get(), 0); + assert_eq!(::VotingFee::get(), 0); + assert_eq!(::PresentSlashPerVoter::get(), 1); assert_eq!(Council::presentation_duration(), 2); - assert_eq!(Council::inactivity_grace_period(), 1); - assert_eq!(Council::voting_period(), 4); + assert_eq!(::InactiveGracePeriod::get(), 1); + assert_eq!(::CouncilVotingPeriod::get(), 4); assert_eq!(Council::term_duration(), 5); assert_eq!(Council::desired_seats(), 2); - assert_eq!(Council::carry_count(), 2); + assert_eq!(::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!(::InactiveGracePeriod::get(), 1); + assert_eq!(::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), diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index f3ac2cfe599f7..71375055ab98b 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -165,6 +165,13 @@ impl Decode for Vote { type BalanceOf = <::Currency as Currency<::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 + IsSubType>; type Event: From> + Into<::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 { let mut t = system::GenesisConfig::default().build_storage::().unwrap().0; t.extend(balances::GenesisConfig::{ - 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); diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index 6630f9df56875..7e197c13e3eb5 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -504,7 +504,7 @@ impl Module { 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 = (); diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 8c023da548e23..123510a803495 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -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::().unwrap().0; t.extend(balances::GenesisConfig:: { - 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!(>::total_balance(&1), 32); + assert_eq!(>::total_balance(&1), 42); assert_eq!(>::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![], }, }, diff --git a/srml/finality-tracker/src/lib.rs b/srml/finality-tracker/src/lib.rs index 3bee1c2001cc2..983cef856b7cf 100644 --- a/srml/finality-tracker/src/lib.rs +++ b/srml/finality-tracker/src/lib.rs @@ -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 inherents::ProvideInherentData for InherentDataProvider } } +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; + /// The number of recent samples to keep from this chain. Default is 101. + type WindowSize: Get; + /// The delay after which point things become suspicious. Default is 1000. + type ReportLatency: Get; } decl_storage! { @@ -99,10 +102,6 @@ decl_storage! { OrderedHints get(ordered_hints) build(|_| vec![T::BlockNumber::zero()]): Vec; /// 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; @@ -114,6 +113,12 @@ decl_storage! { decl_module! { pub struct Module 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 Module { 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 Module { if T::BlockNumber::from(our_window_size) == window_size { let now = srml_system::Module::::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> = Default::default(); + } + + pub struct StallTracker; + impl OnFinalizationStalled 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; - - thread_local! { - static NOTIFICATIONS: std::cell::RefCell> = Default::default(); - } - - pub struct StallTracker; - impl OnFinalizationStalled 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 })); - } + parameter_types! { + pub const WindowSize: u64 = 11; + pub const ReportLatency: u64 = 100; } - impl Trait for Test { type OnFinalizationStalled = StallTracker; + type WindowSize = WindowSize; + type ReportLatency = ReportLatency; } + type System = system::Module; type FinalityTracker = Module; #[test] fn median_works() { let t = system::GenesisConfig::default().build_storage::().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::().unwrap().0; - t.extend(GenesisConfig:: { - window_size: 11, - report_latency: 100 - }.build_storage().unwrap().0); - + let t = system::GenesisConfig::default().build_storage::().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::().unwrap().0; - t.extend(GenesisConfig:: { - window_size: 11, - report_latency: 100 - }.build_storage().unwrap().0); - + let t = system::GenesisConfig::default().build_storage::().unwrap().0; with_externalities(&mut TestExternalities::new(t), || { let mut parent_hash = System::parent_hash(); for i in 2..106 { diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index fd05bf17209f5..44344f55ea394 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -442,6 +442,9 @@ type ExpoMap = BTreeMap< Exposure<::AccountId, BalanceOf> >; +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; diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index 5c4b1e0eea98f..e2377a687809c 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -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 for CurrencyToVoteHandler { thread_local! { static SESSION: RefCell<(Vec, HashSet)> = RefCell::new(Default::default()); + static EXISTENTIAL_DEPOSIT: RefCell = 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 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 { + self.set_associated_consts(); let (mut t, mut c) = system::GenesisConfig::default().build_storage::().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 }; diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index f8c844c81032c..182882e58f6ed 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -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 = <::Currency as Currency< + ReservableCurrency; @@ -105,12 +111,38 @@ pub trait Trait: system::Trait { /// Handler for the unbalanced decrease when slashing for a rejected proposal. type ProposalRejection: OnUnbalanced>; + + /// 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; + + /// Minimum amount of funds that should be placed in a deposit for making a proposal. + type ProposalBondMinimum: Get>; + + /// Period between successive spends. + type SpendPeriod: Get; + + /// Percentage of spare funds (if any) that are burnt per spend period. + type Burn: Get; } type ProposalIndex = u32; decl_module! { pub struct Module 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::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() = 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, - #[compact] spend_period: T::BlockNumber, - #[compact] burn: Permill - ) { - ProposalBond::put(proposal_bond); - >::put(proposal_bond_minimum); - >::put(spend_period); - Burn::put(burn); - } - /// Reject a proposed spend. The original deposit will be slashed. /// /// # @@ -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 { decl_storage! { trait Store for Module 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; - - /// 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 Module { /// The needed bond for a proposal whose spend is `value`. fn calculate_bond(value: BalanceOf) -> BalanceOf { - 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 Module { 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; @@ -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; type Treasury = Module; @@ -401,29 +425,14 @@ mod tests { let mut t = system::GenesisConfig::default().build_storage::().unwrap().0; t.extend(balances::GenesisConfig::{ 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::{ - 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); });