diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index 456fb898dd..04bc98cecb 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -70,7 +70,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. spec_version: 109, - impl_version: 109, + impl_version: 110, apis: RUNTIME_API_VERSIONS, }; diff --git a/substrate/srml/elections/src/lib.rs b/substrate/srml/elections/src/lib.rs index 598d014a50..359407d222 100644 --- a/substrate/srml/elections/src/lib.rs +++ b/substrate/srml/elections/src/lib.rs @@ -777,7 +777,7 @@ impl Module { &who, locked_balance, T::BlockNumber::max_value(), - WithdrawReasons::all() + WithdrawReasons::except(WithdrawReason::TransactionPayment), ); >::insert( diff --git a/substrate/srml/executive/src/lib.rs b/substrate/srml/executive/src/lib.rs index 6ee9da3c54..49d4addb3b 100644 --- a/substrate/srml/executive/src/lib.rs +++ b/substrate/srml/executive/src/lib.rs @@ -398,7 +398,7 @@ mod tests { 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 srml_support::traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}; use system; use hex_literal::hex; @@ -435,7 +435,7 @@ mod tests { pub const ExistentialDeposit: u64 = 0; pub const TransferFee: u64 = 0; pub const CreationFee: u64 = 0; - pub const TransactionBaseFee: u64 = 0; + pub const TransactionBaseFee: u64 = 10; pub const TransactionByteFee: u64 = 0; } impl balances::Trait for Runtime { @@ -498,14 +498,17 @@ mod tests { Digest::default(), )); Executive::apply_extrinsic(xt).unwrap(); - assert_eq!(>::total_balance(&1), 42); + assert_eq!(>::total_balance(&1), 42 - 10); assert_eq!(>::total_balance(&2), 69); }); } fn new_test_ext() -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - balances::GenesisConfig::::default().assimilate_storage(&mut t.0, &mut t.1).unwrap(); + let mut t = system::GenesisConfig::default().build_storage::().unwrap().0; + t.extend(balances::GenesisConfig:: { + balances: vec![(1, 111)], + vesting: vec![], + }.build_storage().unwrap().0); t.into() } @@ -516,7 +519,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("d75c79776d69123b65e819977b70e102482e05fd7538c1dcae1249a248ba64e4").into(), + state_root: hex!("9159f07939faa7de6ec7f46e292144fc82112c42ead820dfb588f1788f3e8058").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Digest { logs: vec![], }, }, @@ -645,4 +648,41 @@ mod tests { assert_eq!(Executive::apply_extrinsic(xt), Ok(ApplyOutcome::Fail)); }); } + + #[test] + fn can_pay_for_tx_fee_on_full_lock() { + let id: LockIdentifier = *b"0 "; + let execute_with_lock = |lock: WithdrawReasons| { + let mut t = new_test_ext(); + with_externalities(&mut t, || { + as LockableCurrency>::set_lock( + id, + &1, + 110, + 10, + lock, + ); + let xt = primitives::testing::TestXt(Some(1), 0, Call::transfer(2, 10)); + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + if lock == WithdrawReasons::except(WithdrawReason::TransactionPayment) { + assert_eq!(Executive::apply_extrinsic(xt).unwrap(), ApplyOutcome::Fail); + // but tx fee has been deducted. the transaction failed on transfer, not on fee. + assert_eq!(>::total_balance(&1), 111 - 10); + } else { + assert_eq!(Executive::apply_extrinsic(xt), Err(ApplyError::CantPay)); + assert_eq!(>::total_balance(&1), 111); + } + }); + }; + + execute_with_lock(WithdrawReasons::all()); + execute_with_lock(WithdrawReasons::except(WithdrawReason::TransactionPayment)); + } } diff --git a/substrate/srml/staking/src/lib.rs b/substrate/srml/staking/src/lib.rs index b87155fda2..7dfe7b60e9 100644 --- a/substrate/srml/staking/src/lib.rs +++ b/substrate/srml/staking/src/lib.rs @@ -278,7 +278,7 @@ use srml_support::{ StorageValue, StorageMap, EnumerableStorageMap, decl_module, decl_event, decl_storage, ensure, traits::{ Currency, OnFreeBalanceZero, OnDilution, LockIdentifier, LockableCurrency, - WithdrawReasons, OnUnbalanced, Imbalance, Get + WithdrawReasons, WithdrawReason, OnUnbalanced, Imbalance, Get } }; use session::{historical::OnSessionEnding, SelectInitialValidators, SessionIndex}; @@ -969,7 +969,8 @@ impl Module { // MUTABLES (DANGEROUS) - /// Update the ledger for a controller. This will also update the stash lock. + /// Update the ledger for a controller. This will also update the stash lock. The lock will + /// will lock the entire funds except paying for further transactions. fn update_ledger( controller: &T::AccountId, ledger: &StakingLedger> @@ -979,7 +980,7 @@ impl Module { &ledger.stash, ledger.total, T::BlockNumber::max_value(), - WithdrawReasons::all() + WithdrawReasons::except(WithdrawReason::TransactionPayment), ); >::insert(controller, ledger); } diff --git a/substrate/srml/support/src/traits.rs b/substrate/srml/support/src/traits.rs index ed76338391..86071a37a2 100644 --- a/substrate/srml/support/src/traits.rs +++ b/substrate/srml/support/src/traits.rs @@ -630,6 +630,15 @@ bitmask! { } } +impl WithdrawReasons { + /// Choose all variants except for `one`. + pub fn except(one: WithdrawReason) -> WithdrawReasons { + let mut mask = Self::all(); + mask.toggle(one); + mask + } +} + /// Trait for type that can handle incremental changes to a set of account IDs. pub trait ChangeMembers { /// A number of members `_incoming` just joined the set and replaced some `_outgoing` ones. The