1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#![cfg_attr(not(feature = "std"), no_std)]
use frame_support::{
decl_error, decl_event, decl_module, decl_storage,
ensure,
dispatch::DispatchResult,
traits::Get
};
use sp_std::prelude::*;
use frame_system::{self as system, ensure_signed};
use df_traits::moderation::IsAccountBlocked;
use pallet_spaces::{Module as Spaces, SpaceById, SpaceIdsByOwner};
use pallet_utils::{Error as UtilsError, SpaceId, remove_from_vec};
pub trait Trait: system::Trait
+ pallet_utils::Trait
+ pallet_spaces::Trait
{
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
decl_error! {
pub enum Error for Module<T: Trait> {
CannotTranferToCurrentOwner,
AlreadyASpaceOwner,
NoPendingTransferOnSpace,
NotAllowedToAcceptOwnershipTransfer,
NotAllowedToRejectOwnershipTransfer,
}
}
decl_storage! {
trait Store for Module<T: Trait> as SpaceOwnershipModule {
pub PendingSpaceOwner get(fn pending_space_owner):
map hasher(twox_64_concat) SpaceId => Option<T::AccountId>;
}
}
decl_event!(
pub enum Event<T> where
<T as system::Trait>::AccountId,
{
SpaceOwnershipTransferCreated( AccountId, SpaceId, AccountId),
SpaceOwnershipTransferAccepted(AccountId, SpaceId),
SpaceOwnershipTransferRejected(AccountId, SpaceId),
}
);
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
type Error = Error<T>;
fn deposit_event() = default;
#[weight = 10_000 + T::DbWeight::get().reads_writes(1, 1)]
pub fn transfer_space_ownership(origin, space_id: SpaceId, transfer_to: T::AccountId) -> DispatchResult {
let who = ensure_signed(origin)?;
let space = Spaces::<T>::require_space(space_id)?;
space.ensure_space_owner(who.clone())?;
ensure!(who != transfer_to, Error::<T>::CannotTranferToCurrentOwner);
ensure!(T::IsAccountBlocked::is_allowed_account(transfer_to.clone(), space_id), UtilsError::<T>::AccountIsBlocked);
<PendingSpaceOwner<T>>::insert(space_id, transfer_to.clone());
Self::deposit_event(RawEvent::SpaceOwnershipTransferCreated(who, space_id, transfer_to));
Ok(())
}
#[weight = 10_000 + T::DbWeight::get().reads_writes(2, 2)]
pub fn accept_pending_ownership(origin, space_id: SpaceId) -> DispatchResult {
let new_owner = ensure_signed(origin)?;
let mut space = Spaces::require_space(space_id)?;
ensure!(!space.is_owner(&new_owner), Error::<T>::AlreadyASpaceOwner);
let transfer_to = Self::pending_space_owner(space_id).ok_or(Error::<T>::NoPendingTransferOnSpace)?;
ensure!(new_owner == transfer_to, Error::<T>::NotAllowedToAcceptOwnershipTransfer);
<PendingSpaceOwner<T>>::remove(space_id);
Spaces::maybe_transfer_handle_deposit_to_new_space_owner(&space, &new_owner)?;
let old_owner = space.owner;
space.owner = new_owner.clone();
<SpaceById<T>>::insert(space_id, space);
<SpaceIdsByOwner<T>>::mutate(old_owner.clone(), |space_ids| remove_from_vec(space_ids, space_id));
<SpaceIdsByOwner<T>>::mutate(new_owner.clone(), |ids| ids.push(space_id));
Self::deposit_event(RawEvent::SpaceOwnershipTransferAccepted(new_owner, space_id));
Ok(())
}
#[weight = 10_000 + T::DbWeight::get().reads_writes(2, 1)]
pub fn reject_pending_ownership(origin, space_id: SpaceId) -> DispatchResult {
let who = ensure_signed(origin)?;
let space = Spaces::<T>::require_space(space_id)?;
let transfer_to = Self::pending_space_owner(space_id).ok_or(Error::<T>::NoPendingTransferOnSpace)?;
ensure!(who == transfer_to || who == space.owner, Error::<T>::NotAllowedToRejectOwnershipTransfer);
<PendingSpaceOwner<T>>::remove(space_id);
Self::deposit_event(RawEvent::SpaceOwnershipTransferRejected(who, space_id));
Ok(())
}
}
}