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}