defuse/contract/accounts/
force.rs1use std::collections::{HashMap, HashSet};
2
3use defuse_core::{
4 DefuseError, Result, accounts::AccountEvent, crypto::PublicKey, engine::StateView,
5 events::DefuseEvent,
6};
7use defuse_near_utils::Lock;
8use near_plugins::{AccessControllable, access_control_any};
9use near_sdk::{AccountId, assert_one_yocto, near};
10
11use crate::{
12 accounts::ForceAccountManager,
13 contract::{Contract, ContractExt, Role},
14};
15
16#[near]
17impl ForceAccountManager for Contract {
18 fn is_account_locked(&self, account_id: &AccountId) -> bool {
19 StateView::is_account_locked(self, account_id)
20 }
21
22 #[access_control_any(roles(
23 Role::DAO,
24 Role::UnrestrictedAccountLocker,
25 Role::UnrestrictedAccountManager
26 ))]
27 #[payable]
28 fn force_lock_account(&mut self, account_id: AccountId) -> bool {
29 assert_one_yocto();
30 let locked = self
31 .accounts
32 .get_or_create(account_id.clone())
33 .lock()
34 .is_some();
35 if locked {
36 DefuseEvent::AccountLocked(AccountEvent::new(account_id, ())).emit();
37 }
38 locked
39 }
40
41 #[access_control_any(roles(
42 Role::DAO,
43 Role::UnrestrictedAccountUnlocker,
44 Role::UnrestrictedAccountManager
45 ))]
46 #[payable]
47 fn force_unlock_account(&mut self, account_id: &AccountId) -> bool {
48 assert_one_yocto();
49 let unlocked = self
50 .accounts
51 .get_mut(account_id)
52 .and_then(Lock::unlock)
53 .is_some();
54 if unlocked {
55 DefuseEvent::AccountUnlocked(AccountEvent::new(account_id, ())).emit();
56 }
57 unlocked
58 }
59
60 #[access_control_any(roles(
61 Role::DAO,
62 Role::UnrestrictedAccountLocker,
63 Role::UnrestrictedAccountManager
64 ))]
65 #[payable]
66 fn force_disable_auth_by_predecessor_ids(&mut self, account_ids: Vec<AccountId>) {
67 assert_one_yocto();
68
69 for account_id in account_ids {
70 let _ = self.internal_set_auth_by_predecessor_id(&account_id, false, true);
72 }
73 }
74
75 #[access_control_any(roles(
76 Role::DAO,
77 Role::UnrestrictedAccountUnlocker,
78 Role::UnrestrictedAccountManager
79 ))]
80 #[payable]
81 fn force_enable_auth_by_predecessor_ids(&mut self, account_ids: Vec<AccountId>) {
82 assert_one_yocto();
83
84 for account_id in account_ids {
85 let _ = self.internal_set_auth_by_predecessor_id(&account_id, true, true);
87 }
88 }
89
90 #[access_control_any(roles(Role::DAO, Role::UnrestrictedAccountManager))]
91 #[payable]
92 fn force_add_public_keys(&mut self, public_keys: HashMap<AccountId, HashSet<PublicKey>>) {
93 assert_one_yocto();
94
95 for (account_id, pks) in public_keys {
96 for pk in pks {
97 self.add_public_key_and_emit_event(account_id.as_ref(), pk);
98 }
99 }
100 }
101
102 #[access_control_any(roles(Role::DAO, Role::UnrestrictedAccountManager))]
103 #[payable]
104 fn force_remove_public_keys(&mut self, public_keys: HashMap<AccountId, HashSet<PublicKey>>) {
105 assert_one_yocto();
106
107 for (account_id, pks) in public_keys {
108 for pk in pks {
109 self.remove_public_key_and_emit_event(account_id.as_ref(), pk);
110 }
111 }
112 }
113}
114
115impl Contract {
116 pub(crate) fn internal_set_auth_by_predecessor_id(
117 &mut self,
118 account_id: &AccountId,
119 enable: bool,
120 force: bool,
121 ) -> Result<bool> {
122 if enable {
123 let Some(account) = self.accounts.get_mut(account_id) else {
124 return Ok(true);
127 };
128 account
129 } else {
130 self.accounts.get_or_create(account_id.clone())
131 }
132 .get_mut_maybe_forced(force)
133 .ok_or_else(|| DefuseError::AccountLocked(account_id.clone()))
134 .map(|account| account.set_auth_by_predecessor_id(account_id, enable))
135 }
136}