casper_contract_sdk/contrib/
pausable.rs

1//! This module provides a trait for pausable contracts.
2//!
3//! The `Pausable` trait allows contracts to be paused and unpaused, which can be useful
4//! in scenarios where the contract needs to be temporarily disabled for maintenance or
5//! security reasons. The trait provides methods to check the current pause state, as well
6//! as to pause and unpause the contract.
7//!
8//! The `Pausable` trait is designed to be used with the `casper` macro, which generates
9//! the necessary boilerplate code for the contract.
10//!
11//! For security reasons you may want to combine `AccessControl` or `Ownable` with
12//! this trait to ensure that only selected entities can manage the pause state.
13use crate::{self as casper_contract_sdk, casper, casper::Entity, macros::casper};
14
15#[casper]
16pub struct PausedState {
17    paused: bool,
18}
19
20#[casper(path = crate)]
21pub enum PausableError {
22    EnforcedPause,
23    ExpectedPause,
24}
25
26/// The `Paused` event is emitted when the contract is paused.
27#[casper(message, path = crate)]
28pub struct Paused {
29    entity: Entity,
30}
31
32/// The `Unpaused` event is emitted when the contract is unpaused.
33#[casper(message, path = crate)]
34pub struct Unpaused {
35    entity: Entity,
36}
37
38/// Pausable is a trait that provides a simple way to pause and unpause a contract.
39#[casper(path = crate, export = true)]
40pub trait Pausable {
41    /// The state of the contract, which contains the paused state.
42    #[casper(private)]
43    fn state(&self) -> &PausedState;
44    /// The mutable state of the contract, which allows modifying the paused state.
45    #[casper(private)]
46    fn state_mut(&mut self) -> &mut PausedState;
47
48    /// Checks if the contract is paused.
49    #[casper(private)]
50    fn paused(&self) -> bool {
51        self.state().paused
52    }
53
54    #[casper(private)]
55    fn pause(&mut self) -> Result<(), PausableError> {
56        self.enforce_unpaused()?;
57        self.state_mut().paused = true;
58        casper::emit(Paused {
59            entity: casper::get_caller(),
60        })
61        .expect("Emit");
62        Ok(())
63    }
64
65    #[casper(private)]
66    fn unpause(&mut self) -> Result<(), PausableError> {
67        self.enforce_paused()?;
68        self.state_mut().paused = false;
69        casper::emit(Unpaused {
70            entity: casper::get_caller(),
71        })
72        .expect("Emit");
73        Ok(())
74    }
75
76    #[casper(private)]
77    fn enforce_paused(&self) -> Result<(), PausableError> {
78        if self.paused() {
79            Ok(())
80        } else {
81            Err(PausableError::ExpectedPause)
82        }
83    }
84
85    #[casper(private)]
86    fn enforce_unpaused(&self) -> Result<(), PausableError> {
87        if !self.paused() {
88            Ok(())
89        } else {
90            Err(PausableError::EnforcedPause)
91        }
92    }
93}