Skip to main content

cougr_core/standards/
recovery_guard.rs

1use soroban_sdk::{contracttype, Address, Env, Symbol};
2
3use super::error::StandardsError;
4
5const RECOVERY_GUARD_PREFIX: &str = "std_recov";
6
7/// Guard used to block sensitive flows while recovery is active.
8#[derive(Clone, Debug)]
9pub struct RecoveryGuard {
10    id: Symbol,
11}
12
13#[contracttype]
14#[derive(Clone, Debug, Eq, PartialEq)]
15pub struct RecoveryGuardActivatedEvent {
16    pub account: Address,
17    pub activated_at: u64,
18}
19
20#[contracttype]
21#[derive(Clone, Debug, Eq, PartialEq)]
22pub struct RecoveryGuardClearedEvent {
23    pub account: Address,
24    pub cleared_at: u64,
25}
26
27impl RecoveryGuard {
28    pub fn new(id: Symbol) -> Self {
29        Self { id }
30    }
31
32    pub fn is_active(&self, env: &Env) -> bool {
33        env.storage()
34            .persistent()
35            .get::<_, bool>(&self.guard_key(env))
36            .unwrap_or(false)
37    }
38
39    pub fn require_active(&self, env: &Env) -> Result<(), StandardsError> {
40        if self.is_active(env) {
41            return Ok(());
42        }
43        Err(StandardsError::RecoveryInactive)
44    }
45
46    pub fn require_inactive(&self, env: &Env) -> Result<(), StandardsError> {
47        if self.is_active(env) {
48            return Err(StandardsError::RecoveryActive);
49        }
50        Ok(())
51    }
52
53    pub fn activate(
54        &self,
55        env: &Env,
56        caller: &Address,
57    ) -> Result<RecoveryGuardActivatedEvent, StandardsError> {
58        self.require_inactive(env)?;
59        env.storage().persistent().set(&self.guard_key(env), &true);
60        Ok(RecoveryGuardActivatedEvent {
61            account: caller.clone(),
62            activated_at: env.ledger().timestamp(),
63        })
64    }
65
66    pub fn clear(
67        &self,
68        env: &Env,
69        caller: &Address,
70    ) -> Result<RecoveryGuardClearedEvent, StandardsError> {
71        self.require_active(env)?;
72        env.storage().persistent().set(&self.guard_key(env), &false);
73        Ok(RecoveryGuardClearedEvent {
74            account: caller.clone(),
75            cleared_at: env.ledger().timestamp(),
76        })
77    }
78
79    fn guard_key(&self, env: &Env) -> (Symbol, Symbol) {
80        (Symbol::new(env, RECOVERY_GUARD_PREFIX), self.id.clone())
81    }
82}