Skip to content

Commit

Permalink
Merge pull request #355 from liberland/BLOCKCHAIN-386-substrate-send-…
Browse files Browse the repository at this point in the history
…lld-in-staked-form-development

BLOCKCHAIN-386 Substrate send LLD in staked form - added bond_to
  • Loading branch information
DorianSternVukotic authored Feb 27, 2024
2 parents a9de022 + 01d3d1c commit f34f1a3
Show file tree
Hide file tree
Showing 4 changed files with 288 additions and 1 deletion.
12 changes: 12 additions & 0 deletions substrate/frame/staking/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,18 @@ benchmarks! {
assert_eq!(CitizenshipRequired::<T>::get(), true);
}

bond_to {
let stash = create_funded_user::<T>("stash", USER_SEED, 100);
let stash_two = create_funded_user::<T>("stash", 3, 100);
let amount = T::Currency::minimum_balance() * 10u32.into();
whitelist_account!(stash);
whitelist_account!(stash_two);
}: _(RawOrigin::Signed(stash), stash_two.clone(), amount)
verify {
assert!(Bonded::<T>::contains_key(stash_two.clone()));
assert!(Ledger::<T>::contains_key(stash_two));
}

impl_benchmark_test_suite!(
Staking,
crate::mock::ExtBuilder::default().has_stakers(true),
Expand Down
41 changes: 41 additions & 0 deletions substrate/frame/staking/src/pallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use frame_support::{
Currency, Defensive, DefensiveResult, DefensiveSaturating, EnsureOrigin,
EstimateNextNewSession, Get, LockIdentifier, LockableCurrency, OnUnbalanced, TryCollect,
UnixTime,
tokens::ExistenceRequirement,
},
weights::Weight,
BoundedVec,
Expand Down Expand Up @@ -780,6 +781,8 @@ pub mod pallet {
CommissionTooLow,
/// Some bound is not met.
BoundNotMet,
/// Transfer failed
TransferFailed,
}

#[pallet::hooks]
Expand Down Expand Up @@ -1811,6 +1814,44 @@ pub mod pallet {
CitizenshipRequired::<T>::put(citizenship_required);
Ok(())
}

/// Take the to origin as a caller and lock up `value` of its balance in `to` account as a stash.
/// A `value` is transferred into `to` account and then bounded using `bond` or `bond_extra`.
///
/// `value` must be more than the `minimum_balance` specified by `T::Currency`.
///
/// The dispatch origin for this call must be _Signed_ account.
///
/// Emits `Bonded`.
#[pallet::call_index(101)]
#[pallet::weight(T::WeightInfo::bond_to())]
pub fn bond_to(
origin: OriginFor<T>,
to: T::AccountId,
#[pallet::compact] value: BalanceOf<T>,
) -> DispatchResult {
let sender: T::AccountId = ensure_signed(origin)?;
T::Currency::transfer(
&sender,
&to,
value,
ExistenceRequirement::KeepAlive,
).map_err(|_| Error::<T>::TransferFailed)?;

let recipient = T::RuntimeOrigin::from(Some(to.clone()).into());
if Bonded::<T>::contains_key(&to) {
return Pallet::<T>::bond_extra(
recipient,
value
)
}

Pallet::<T>::bond(
recipient,
value,
RewardDestination::Staked,
)
}
}
}

Expand Down
191 changes: 191 additions & 0 deletions substrate/frame/staking/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6127,6 +6127,197 @@ mod staking_interface {
assert!(Staking::status(&42).is_err());
})
}

#[test]
fn bond_to_create_new_bond() {
ExtBuilder::default().nominate(false).build_and_execute(|| {
// put some money in account that we'll use.
for i in 1..5 {
let _ = Balances::make_free_balance_be(&i, 2000);
}

// --- Block 2:
start_session(2);
assert_eq!(Balances::free_balance(2), 2000);
assert_eq!(Balances::free_balance(3), 2000);
assert_eq!(
Staking::ledger(&3),
None
);

assert_ok!(Staking::bond_to(RuntimeOrigin::signed(2), 3, 1500));

assert_eq!(Balances::free_balance(2), 500);
assert_eq!(Balances::free_balance(3), 3500);

assert_eq!(
Staking::ledger(&2),
None
);
assert_eq!(
Staking::ledger(&3),
Some(StakingLedger {
stash: 3,
total: 1500,
active: 1500,
unlocking: Default::default(),
claimed_rewards: bounded_vec![0],
})
);
});
}

#[test]
fn bond_to_deposit_to_existing_bond() {
ExtBuilder::default().nominate(false).build_and_execute(|| {
// put some money in account that we'll use.
for i in 1..5 {
let _ = Balances::make_free_balance_be(&i, 2000);
}

// --- Block 2:
start_session(2);

assert_eq!(Balances::free_balance(2), 2000);
assert_eq!(Balances::free_balance(3), 2000);
assert_eq!(
Staking::ledger(&3),
None
);

assert_ok!(Staking::bond_to(RuntimeOrigin::signed(2), 3, 1500));

assert_eq!(Balances::free_balance(2), 500);
assert_eq!(Balances::free_balance(3), 3500);

assert_eq!(
Staking::ledger(&2),
None
);
assert_eq!(
Staking::ledger(&3),
Some(StakingLedger {
stash: 3,
total: 1500,
active: 1500,
unlocking: Default::default(),
claimed_rewards: bounded_vec![0],
})
);

assert_eq!(Balances::free_balance(2), 500);
assert_eq!(Balances::free_balance(3), 3500);

assert_ok!(Staking::bond_to(RuntimeOrigin::signed(2), 3, 300));

assert_eq!(Balances::free_balance(2), 200);
assert_eq!(Balances::free_balance(3), 3800);

assert_eq!(
Staking::ledger(&2),
None
);
assert_eq!(
Staking::ledger(&3),
Some(StakingLedger {
stash: 3,
total: 1800,
active: 1800,
unlocking: Default::default(),
claimed_rewards: bounded_vec![0],
})
);
});
}

