Skip to content

Commit

Permalink
bond_extra should be authorised only from stash (paritytech#2096)
Browse files Browse the repository at this point in the history
* bond_extra should be authorised only from stash, lest the controller
gets compromised.

* Fix tests

* Fix grumbles

* Pass compact balances
  • Loading branch information
gavofyork authored and MTDK1 committed Apr 12, 2019
1 parent 08721ed commit 4a73126
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 14 deletions.
Binary file not shown.
2 changes: 1 addition & 1 deletion node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("node"),
impl_name: create_runtime_str!("substrate-node"),
authoring_version: 10,
spec_version: 41,
spec_version: 42,
impl_version: 42,
apis: RUNTIME_API_VERSIONS,
};
Expand Down
Binary file not shown.
22 changes: 12 additions & 10 deletions srml/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ use srml_support::traits::{
};
use session::OnSessionChange;
use primitives::Perbill;
use primitives::traits::{Zero, One, As, StaticLookup, Saturating, Bounded};
use primitives::traits::{Zero, One, As, StaticLookup, CheckedSub, Saturating, Bounded};
#[cfg(feature = "std")]
use primitives::{Serialize, Deserialize};
use system::ensure_signed;
Expand Down Expand Up @@ -549,14 +549,17 @@ decl_module! {
///
/// Use this if there are additional funds in your stash account that you wish to bond.
///
/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
fn bond_extra(origin, max_additional: BalanceOf<T>) {
let controller = ensure_signed(origin)?;
/// The dispatch origin for this call must be _Signed_ by the stash, not the controller.
fn bond_extra(origin, #[compact] max_additional: BalanceOf<T>) {
let stash = ensure_signed(origin)?;

let controller = Self::bonded(&stash).ok_or("not a stash")?;
let mut ledger = Self::ledger(&controller).ok_or("not a controller")?;
let stash_balance = T::Currency::free_balance(&ledger.stash);

if stash_balance > ledger.total {
let extra = (stash_balance - ledger.total).min(max_additional);
let stash_balance = T::Currency::free_balance(&stash);

if let Some(extra) = stash_balance.checked_sub(&ledger.total) {
let extra = extra.min(max_additional);
ledger.total += extra;
ledger.active += extra;
Self::update_ledger(&controller, &ledger);
Expand All @@ -583,8 +586,7 @@ decl_module! {
ledger.active -= value;

// Avoid there being a dust balance left in the staking system.
let ed = T::Currency::minimum_balance();
if ledger.active < ed {
if ledger.active < T::Currency::minimum_balance() {
value += ledger.active;
ledger.active = Zero::zero();
}
Expand Down Expand Up @@ -672,7 +674,7 @@ decl_module! {
///
/// Effects will be felt at the beginning of the next era.
///
/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
/// The dispatch origin for this call must be _Signed_ by the stash, not the controller.
fn set_controller(origin, controller: <T::Lookup as StaticLookup>::Source) {
let stash = ensure_signed(origin)?;
let old_controller = Self::bonded(&stash).ok_or("not a stash")?;
Expand Down
6 changes: 3 additions & 3 deletions srml/staking/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1104,12 +1104,12 @@ fn bond_extra_works() {
let _ = Balances::make_free_balance_be(&11, 1000000);

// Call the bond_extra function from controller, add only 100
assert_ok!(Staking::bond_extra(Origin::signed(10), 100));
assert_ok!(Staking::bond_extra(Origin::signed(11), 100));
// There should be 100 more `total` and `active` in the ledger
assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 100, active: 1000 + 100, unlocking: vec![] }));

// Call the bond_extra function with a large number, should handle it
assert_ok!(Staking::bond_extra(Origin::signed(10), u64::max_value()));
assert_ok!(Staking::bond_extra(Origin::signed(11), u64::max_value()));
// The full amount of the funds should now be in the total and active
assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000000, active: 1000000, unlocking: vec![] }));

Expand Down Expand Up @@ -1161,7 +1161,7 @@ fn bond_extra_and_withdraw_unbonded_works() {
assert_eq!(Staking::stakers(&11), Exposure { total: 1000, own: 1000, others: vec![] });

// deposit the extra 100 units
Staking::bond_extra(Origin::signed(10), 100).unwrap();
Staking::bond_extra(Origin::signed(11), 100).unwrap();

assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 100, active: 1000 + 100, unlocking: vec![] }));
// Exposure is a snapshot! only updated after the next era update.
Expand Down

0 comments on commit 4a73126

Please sign in to comment.