odra_modules/security/
pauseable.rs

1//! A module allowing to implement an emergency stop mechanism that can be triggered by any account.
2///
3/// You can use this module in a custom module by adding it as a field.
4///
5/// It will make available `require_not_paused()` and `require_paused()` functions,
6/// which can be used in the functions of your contract to ensure the contract is
7/// in the correct state.
8use crate::security::errors::Error;
9use crate::security::events::{Paused, Unpaused};
10use odra::prelude::*;
11
12/// The Pauseable module.
13#[odra::module(events = [Paused, Unpaused], errors = Error)]
14pub struct Pauseable {
15    is_paused: Var<bool>
16}
17
18impl Pauseable {
19    /// Returns true if the contract is paused, and false otherwise.
20    pub fn is_paused(&self) -> bool {
21        self.is_paused.get_or_default()
22    }
23
24    /// Reverts with `[Error::UnpausedRequired]` if the contract is paused.
25    pub fn require_not_paused(&self) {
26        if self.is_paused() {
27            self.env().revert(Error::UnpausedRequired);
28        }
29    }
30
31    /// Reverts with `[Error::PausedRequired]` if the contract is paused.
32    pub fn require_paused(&self) {
33        if !self.is_paused() {
34            self.env().revert(Error::PausedRequired);
35        }
36    }
37
38    /// Changes the state to `stopped`.
39    ///
40    /// The contract must not be paused.
41    ///
42    /// Emits Paused event.
43    pub fn pause(&mut self) {
44        self.require_not_paused();
45        self.is_paused.set(true);
46
47        self.env().emit_event(Paused {
48            account: self.env().caller()
49        });
50    }
51
52    /// Returns the contract to normal state.
53    ///
54    /// The contract must be paused.
55    ///
56    /// Emits Unpaused event.
57    pub fn unpause(&mut self) {
58        self.require_paused();
59        self.is_paused.set(false);
60
61        self.env().emit_event(Unpaused {
62            account: self.env().caller()
63        });
64    }
65}