lib.rs 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174
  1. // Ensure we're `no_std` when compiling for Wasm.
  2. #![cfg_attr(not(feature = "std"), no_std)]
  3. use rstd::prelude::*;
  4. use codec::{Codec, Decode, Encode};
  5. use runtime_primitives::traits::{
  6. AccountIdConversion, MaybeSerialize, Member, One, SimpleArithmetic, Zero,
  7. };
  8. use runtime_primitives::ModuleId;
  9. use srml_support::traits::{Currency, ExistenceRequirement, Get, Imbalance, WithdrawReasons};
  10. use srml_support::{decl_module, decl_storage, ensure, Parameter};
  11. use rstd::collections::btree_map::BTreeMap;
  12. mod errors;
  13. pub use errors::*;
  14. mod macroes;
  15. mod mock;
  16. mod tests;
  17. pub type BalanceOf<T> =
  18. <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
  19. pub type NegativeImbalance<T> =
  20. <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::NegativeImbalance;
  21. pub trait Trait: system::Trait + Sized {
  22. /// The currency that is managed by the module
  23. type Currency: Currency<Self::AccountId>;
  24. /// ModuleId for computing deterministic AccountId for the module
  25. type StakePoolId: Get<[u8; 8]>;
  26. /// Type that will handle various staking events
  27. type StakingEventsHandler: StakingEventsHandler<Self>;
  28. /// The type used as a stake identifier.
  29. type StakeId: Parameter
  30. + Member
  31. + SimpleArithmetic
  32. + Codec
  33. + Default
  34. + Copy
  35. + MaybeSerialize
  36. + PartialEq;
  37. /// The type used as slash identifier.
  38. type SlashId: Parameter
  39. + Member
  40. + SimpleArithmetic
  41. + Codec
  42. + Default
  43. + Copy
  44. + MaybeSerialize
  45. + PartialEq
  46. + Ord; //required to be a key in BTreeMap
  47. }
  48. pub trait StakingEventsHandler<T: Trait> {
  49. /// Handler for unstaking event.
  50. /// The handler is informed of the amount that was unstaked, and the value removed from stake is passed as a negative imbalance.
  51. /// The handler is responsible to consume part or all of the value (for example by moving it into an account). The remainder
  52. /// of the value that is not consumed should be returned as a negative imbalance.
  53. fn unstaked(
  54. id: &T::StakeId,
  55. unstaked_amount: BalanceOf<T>,
  56. remaining_imbalance: NegativeImbalance<T>,
  57. ) -> NegativeImbalance<T>;
  58. /// Handler for slashing event.
  59. /// NB: actually_slashed can be less than amount of the slash itself if the
  60. /// claim amount on the stake cannot cover it fully.
  61. /// The SlashId is optional, as slashing may not be associated with a slashing that was initiated, but was an immediate slashing.
  62. /// For Immediate slashes, the stake may have transitioned to NotStaked so handler should not assume the state
  63. /// is still in staked status.
  64. fn slashed(
  65. id: &T::StakeId,
  66. slash_id: Option<T::SlashId>,
  67. slashed_amount: BalanceOf<T>,
  68. remaining_stake: BalanceOf<T>,
  69. remaining_imbalance: NegativeImbalance<T>,
  70. ) -> NegativeImbalance<T>;
  71. }
  72. /// Default implementation just destroys the unstaked or slashed value
  73. impl<T: Trait> StakingEventsHandler<T> for () {
  74. fn unstaked(
  75. _id: &T::StakeId,
  76. _unstaked_amount: BalanceOf<T>,
  77. _remaining_imbalance: NegativeImbalance<T>,
  78. ) -> NegativeImbalance<T> {
  79. NegativeImbalance::<T>::zero()
  80. }
  81. fn slashed(
  82. _id: &T::StakeId,
  83. _slash_id: Option<T::SlashId>,
  84. _slahed_amount: BalanceOf<T>,
  85. _remaining_stake: BalanceOf<T>,
  86. _remaining_imbalance: NegativeImbalance<T>,
  87. ) -> NegativeImbalance<T> {
  88. NegativeImbalance::<T>::zero()
  89. }
  90. }
  91. /// Helper implementation so we can chain multiple handlers by grouping handlers in tuple pairs.
  92. /// For example for three handlers, A, B and C we can set the StakingEventHandler type on the trait to:
  93. /// type StakingEventHandler = ((A, B), C)
  94. /// Individual handlers are expected consume in full or in part the negative imbalance and return any unconsumed value.
  95. /// The unconsumed value is then passed to the next handler in the chain.
  96. impl<T: Trait, X: StakingEventsHandler<T>, Y: StakingEventsHandler<T>> StakingEventsHandler<T>
  97. for (X, Y)
  98. {
  99. fn unstaked(
  100. id: &T::StakeId,
  101. unstaked_amount: BalanceOf<T>,
  102. imbalance: NegativeImbalance<T>,
  103. ) -> NegativeImbalance<T> {
  104. let unused_imbalance = X::unstaked(id, unstaked_amount, imbalance);
  105. Y::unstaked(id, unstaked_amount, unused_imbalance)
  106. }
  107. fn slashed(
  108. id: &T::StakeId,
  109. slash_id: Option<T::SlashId>,
  110. slashed_amount: BalanceOf<T>,
  111. remaining_stake: BalanceOf<T>,
  112. imbalance: NegativeImbalance<T>,
  113. ) -> NegativeImbalance<T> {
  114. let unused_imbalance = X::slashed(id, slash_id, slashed_amount, remaining_stake, imbalance);
  115. Y::slashed(
  116. id,
  117. slash_id,
  118. slashed_amount,
  119. remaining_stake,
  120. unused_imbalance,
  121. )
  122. }
  123. }
  124. #[derive(Encode, Decode, Copy, Clone, Debug, Default, Eq, PartialEq)]
  125. pub struct Slash<BlockNumber, Balance> {
  126. /// The block where slashing was initiated.
  127. pub started_at_block: BlockNumber,
  128. /// Whether slashing is in active, or conversley paused state.
  129. /// Blocks are only counted towards slashing execution delay when active.
  130. pub is_active: bool,
  131. /// The number blocks which must be finalised while in the active period before the slashing can be executed
  132. pub blocks_remaining_in_active_period_for_slashing: BlockNumber,
  133. /// Amount to slash
  134. pub slash_amount: Balance,
  135. }
  136. #[derive(Encode, Decode, Debug, Default, Eq, PartialEq)]
  137. pub struct UnstakingState<BlockNumber> {
  138. /// The block where the unstaking was initiated
  139. pub started_at_block: BlockNumber,
  140. /// Whether unstaking is in active, or conversely paused state.
  141. /// Blocks are only counted towards unstaking period when active.
  142. pub is_active: bool,
  143. /// The number blocks which must be finalised while in the active period before the unstaking is finished
  144. pub blocks_remaining_in_active_period_for_unstaking: BlockNumber,
  145. }
  146. #[derive(Encode, Decode, Debug, Eq, PartialEq)]
  147. pub enum StakedStatus<BlockNumber> {
  148. /// Baseline staking status, nothing is happening.
  149. Normal,
  150. /// Unstaking is under way.
  151. Unstaking(UnstakingState<BlockNumber>),
  152. }
  153. impl<BlockNumber> Default for StakedStatus<BlockNumber> {
  154. fn default() -> Self {
  155. StakedStatus::Normal
  156. }
  157. }
  158. #[derive(Encode, Decode, Debug, Default, Eq, PartialEq)]
  159. pub struct StakedState<BlockNumber, Balance, SlashId: Ord> {
  160. /// Total amount of funds at stake.
  161. pub staked_amount: Balance,
  162. /// Status of the staking.
  163. pub staked_status: StakedStatus<BlockNumber>,
  164. /// SlashId to use for next Slash that is initiated.
  165. /// Will be incremented by one after adding a new Slash.
  166. pub next_slash_id: SlashId,
  167. /// All ongoing slashing.
  168. pub ongoing_slashes: BTreeMap<SlashId, Slash<BlockNumber, Balance>>,
  169. }
  170. impl<BlockNumber, Balance, SlashId> StakedState<BlockNumber, Balance, SlashId>
  171. where
  172. BlockNumber: SimpleArithmetic + Copy,
  173. Balance: SimpleArithmetic + Copy,
  174. SlashId: Ord + Copy,
  175. {
  176. /// Iterates over all ongoing slashes and decrements blocks_remaining_in_active_period_for_slashing of active slashes (advancing the timer).
  177. /// Returns true if there was at least one slashe that was active and had its timer advanced.
  178. fn advance_slashing_timer(&mut self) -> bool {
  179. let mut did_advance_timers = false;
  180. for (_slash_id, slash) in self.ongoing_slashes.iter_mut() {
  181. if slash.is_active
  182. && slash.blocks_remaining_in_active_period_for_slashing > Zero::zero()
  183. {
  184. slash.blocks_remaining_in_active_period_for_slashing -= One::one();
  185. did_advance_timers = true;
  186. }
  187. }
  188. did_advance_timers
  189. }
  190. /// Returns pair of slash_id and slashes that should be executed
  191. fn get_slashes_to_finalize(&mut self) -> Vec<(SlashId, Slash<BlockNumber, Balance>)> {
  192. let slashes_to_finalize = self
  193. .ongoing_slashes
  194. .iter()
  195. .filter(|(_, slash)| {
  196. slash.blocks_remaining_in_active_period_for_slashing == Zero::zero()
  197. })
  198. .map(|(slash_id, _)| *slash_id)
  199. .collect::<Vec<_>>();
  200. // remove and return the slashes
  201. slashes_to_finalize
  202. .iter()
  203. .map(|slash_id| {
  204. // assert!(self.ongoing_slashes.contains_key(slash_id))
  205. (*slash_id, self.ongoing_slashes.remove(slash_id).unwrap())
  206. })
  207. .collect()
  208. }
  209. /// Executes a Slash. If remaining at stake drops below the minimum_balance, it will slash the entire staked amount.
  210. /// Returns the actual slashed amount.
  211. fn apply_slash(&mut self, slash_amount: Balance, minimum_balance: Balance) -> Balance {
  212. // calculate how much to slash
  213. let mut slash_amount = if slash_amount > self.staked_amount {
  214. self.staked_amount
  215. } else {
  216. slash_amount
  217. };
  218. // apply the slashing
  219. self.staked_amount -= slash_amount;
  220. // don't leave less than minimum_balance at stake
  221. if self.staked_amount < minimum_balance {
  222. slash_amount += self.staked_amount;
  223. self.staked_amount = Zero::zero();
  224. }
  225. slash_amount
  226. }
  227. /// For all slahes that should be executed, will apply the Slash to the staked amount, and drop it from the ongoing slashes map.
  228. /// Returns a vector of the executed slashes outcome: (SlashId, Slashed Amount, Remaining Staked Amount)
  229. fn finalize_slashes(&mut self, minimum_balance: Balance) -> Vec<(SlashId, Balance, Balance)> {
  230. let mut finalized_slashes: Vec<(SlashId, Balance, Balance)> = vec![];
  231. for (slash_id, slash) in self.get_slashes_to_finalize().iter() {
  232. // apply the slashing and get back actual amount slashed
  233. let slashed_amount = self.apply_slash(slash.slash_amount, minimum_balance);
  234. finalized_slashes.push((*slash_id, slashed_amount, self.staked_amount));
  235. }
  236. finalized_slashes
  237. }
  238. }
  239. #[derive(Encode, Decode, Debug, Eq, PartialEq)]
  240. pub enum StakingStatus<BlockNumber, Balance, SlashId: Ord> {
  241. NotStaked,
  242. Staked(StakedState<BlockNumber, Balance, SlashId>),
  243. }
  244. impl<BlockNumber, Balance, SlashId: Ord> Default for StakingStatus<BlockNumber, Balance, SlashId> {
  245. fn default() -> Self {
  246. StakingStatus::NotStaked
  247. }
  248. }
  249. #[derive(Encode, Decode, Default, Debug, Eq, PartialEq)]
  250. pub struct Stake<BlockNumber, Balance, SlashId: Ord> {
  251. /// When role was created
  252. pub created: BlockNumber,
  253. /// Status of any possible ongoing staking
  254. pub staking_status: StakingStatus<BlockNumber, Balance, SlashId>,
  255. }
  256. impl<BlockNumber, Balance, SlashId> Stake<BlockNumber, Balance, SlashId>
  257. where
  258. BlockNumber: Copy + SimpleArithmetic + Zero,
  259. Balance: Copy + SimpleArithmetic,
  260. SlashId: Copy + Ord + Zero + One,
  261. {
  262. fn new(created_at: BlockNumber) -> Self {
  263. Self {
  264. created: created_at,
  265. staking_status: StakingStatus::NotStaked,
  266. }
  267. }
  268. fn is_not_staked(&self) -> bool {
  269. self.staking_status == StakingStatus::NotStaked
  270. }
  271. /// If staking status is Staked and not currently Unstaking it will increase the staked amount by value.
  272. /// On success returns new total staked value.
  273. /// Increasing stake by zero is an error.
  274. fn increase_stake(&mut self, value: Balance) -> Result<Balance, IncreasingStakeError> {
  275. ensure!(
  276. value > Zero::zero(),
  277. IncreasingStakeError::CannotChangeStakeByZero
  278. );
  279. match self.staking_status {
  280. StakingStatus::Staked(ref mut staked_state) => match staked_state.staked_status {
  281. StakedStatus::Normal => {
  282. staked_state.staked_amount += value;
  283. Ok(staked_state.staked_amount)
  284. }
  285. _ => Err(IncreasingStakeError::CannotIncreaseStakeWhileUnstaking),
  286. },
  287. _ => Err(IncreasingStakeError::NotStaked),
  288. }
  289. }
  290. /// If staking status is Staked and not currently Unstaking, and no ongoing slashes exist, it will decrease the amount at stake
  291. /// by provided value. If remaining at stake drops below the minimum_balance it will decrease the stake to zero.
  292. /// On success returns (the actual amount of stake decreased, the remaining amount at stake).
  293. /// Decreasing stake by zero is an error.
  294. fn decrease_stake(
  295. &mut self,
  296. value: Balance,
  297. minimum_balance: Balance,
  298. ) -> Result<(Balance, Balance), DecreasingStakeError> {
  299. // maybe StakeDecrease
  300. ensure!(
  301. value > Zero::zero(),
  302. DecreasingStakeError::CannotChangeStakeByZero
  303. );
  304. match self.staking_status {
  305. StakingStatus::Staked(ref mut staked_state) => match staked_state.staked_status {
  306. StakedStatus::Normal => {
  307. // prevent decreasing stake if there are any ongoing slashes (irrespective if active or not)
  308. if !staked_state.ongoing_slashes.is_empty() {
  309. return Err(DecreasingStakeError::CannotDecreaseStakeWhileOngoingSlahes);
  310. }
  311. if value > staked_state.staked_amount {
  312. return Err(DecreasingStakeError::InsufficientStake);
  313. }
  314. let stake_to_reduce = if staked_state.staked_amount - value < minimum_balance {
  315. // If staked amount would drop below minimum balance, deduct the entire stake
  316. staked_state.staked_amount
  317. } else {
  318. value
  319. };
  320. staked_state.staked_amount -= stake_to_reduce;
  321. Ok((stake_to_reduce, staked_state.staked_amount))
  322. }
  323. _ => Err(DecreasingStakeError::CannotDecreaseStakeWhileUnstaking),
  324. },
  325. _ => Err(DecreasingStakeError::NotStaked),
  326. }
  327. }
  328. fn start_staking(
  329. &mut self,
  330. value: Balance,
  331. minimum_balance: Balance,
  332. ) -> Result<(), StakingError> {
  333. ensure!(value > Zero::zero(), StakingError::CannotStakeZero);
  334. ensure!(
  335. value >= minimum_balance,
  336. StakingError::CannotStakeLessThanMinimumBalance
  337. );
  338. if self.is_not_staked() {
  339. self.staking_status = StakingStatus::Staked(StakedState {
  340. staked_amount: value,
  341. next_slash_id: Zero::zero(),
  342. ongoing_slashes: BTreeMap::new(),
  343. staked_status: StakedStatus::Normal,
  344. });
  345. Ok(())
  346. } else {
  347. Err(StakingError::AlreadyStaked)
  348. }
  349. }
  350. fn slash_immediate(
  351. &mut self,
  352. slash_amount: Balance,
  353. minimum_balance: Balance,
  354. ) -> Result<(Balance, Balance), ImmediateSlashingError> {
  355. ensure!(
  356. slash_amount > Zero::zero(),
  357. ImmediateSlashingError::SlashAmountShouldBeGreaterThanZero
  358. );
  359. match self.staking_status {
  360. StakingStatus::Staked(ref mut staked_state) => {
  361. // irrespective of wether we are unstaking or not, slash!
  362. let actually_slashed = staked_state.apply_slash(slash_amount, minimum_balance);
  363. let remaining_stake = staked_state.staked_amount;
  364. Ok((actually_slashed, remaining_stake))
  365. }
  366. // can't slash if not staked
  367. _ => Err(ImmediateSlashingError::NotStaked),
  368. }
  369. }
  370. fn initiate_slashing(
  371. &mut self,
  372. slash_amount: Balance,
  373. slash_period: BlockNumber,
  374. now: BlockNumber,
  375. ) -> Result<SlashId, InitiateSlashingError> {
  376. ensure!(
  377. slash_period > Zero::zero(),
  378. InitiateSlashingError::SlashPeriodShouldBeGreaterThanZero
  379. );
  380. ensure!(
  381. slash_amount > Zero::zero(),
  382. InitiateSlashingError::SlashAmountShouldBeGreaterThanZero
  383. );
  384. match self.staking_status {
  385. StakingStatus::Staked(ref mut staked_state) => {
  386. let slash_id = staked_state.next_slash_id;
  387. staked_state.next_slash_id = slash_id + One::one();
  388. staked_state.ongoing_slashes.insert(
  389. slash_id,
  390. Slash {
  391. is_active: true,
  392. blocks_remaining_in_active_period_for_slashing: slash_period,
  393. slash_amount,
  394. started_at_block: now,
  395. },
  396. );
  397. // pause Unstaking if unstaking is active
  398. if let StakedStatus::Unstaking(ref mut unstaking_state) = staked_state.staked_status
  399. {
  400. unstaking_state.is_active = false;
  401. }
  402. Ok(slash_id)
  403. }
  404. _ => Err(InitiateSlashingError::NotStaked),
  405. }
  406. }
  407. fn pause_slashing(&mut self, slash_id: &SlashId) -> Result<(), PauseSlashingError> {
  408. match self.staking_status {
  409. StakingStatus::Staked(ref mut staked_state) => {
  410. match staked_state.ongoing_slashes.get_mut(slash_id) {
  411. Some(ref mut slash) => {
  412. if slash.is_active {
  413. slash.is_active = false;
  414. Ok(())
  415. } else {
  416. Err(PauseSlashingError::AlreadyPaused)
  417. }
  418. }
  419. _ => Err(PauseSlashingError::SlashNotFound),
  420. }
  421. }
  422. _ => Err(PauseSlashingError::NotStaked),
  423. }
  424. }
  425. fn resume_slashing(&mut self, slash_id: &SlashId) -> Result<(), ResumeSlashingError> {
  426. match self.staking_status {
  427. StakingStatus::Staked(ref mut staked_state) => {
  428. match staked_state.ongoing_slashes.get_mut(slash_id) {
  429. Some(ref mut slash) => {
  430. if slash.is_active {
  431. Err(ResumeSlashingError::NotPaused)
  432. } else {
  433. slash.is_active = true;
  434. Ok(())
  435. }
  436. }
  437. _ => Err(ResumeSlashingError::SlashNotFound),
  438. }
  439. }
  440. _ => Err(ResumeSlashingError::NotStaked),
  441. }
  442. }
  443. fn cancel_slashing(&mut self, slash_id: &SlashId) -> Result<(), CancelSlashingError> {
  444. match self.staking_status {
  445. StakingStatus::Staked(ref mut staked_state) => {
  446. if staked_state.ongoing_slashes.remove(slash_id).is_none() {
  447. return Err(CancelSlashingError::SlashNotFound);
  448. }
  449. // unpause unstaking on last ongoing slash cancelled
  450. if staked_state.ongoing_slashes.is_empty() {
  451. if let StakedStatus::Unstaking(ref mut unstaking_state) =
  452. staked_state.staked_status
  453. {
  454. unstaking_state.is_active = true;
  455. }
  456. }
  457. Ok(())
  458. }
  459. _ => Err(CancelSlashingError::NotStaked),
  460. }
  461. }
  462. fn unstake(&mut self) -> Result<Balance, UnstakingError> {
  463. let staked_amount = match self.staking_status {
  464. StakingStatus::Staked(ref staked_state) => {
  465. // prevent unstaking if there are any ongonig slashes (irrespective if active or not)
  466. if !staked_state.ongoing_slashes.is_empty() {
  467. return Err(UnstakingError::CannotUnstakeWhileSlashesOngoing);
  468. }
  469. if StakedStatus::Normal != staked_state.staked_status {
  470. return Err(UnstakingError::AlreadyUnstaking);
  471. }
  472. Ok(staked_state.staked_amount)
  473. }
  474. _ => Err(UnstakingError::NotStaked),
  475. }?;
  476. self.staking_status = StakingStatus::NotStaked;
  477. Ok(staked_amount)
  478. }
  479. fn initiate_unstaking(
  480. &mut self,
  481. unstaking_period: BlockNumber,
  482. now: BlockNumber,
  483. ) -> Result<(), InitiateUnstakingError> {
  484. ensure!(
  485. unstaking_period > Zero::zero(),
  486. InitiateUnstakingError::UnstakingPeriodShouldBeGreaterThanZero
  487. );
  488. match self.staking_status {
  489. StakingStatus::Staked(ref mut staked_state) => {
  490. // prevent unstaking if there are any ongonig slashes (irrespective if active or not)
  491. if !staked_state.ongoing_slashes.is_empty() {
  492. return Err(InitiateUnstakingError::UnstakingError(
  493. UnstakingError::CannotUnstakeWhileSlashesOngoing,
  494. ));
  495. }
  496. if StakedStatus::Normal != staked_state.staked_status {
  497. return Err(InitiateUnstakingError::UnstakingError(
  498. UnstakingError::AlreadyUnstaking,
  499. ));
  500. }
  501. staked_state.staked_status = StakedStatus::Unstaking(UnstakingState {
  502. started_at_block: now,
  503. is_active: true,
  504. blocks_remaining_in_active_period_for_unstaking: unstaking_period,
  505. });
  506. Ok(())
  507. }
  508. _ => Err(InitiateUnstakingError::UnstakingError(
  509. UnstakingError::NotStaked,
  510. )),
  511. }
  512. }
  513. fn pause_unstaking(&mut self) -> Result<(), PauseUnstakingError> {
  514. match self.staking_status {
  515. StakingStatus::Staked(ref mut staked_state) => match staked_state.staked_status {
  516. StakedStatus::Unstaking(ref mut unstaking_state) => {
  517. if unstaking_state.is_active {
  518. unstaking_state.is_active = false;
  519. Ok(())
  520. } else {
  521. Err(PauseUnstakingError::AlreadyPaused)
  522. }
  523. }
  524. _ => Err(PauseUnstakingError::NotUnstaking),
  525. },
  526. _ => Err(PauseUnstakingError::NotStaked),
  527. }
  528. }
  529. fn resume_unstaking(&mut self) -> Result<(), ResumeUnstakingError> {
  530. match self.staking_status {
  531. StakingStatus::Staked(ref mut staked_state) => match staked_state.staked_status {
  532. StakedStatus::Unstaking(ref mut unstaking_state) => {
  533. if !unstaking_state.is_active {
  534. unstaking_state.is_active = true;
  535. Ok(())
  536. } else {
  537. Err(ResumeUnstakingError::NotPaused)
  538. }
  539. }
  540. _ => Err(ResumeUnstakingError::NotUnstaking),
  541. },
  542. _ => Err(ResumeUnstakingError::NotStaked),
  543. }
  544. }
  545. fn finalize_slashing(
  546. &mut self,
  547. minimum_balance: Balance,
  548. ) -> (bool, Vec<(SlashId, Balance, Balance)>) {
  549. match self.staking_status {
  550. StakingStatus::Staked(ref mut staked_state) => {
  551. // tick the slashing timer
  552. let did_update = staked_state.advance_slashing_timer();
  553. // finalize and apply slashes
  554. let slashed = staked_state.finalize_slashes(minimum_balance);
  555. (did_update, slashed)
  556. }
  557. _ => (false, vec![]),
  558. }
  559. }
  560. fn finalize_unstaking(&mut self) -> (bool, Option<Balance>) {
  561. let (did_update, unstaked) = match self.staking_status {
  562. StakingStatus::Staked(ref mut staked_state) => match staked_state.staked_status {
  563. StakedStatus::Unstaking(ref mut unstaking_state) => {
  564. // if all slashes were processed and there are no more active slashes
  565. // resume unstaking
  566. if staked_state.ongoing_slashes.is_empty() {
  567. unstaking_state.is_active = true;
  568. }
  569. // tick the unstaking timer
  570. if unstaking_state.is_active
  571. && unstaking_state.blocks_remaining_in_active_period_for_unstaking
  572. > Zero::zero()
  573. {
  574. // tick the unstaking timer
  575. unstaking_state.blocks_remaining_in_active_period_for_unstaking -=
  576. One::one();
  577. }
  578. // finalize unstaking
  579. if unstaking_state.blocks_remaining_in_active_period_for_unstaking
  580. == Zero::zero()
  581. {
  582. (true, Some(staked_state.staked_amount))
  583. } else {
  584. (unstaking_state.is_active, None)
  585. }
  586. }
  587. _ => (false, None),
  588. },
  589. _ => (false, None),
  590. };
  591. // if unstaking was finalized transition to NotStaked state
  592. if unstaked.is_some() {
  593. self.staking_status = StakingStatus::NotStaked;
  594. }
  595. (did_update, unstaked)
  596. }
  597. fn finalize_slashing_and_unstaking(
  598. &mut self,
  599. minimum_balance: Balance,
  600. ) -> (bool, Vec<(SlashId, Balance, Balance)>, Option<Balance>) {
  601. let (did_update_slashing_timers, slashed) = self.finalize_slashing(minimum_balance);
  602. let (did_update_unstaking_timer, unstaked) = self.finalize_unstaking();
  603. (
  604. did_update_slashing_timers || did_update_unstaking_timer,
  605. slashed,
  606. unstaked,
  607. )
  608. }
  609. }
  610. #[derive(Debug, Eq, PartialEq)]
  611. pub struct SlashImmediateOutcome<Balance, NegativeImbalance> {
  612. pub caused_unstake: bool,
  613. pub actually_slashed: Balance,
  614. pub remaining_stake: Balance,
  615. pub remaining_imbalance: NegativeImbalance,
  616. }
  617. decl_storage! {
  618. trait Store for Module<T: Trait> as StakePool {
  619. /// Maps identifiers to a stake.
  620. pub Stakes get(stakes): linked_map T::StakeId => Stake<T::BlockNumber, BalanceOf<T>, T::SlashId>;
  621. /// Identifier value for next stake, and count of total stakes created (not necessarily the number of current
  622. /// stakes in the Stakes map as stakes can be removed.)
  623. pub StakesCreated get(stakes_created): T::StakeId;
  624. }
  625. }
  626. decl_module! {
  627. pub struct Module<T: Trait> for enum Call where origin: T::Origin {
  628. fn on_finalize(_now: T::BlockNumber) {
  629. Self::finalize_slashing_and_unstaking();
  630. }
  631. }
  632. }
  633. impl<T: Trait> Module<T> {
  634. /// The account ID of theis module which holds all the staked balance. (referred to as the stake pool)
  635. ///
  636. /// This actually does computation. If you need to keep using it, then make sure you cache the
  637. /// value and only call this once. Is it deterministic?
  638. pub fn stake_pool_account_id() -> T::AccountId {
  639. ModuleId(T::StakePoolId::get()).into_account()
  640. }
  641. pub fn stake_pool_balance() -> BalanceOf<T> {
  642. T::Currency::free_balance(&Self::stake_pool_account_id())
  643. }
  644. /// Adds a new Stake which is NotStaked, created at given block, into stakes map.
  645. pub fn create_stake() -> T::StakeId {
  646. let stake_id = Self::stakes_created();
  647. <StakesCreated<T>>::put(stake_id + One::one());
  648. <Stakes<T>>::insert(&stake_id, Stake::new(<system::Module<T>>::block_number()));
  649. stake_id
  650. }
  651. /// Given that stake with id exists in stakes and is NotStaked, remove from stakes.
  652. pub fn remove_stake(stake_id: &T::StakeId) -> Result<(), StakeActionError<StakingError>> {
  653. let stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  654. ensure!(
  655. stake.is_not_staked(),
  656. StakeActionError::Error(StakingError::AlreadyStaked)
  657. );
  658. <Stakes<T>>::remove(stake_id);
  659. Ok(())
  660. }
  661. /// Dry run to see if staking can be initiated for the specified stake id. This should
  662. /// be called before stake() to make sure staking is possible before withdrawing funds.
  663. pub fn ensure_can_stake(
  664. stake_id: &T::StakeId,
  665. value: BalanceOf<T>,
  666. ) -> Result<(), StakeActionError<StakingError>> {
  667. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  668. stake
  669. .start_staking(value, T::Currency::minimum_balance())
  670. .err()
  671. .map_or(Ok(()), |err| Err(StakeActionError::Error(err)))
  672. }
  673. /// Provided the stake exists and is in state NotStaked the value is transferred
  674. /// to the module's account, and the corresponding staked_balance is set to this amount in the new Staked state.
  675. /// On error, as the negative imbalance is not returned to the caller, it is the caller's responsibility to return the funds
  676. /// back to the source (by creating a new positive imbalance)
  677. pub fn stake(
  678. stake_id: &T::StakeId,
  679. imbalance: NegativeImbalance<T>,
  680. ) -> Result<(), StakeActionError<StakingError>> {
  681. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  682. let value = imbalance.peek();
  683. stake.start_staking(value, T::Currency::minimum_balance())?;
  684. <Stakes<T>>::insert(stake_id, stake);
  685. Self::deposit_funds_into_stake_pool(imbalance);
  686. Ok(())
  687. }
  688. pub fn stake_from_account(
  689. stake_id: &T::StakeId,
  690. source_account_id: &T::AccountId,
  691. value: BalanceOf<T>,
  692. ) -> Result<(), StakeActionError<StakingFromAccountError>> {
  693. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  694. stake.start_staking(value, T::Currency::minimum_balance())?;
  695. // Its important to only do the transfer as the last step to ensure starting staking was possible.
  696. Self::transfer_funds_from_account_into_stake_pool(source_account_id, value)?;
  697. <Stakes<T>>::insert(stake_id, stake);
  698. Ok(())
  699. }
  700. /// Moves funds from specified account into the module's account
  701. fn transfer_funds_from_account_into_stake_pool(
  702. source: &T::AccountId,
  703. value: BalanceOf<T>,
  704. ) -> Result<(), TransferFromAccountError> {
  705. // We don't use T::Currency::transfer() to prevent fees being incurred.
  706. let negative_imbalance = T::Currency::withdraw(
  707. source,
  708. value,
  709. WithdrawReasons::all(),
  710. ExistenceRequirement::AllowDeath,
  711. )
  712. .map_err(|_err| TransferFromAccountError::InsufficientBalance)?;
  713. Self::deposit_funds_into_stake_pool(negative_imbalance);
  714. Ok(())
  715. }
  716. fn deposit_funds_into_stake_pool(imbalance: NegativeImbalance<T>) {
  717. // move the negative imbalance into the stake pool
  718. T::Currency::resolve_creating(&Self::stake_pool_account_id(), imbalance);
  719. }
  720. /// Moves funds from the module's account into specified account. Should never fail if used internally.
  721. /// Will panic! if value exceeds balance in the pool.
  722. fn transfer_funds_from_pool_into_account(destination: &T::AccountId, value: BalanceOf<T>) {
  723. let imbalance = Self::withdraw_funds_from_stake_pool(value);
  724. T::Currency::resolve_creating(destination, imbalance);
  725. }
  726. /// Withdraws value from the pool and returns a NegativeImbalance.
  727. /// As long as it is only called internally when executing slashes and unstaking, it
  728. /// should never fail as the pool balance is always in sync with total amount at stake.
  729. fn withdraw_funds_from_stake_pool(value: BalanceOf<T>) -> NegativeImbalance<T> {
  730. // We don't use T::Currency::transfer() to prevent fees being incurred.
  731. T::Currency::withdraw(
  732. &Self::stake_pool_account_id(),
  733. value,
  734. WithdrawReasons::all(),
  735. ExistenceRequirement::AllowDeath,
  736. )
  737. .expect("pool had less than expected funds!")
  738. }
  739. /// Dry run to see if the state of stake allows for increasing stake. This should be called
  740. /// to make sure increasing stake is possible before withdrawing funds.
  741. pub fn ensure_can_increase_stake(
  742. stake_id: &T::StakeId,
  743. value: BalanceOf<T>,
  744. ) -> Result<(), StakeActionError<IncreasingStakeError>> {
  745. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  746. stake
  747. .increase_stake(value)
  748. .err()
  749. .map_or(Ok(()), |err| Err(StakeActionError::Error(err)))
  750. }
  751. /// Provided the stake exists and is in state Staked.Normal, then the amount is transferred to the module's account,
  752. /// and the corresponding staked_amount is increased by the value. New value of staked_amount is returned.
  753. /// Caller should call check ensure_can_increase_stake() prior to avoid getting back an error. On error, as the negative imbalance
  754. /// is not returned to the caller, it is the caller's responsibility to return the funds back to the source (by creating a new positive imbalance)
  755. pub fn increase_stake(
  756. stake_id: &T::StakeId,
  757. imbalance: NegativeImbalance<T>,
  758. ) -> Result<BalanceOf<T>, StakeActionError<IncreasingStakeError>> {
  759. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  760. let total_staked_amount = stake.increase_stake(imbalance.peek())?;
  761. <Stakes<T>>::insert(stake_id, stake);
  762. Self::deposit_funds_into_stake_pool(imbalance);
  763. Ok(total_staked_amount)
  764. }
  765. /// Provided the stake exists and is in state Staked.Normal, and the given source account covers the amount,
  766. /// then the amount is transferred to the module's account, and the corresponding staked_amount is increased
  767. /// by the amount. New value of staked_amount is returned.
  768. pub fn increase_stake_from_account(
  769. stake_id: &T::StakeId,
  770. source_account_id: &T::AccountId,
  771. value: BalanceOf<T>,
  772. ) -> Result<BalanceOf<T>, StakeActionError<IncreasingStakeFromAccountError>> {
  773. // Compiler error when using macro: cannot infer type for `ErrorType`
  774. // let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  775. ensure!(
  776. <Stakes<T>>::exists(stake_id),
  777. StakeActionError::StakeNotFound
  778. );
  779. let mut stake = Self::stakes(stake_id);
  780. let total_staked_amount = stake.increase_stake(value)?;
  781. Self::transfer_funds_from_account_into_stake_pool(&source_account_id, value)?;
  782. <Stakes<T>>::insert(stake_id, stake);
  783. Ok(total_staked_amount)
  784. }
  785. pub fn ensure_can_decrease_stake(
  786. stake_id: &T::StakeId,
  787. value: BalanceOf<T>,
  788. ) -> Result<(), StakeActionError<DecreasingStakeError>> {
  789. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  790. stake
  791. .decrease_stake(value, T::Currency::minimum_balance())
  792. .err()
  793. .map_or(Ok(()), |err| Err(StakeActionError::Error(err)))
  794. }
  795. pub fn decrease_stake(
  796. stake_id: &T::StakeId,
  797. value: BalanceOf<T>,
  798. ) -> Result<(BalanceOf<T>, NegativeImbalance<T>), StakeActionError<DecreasingStakeError>> {
  799. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  800. let (deduct_from_pool, staked_amount) =
  801. stake.decrease_stake(value, T::Currency::minimum_balance())?;
  802. <Stakes<T>>::insert(stake_id, stake);
  803. let imbalance = Self::withdraw_funds_from_stake_pool(deduct_from_pool);
  804. Ok((staked_amount, imbalance))
  805. }
  806. /// Provided the stake exists and is in state Staked.Normal, and the given stake holds at least the value,
  807. /// then the value is transferred from the module's account to the destination_account, and the corresponding
  808. /// staked_amount is decreased by the value. New value of staked_amount is returned.
  809. pub fn decrease_stake_to_account(
  810. stake_id: &T::StakeId,
  811. destination_account_id: &T::AccountId,
  812. value: BalanceOf<T>,
  813. ) -> Result<BalanceOf<T>, StakeActionError<DecreasingStakeError>> {
  814. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  815. let (deduct_from_pool, staked_amount) =
  816. stake.decrease_stake(value, T::Currency::minimum_balance())?;
  817. <Stakes<T>>::insert(stake_id, stake);
  818. Self::transfer_funds_from_pool_into_account(&destination_account_id, deduct_from_pool);
  819. Ok(staked_amount)
  820. }
  821. /// Slashes a stake with immediate effect, returns the outcome of the slashing.
  822. /// Can optionally specify if slashing can result in immediate unstaking if staked amount
  823. /// after slashing goes to zero.
  824. pub fn slash_immediate(
  825. stake_id: &T::StakeId,
  826. slash_amount: BalanceOf<T>,
  827. unstake_on_zero_staked: bool,
  828. ) -> Result<
  829. SlashImmediateOutcome<BalanceOf<T>, NegativeImbalance<T>>,
  830. StakeActionError<ImmediateSlashingError>,
  831. > {
  832. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  833. // Get amount at stake before slashing to be used in unstaked event trigger
  834. let staked_amount_before_slash = ensure_staked_amount!(
  835. stake,
  836. StakeActionError::Error(ImmediateSlashingError::NotStaked)
  837. )?;
  838. let (actually_slashed, remaining_stake) =
  839. stake.slash_immediate(slash_amount, T::Currency::minimum_balance())?;
  840. let caused_unstake = unstake_on_zero_staked && remaining_stake == BalanceOf::<T>::zero();
  841. if caused_unstake {
  842. stake.staking_status = StakingStatus::NotStaked;
  843. }
  844. // Update state before calling handlers!
  845. <Stakes<T>>::insert(stake_id, stake);
  846. // Remove the slashed amount from the pool
  847. let slashed_imbalance = Self::withdraw_funds_from_stake_pool(actually_slashed);
  848. // Notify slashing event handler before unstaked handler.
  849. let remaining_imbalance_after_slash_handler = T::StakingEventsHandler::slashed(
  850. stake_id,
  851. None,
  852. actually_slashed,
  853. remaining_stake,
  854. slashed_imbalance,
  855. );
  856. let remaining_imbalance = if caused_unstake {
  857. // Notify unstaked handler with any remaining unused imbalance
  858. // from the slashing event handler
  859. T::StakingEventsHandler::unstaked(
  860. &stake_id,
  861. staked_amount_before_slash,
  862. remaining_imbalance_after_slash_handler,
  863. )
  864. } else {
  865. remaining_imbalance_after_slash_handler
  866. };
  867. Ok(SlashImmediateOutcome {
  868. caused_unstake,
  869. actually_slashed,
  870. remaining_stake,
  871. remaining_imbalance,
  872. })
  873. }
  874. /// Initiate a new slashing of a staked stake. Slashing begins at next block.
  875. pub fn initiate_slashing(
  876. stake_id: &T::StakeId,
  877. slash_amount: BalanceOf<T>,
  878. slash_period: T::BlockNumber,
  879. ) -> Result<T::SlashId, StakeActionError<InitiateSlashingError>> {
  880. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  881. let slash_id = stake.initiate_slashing(
  882. slash_amount,
  883. slash_period,
  884. <system::Module<T>>::block_number(),
  885. )?;
  886. <Stakes<T>>::insert(stake_id, stake);
  887. Ok(slash_id)
  888. }
  889. /// Pause an ongoing slashing
  890. pub fn pause_slashing(
  891. stake_id: &T::StakeId,
  892. slash_id: &T::SlashId,
  893. ) -> Result<(), StakeActionError<PauseSlashingError>> {
  894. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  895. stake.pause_slashing(slash_id)?;
  896. <Stakes<T>>::insert(stake_id, stake);
  897. Ok(())
  898. }
  899. /// Resume a currently paused ongoing slashing.
  900. pub fn resume_slashing(
  901. stake_id: &T::StakeId,
  902. slash_id: &T::SlashId,
  903. ) -> Result<(), StakeActionError<ResumeSlashingError>> {
  904. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  905. stake.resume_slashing(slash_id)?;
  906. <Stakes<T>>::insert(stake_id, stake);
  907. Ok(())
  908. }
  909. /// Cancel an ongoing slashing (regardless of whether its active or paused).
  910. pub fn cancel_slashing(
  911. stake_id: &T::StakeId,
  912. slash_id: &T::SlashId,
  913. ) -> Result<(), StakeActionError<CancelSlashingError>> {
  914. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  915. stake.cancel_slashing(slash_id)?;
  916. <Stakes<T>>::insert(stake_id, stake);
  917. Ok(())
  918. }
  919. /// Initiate unstaking of a Staked stake.
  920. pub fn initiate_unstaking(
  921. stake_id: &T::StakeId,
  922. unstaking_period: Option<T::BlockNumber>,
  923. ) -> Result<(), StakeActionError<InitiateUnstakingError>> {
  924. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  925. if let Some(unstaking_period) = unstaking_period {
  926. stake.initiate_unstaking(unstaking_period, <system::Module<T>>::block_number())?;
  927. <Stakes<T>>::insert(stake_id, stake);
  928. } else {
  929. let staked_amount = stake.unstake()?;
  930. <Stakes<T>>::insert(stake_id, stake);
  931. let imbalance = Self::withdraw_funds_from_stake_pool(staked_amount);
  932. let _ = T::StakingEventsHandler::unstaked(stake_id, staked_amount, imbalance);
  933. }
  934. Ok(())
  935. }
  936. /// Pause an ongoing Unstaking.
  937. pub fn pause_unstaking(
  938. stake_id: &T::StakeId,
  939. ) -> Result<(), StakeActionError<PauseUnstakingError>> {
  940. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  941. stake.pause_unstaking()?;
  942. <Stakes<T>>::insert(stake_id, stake);
  943. Ok(())
  944. }
  945. /// Resume a currently paused ongoing unstaking.
  946. pub fn resume_unstaking(
  947. stake_id: &T::StakeId,
  948. ) -> Result<(), StakeActionError<ResumeUnstakingError>> {
  949. let mut stake = ensure_stake_exists!(T, stake_id, StakeActionError::StakeNotFound)?;
  950. stake.resume_unstaking()?;
  951. <Stakes<T>>::insert(stake_id, stake);
  952. Ok(())
  953. }
  954. /// Handle timers for finalizing unstaking and slashing.
  955. /// Finalised unstaking results in the staked_balance in the given stake to removed from the pool, the corresponding
  956. /// imbalance is provided to the unstaked() hook in the StakingEventsHandler.
  957. /// Finalised slashing results in the staked_balance in the given stake being correspondingly reduced, and the imbalance
  958. /// is provided to the slashed() hook in the StakingEventsHandler.
  959. fn finalize_slashing_and_unstaking() {
  960. for (stake_id, ref mut stake) in <Stakes<T>>::enumerate() {
  961. let (updated, slashed, unstaked) =
  962. stake.finalize_slashing_and_unstaking(T::Currency::minimum_balance());
  963. // update the state before making external calls to StakingEventsHandler
  964. if updated {
  965. <Stakes<T>>::insert(stake_id, stake)
  966. }
  967. for (slash_id, slashed_amount, staked_amount) in slashed.into_iter() {
  968. // remove the slashed amount from the pool
  969. let imbalance = Self::withdraw_funds_from_stake_pool(slashed_amount);
  970. let _ = T::StakingEventsHandler::slashed(
  971. &stake_id,
  972. Some(slash_id),
  973. slashed_amount,
  974. staked_amount,
  975. imbalance,
  976. );
  977. }
  978. if let Some(staked_amount) = unstaked {
  979. // remove the unstaked amount from the pool
  980. let imbalance = Self::withdraw_funds_from_stake_pool(staked_amount);
  981. let _ = T::StakingEventsHandler::unstaked(&stake_id, staked_amount, imbalance);
  982. }
  983. }
  984. }
  985. }