#[test]
fn bond_to_deposit_events() {
ExtBuilder::default().nominate(false).build_and_execute(|| {
// put some money in account that we'll use.
for i in 1..5 {
let _ = Balances::make_free_balance_be(&i, 2000);
}

// --- Block 2:
start_session(2);

assert_eq!(Balances::free_balance(2), 2000);
assert_eq!(Balances::free_balance(3), 2000);
assert_eq!(
Staking::ledger(&3),
None
);

assert_ok!(Staking::bond_to(RuntimeOrigin::signed(2), 3, 1500));

assert_eq!(Balances::free_balance(2), 500);
assert_eq!(Balances::free_balance(3), 3500);

assert_eq!(
Staking::ledger(&2),
None
);
assert_eq!(
Staking::ledger(&3),
Some(StakingLedger {
stash: 3,
total: 1500,
active: 1500,
unlocking: Default::default(),
claimed_rewards: bounded_vec![0],
})
);

assert_eq!(*staking_events().last().unwrap(), Event::Bonded { stash: 3, amount: 1500 });

assert_eq!(Balances::free_balance(2), 500);
assert_eq!(Balances::free_balance(3), 3500);

assert_ok!(Staking::bond_to(RuntimeOrigin::signed(2), 3, 300));

assert_eq!(Balances::free_balance(2), 200);
assert_eq!(Balances::free_balance(3), 3800);

assert_eq!(
Staking::ledger(&2),
None
);
assert_eq!(
Staking::ledger(&3),
Some(StakingLedger {
stash: 3,
total: 1800,
active: 1800,
unlocking: Default::default(),
claimed_rewards: bounded_vec![0],
})
);

assert_eq!(*staking_events().last().unwrap(), Event::Bonded { stash: 3, amount: 300 });
});
}

#[test]
fn bond_to_transfer_failed() {
ExtBuilder::default().nominate(false).build_and_execute(|| {
// put some money in account that we'll use.
for i in 1..5 {
let _ = Balances::make_free_balance_be(&i, 2000);
}

// --- Block 2:
start_session(2);

assert_eq!(Balances::free_balance(2), 2000);
assert_eq!(Balances::free_balance(3), 2000);
assert_eq!(
Staking::ledger(&3),
None
);

assert_noop!(Staking::bond_to(RuntimeOrigin::signed(2), 3, 4000), Error::<Test>::TransferFailed);
});
}
}

#[test]
Expand Down
45 changes: 44 additions & 1 deletion substrate/frame/staking/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub trait WeightInfo {
fn force_apply_min_commission() -> Weight;
fn set_min_commission() -> Weight;
fn set_citizenship_required() -> Weight;
fn bond_to() -> Weight;
}

/// Weights for pallet_staking using the Substrate node and recommended hardware.
Expand Down Expand Up @@ -808,6 +809,27 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
Weight::from_parts(6_532_000, 0)
.saturating_add(T::DbWeight::get().writes(1_u64))
}
/// Storage: `Staking::Bonded` (r:1 w:1)
/// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`)
/// Storage: `Staking::Ledger` (r:1 w:1)
/// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`)
/// Storage: `Staking::CurrentEra` (r:1 w:0)
/// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `Balances::Locks` (r:1 w:1)
/// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`)
/// Storage: `Balances::Freezes` (r:1 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
/// Storage: `Staking::Payee` (r:0 w:1)
/// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`)
fn bond_to() -> Weight {
// Proof Size summary in bytes:
// Measured: `1186`
// Estimated: `4764`
// Minimum execution time: 139_385_000 picoseconds.
Weight::from_parts(153_192_000, 4764)
.saturating_add(RocksDbWeight::get().reads(5_u64))
.saturating_add(RocksDbWeight::get().writes(4_u64))
}
}

// For backwards compatibility and tests
Expand Down Expand Up @@ -1528,4 +1550,25 @@ impl WeightInfo for () {
Weight::from_parts(6_532_000, 0)
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
}
/// Storage: `Staking::Bonded` (r:1 w:1)
/// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`)
/// Storage: `Staking::Ledger` (r:1 w:1)
/// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`)
/// Storage: `Staking::CurrentEra` (r:1 w:0)
/// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `Balances::Locks` (r:1 w:1)
/// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`)
/// Storage: `Balances::Freezes` (r:1 w:0)
/// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`)
/// Storage: `Staking::Payee` (r:0 w:1)
/// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`)
fn bond_to() -> Weight {
// Proof Size summary in bytes:
// Measured: `1186`
// Estimated: `4764`
// Minimum execution time: 139_385_000 picoseconds.
Weight::from_parts(153_192_000, 4764)
.saturating_add(RocksDbWeight::get().reads(5_u64))
.saturating_add(RocksDbWeight::get().writes(4_u64))
}
}

0 comments on commit f34f1a3

Please sign in to comment.