Security
The following documentation provides context, reasoning, and examples of modules found under openzeppelin_security.
Expect these modules to evolve.
Initializable
The Initializable component provides a simple mechanism that mimics the functionality of a constructor. More specifically, it enables logic to be performed once and only once which is useful to set up a contract’s initial state when a constructor cannot be used, for example when there are circular dependencies at construction time.
Usage
You can use the component in your contracts like this:
#[starknet::contract]
mod MyInitializableContract {
    use openzeppelin_security::InitializableComponent;
    component!(path: InitializableComponent, storage: initializable, event: InitializableEvent);
    impl InternalImpl = InitializableComponent::InternalImpl<ContractState>;
    #[storage]
    struct Storage {
        #[substorage(v0)]
        initializable: InitializableComponent::Storage,
        param: felt252
    }
    #[event]
    #[derive(Drop, starknet::Event)]
    enum Event {
        #[flat]
        InitializableEvent: InitializableComponent::Event
    }
    fn initializer(ref self: ContractState, some_param: felt252) {
        // Makes the method callable only once
        self.initializable.initialize();
        // Initialization logic
        self.param.write(some_param);
    }
}This Initializable pattern should only be used in one function.
Interface
The component provides the following external functions as part of the InitializableImpl implementation:
#[starknet::interface]
pub trait InitializableABI {
    fn is_initialized() -> bool;
}Pausable
The Pausable component allows contracts to implement an emergency stop mechanism. This can be useful for scenarios such as preventing trades until the end of an evaluation period or having an emergency switch to freeze all transactions in the event of a large bug.
To become pausable, the contract should include pause and unpause functions (which should be protected).
For methods that should be available only when paused or not, insert calls to [assert_paused](/contracts-cairo/2.x/api/security#PausableComponent-assert_paused) and [assert_not_paused](/contracts-cairo/2.x/api/security#PausableComponent-assert_not_paused)
respectively.
Usage
For example (using the Ownable component for access control):
#[starknet::contract]
mod MyPausableContract {
    use openzeppelin_access::ownable::OwnableComponent;
    use openzeppelin_security::PausableComponent;
    use starknet::ContractAddress;
    component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
    component!(path: PausableComponent, storage: pausable, event: PausableEvent);
    // Ownable Mixin
    #[abi(embed_v0)]
    impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;
    impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;
    // Pausable
    #[abi(embed_v0)]
    impl PausableImpl = PausableComponent::PausableImpl<ContractState>;
    impl PausableInternalImpl = PausableComponent::InternalImpl<ContractState>;
    #[storage]
    struct Storage {
        #[substorage(v0)]
        ownable: OwnableComponent::Storage,
        #[substorage(v0)]
        pausable: PausableComponent::Storage
    }
    #[event]
    #[derive(Drop, starknet::Event)]
    enum Event {
        #[flat]
        OwnableEvent: OwnableComponent::Event,
        #[flat]
        PausableEvent: PausableComponent::Event
    }
    #[constructor]
    fn constructor(ref self: ContractState, owner: ContractAddress) {
        self.ownable.initializer(owner);
    }
    #[external(v0)]
    fn pause(ref self: ContractState) {
        self.ownable.assert_only_owner();
        self.pausable.pause();
    }
    #[external(v0)]
    fn unpause(ref self: ContractState) {
        self.ownable.assert_only_owner();
        self.pausable.unpause();
    }
    #[external(v0)]
    fn when_not_paused(ref self: ContractState) {
        self.pausable.assert_not_paused();
        // Do something
    }
    #[external(v0)]
    fn when_paused(ref self: ContractState) {
        self.pausable.assert_paused();
        // Do something
    }
}Interface
The component provides the following external functions as part of the PausableImpl implementation:
#[starknet::interface]
pub trait PausableABI {
    fn is_paused() -> bool;
}Reentrancy Guard
A reentrancy attack occurs when the caller is able to obtain more resources than allowed by recursively calling a target’s function.
Usage
Since Cairo does not support modifiers like Solidity, the ReentrancyGuard
component exposes two methods [start](/contracts-cairo/2.x/api/security#ReentrancyGuardComponent-start) and [end](/contracts-cairo/2.x/api/security#ReentrancyGuardComponent-end) to protect functions against reentrancy attacks.
The protected function must call start before the first function statement, and end before the return statement, as shown below:
#[starknet::contract]
mod MyReentrancyContract {
    use openzeppelin_security::ReentrancyGuardComponent;
    component!(
        path: ReentrancyGuardComponent, storage: reentrancy_guard, event: ReentrancyGuardEvent
    );
    impl InternalImpl = ReentrancyGuardComponent::InternalImpl<ContractState>;
    #[storage]
    struct Storage {
        #[substorage(v0)]
        reentrancy_guard: ReentrancyGuardComponent::Storage
    }
    #[event]
    #[derive(Drop, starknet::Event)]
    enum Event {
        #[flat]
        ReentrancyGuardEvent: ReentrancyGuardComponent::Event
    }
    #[external(v0)]
    fn protected_function(ref self: ContractState) {
        self.reentrancy_guard.start();
        // Do something
        self.reentrancy_guard.end();
    }
    #[external(v0)]
    fn another_protected_function(ref self: ContractState) {
        self.reentrancy_guard.start();
        // Do something
        self.reentrancy_guard.end();
    }
}The guard prevents the execution flow occurring inside protected_function
to call itself or another_protected_function, and vice versa.