council.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. use rstd::prelude::*;
  2. use runtime_primitives::traits::{As, Zero};
  3. use srml_support::{decl_event, decl_module, decl_storage, ensure, StorageValue};
  4. use system;
  5. pub use super::election::{self, CouncilElected, Seat, Seats};
  6. pub use crate::currency::{BalanceOf, GovernanceCurrency};
  7. // Hook For announcing that council term has ended
  8. pub trait CouncilTermEnded {
  9. fn council_term_ended();
  10. }
  11. impl CouncilTermEnded for () {
  12. fn council_term_ended() {}
  13. }
  14. impl<X: CouncilTermEnded> CouncilTermEnded for (X,) {
  15. fn council_term_ended() {
  16. X::council_term_ended();
  17. }
  18. }
  19. pub trait Trait: system::Trait + GovernanceCurrency {
  20. type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
  21. type CouncilTermEnded: CouncilTermEnded;
  22. }
  23. decl_storage! {
  24. trait Store for Module<T: Trait> as Council {
  25. ActiveCouncil get(active_council) config(): Seats<T::AccountId, BalanceOf<T>>;
  26. TermEndsAt get(term_ends_at) config() : T::BlockNumber = T::BlockNumber::sa(1);
  27. }
  28. }
  29. // Event for this module.
  30. decl_event!(
  31. pub enum Event<T> where <T as system::Trait>::BlockNumber {
  32. CouncilTermEnded(BlockNumber),
  33. NewCouncilTermStarted(BlockNumber),
  34. }
  35. );
  36. impl<T: Trait> CouncilElected<Seats<T::AccountId, BalanceOf<T>>, T::BlockNumber> for Module<T> {
  37. fn council_elected(seats: Seats<T::AccountId, BalanceOf<T>>, term: T::BlockNumber) {
  38. <ActiveCouncil<T>>::put(seats);
  39. let next_term_ends_at = <system::Module<T>>::block_number() + term;
  40. <TermEndsAt<T>>::put(next_term_ends_at);
  41. Self::deposit_event(RawEvent::NewCouncilTermStarted(next_term_ends_at));
  42. }
  43. }
  44. impl<T: Trait> Module<T> {
  45. pub fn is_term_ended() -> bool {
  46. <system::Module<T>>::block_number() >= Self::term_ends_at()
  47. }
  48. pub fn is_councilor(sender: &T::AccountId) -> bool {
  49. Self::active_council().iter().any(|c| c.member == *sender)
  50. }
  51. }
  52. decl_module! {
  53. pub struct Module<T: Trait> for enum Call where origin: T::Origin {
  54. fn deposit_event<T>() = default;
  55. fn on_finalize(now: T::BlockNumber) {
  56. if now == Self::term_ends_at() {
  57. Self::deposit_event(RawEvent::CouncilTermEnded(now));
  58. T::CouncilTermEnded::council_term_ended();
  59. }
  60. }
  61. // Sudo methods...
  62. /// Force set a zero staked council. Stakes in existing council will vanish into thin air!
  63. fn set_council(accounts: Vec<T::AccountId>) {
  64. let new_council: Seats<T::AccountId, BalanceOf<T>> = accounts.into_iter().map(|account| {
  65. Seat {
  66. member: account,
  67. stake: BalanceOf::<T>::zero(),
  68. backers: vec![]
  69. }
  70. }).collect();
  71. <ActiveCouncil<T>>::put(new_council);
  72. }
  73. /// Adds a zero staked council member
  74. fn add_council_member(account: T::AccountId) {
  75. ensure!(!Self::is_councilor(&account), "cannot add same account multiple times");
  76. let seat = Seat {
  77. member: account,
  78. stake: BalanceOf::<T>::zero(),
  79. backers: vec![]
  80. };
  81. // add member to existing council
  82. <ActiveCouncil<T>>::mutate(|council| council.push(seat));
  83. }
  84. fn remove_council_member(account_to_remove: T::AccountId) {
  85. ensure!(Self::is_councilor(&account_to_remove), "account is not a councilor");
  86. let filtered_council: Seats<T::AccountId, BalanceOf<T>> = Self::active_council()
  87. .into_iter()
  88. .filter(|c| c.member != account_to_remove)
  89. .collect();
  90. <ActiveCouncil<T>>::put(filtered_council);
  91. }
  92. /// Set blocknumber when council term will end
  93. fn set_term_ends_at(ends_at: T::BlockNumber) {
  94. ensure!(ends_at > <system::Module<T>>::block_number(), "must set future block number");
  95. <TermEndsAt<T>>::put(ends_at);
  96. }
  97. }
  98. }
  99. #[cfg(test)]
  100. mod tests {
  101. use crate::governance::mock::*;
  102. use runtime_io::with_externalities;
  103. use srml_support::*;
  104. #[test]
  105. fn add_council_member_test() {
  106. with_externalities(&mut initial_test_ext(), || {
  107. assert!(!Council::is_councilor(&1));
  108. assert_ok!(Council::add_council_member(1));
  109. assert!(Council::is_councilor(&1));
  110. assert_ok!(Council::add_council_member(2));
  111. assert!(Council::is_councilor(&1));
  112. assert!(Council::is_councilor(&2));
  113. });
  114. }
  115. #[test]
  116. fn remove_council_member_test() {
  117. with_externalities(&mut initial_test_ext(), || {
  118. assert_ok!(Council::add_council_member(1));
  119. assert_ok!(Council::add_council_member(2));
  120. assert_ok!(Council::add_council_member(3));
  121. assert_ok!(Council::remove_council_member(2));
  122. assert!(!Council::is_councilor(&2));
  123. assert!(Council::is_councilor(&1));
  124. assert!(Council::is_councilor(&3));
  125. });
  126. }
  127. #[test]
  128. fn set_council_test() {
  129. with_externalities(&mut initial_test_ext(), || {
  130. assert_ok!(Council::set_council(vec![4, 5, 6]));
  131. assert!(Council::is_councilor(&4));
  132. assert!(Council::is_councilor(&5));
  133. assert!(Council::is_councilor(&6));
  134. });
  135. }
  136. }