# Safety Module Raises

## Triggering a Safety Module

Assets in a Safety Module can be tapped in the event that any of the Safety Module's configured controllers are used to trigger it. To trigger a Safety Module, `SafetyModule.trigger(triggerEventId_)` can be called permissionlessly with a controller that the Safety Module has been configured to use (see [Create a Controller](/developer-guides/create-a-controller.md)).

```solidity
/// @notice Triggers the SafetyModule by referencing one of the controllers configured for this SafetyModule.
/// @param triggerEventId_ The trigger event ID to reference when triggering the SafetyModule.
/// @param validityDuration_ The duration of the trigger event validity. This will be capped by the SafetyModule's
/// default `triggerEventValidityDuration` delay.
function trigger(bytes32 triggerEventId_, uint256 validityDuration_) external;
```

Each controller can trigger a SafetyModule an unlimited number of times, given that each triggerEventId is unique.

At a high-level, when `SafetyModule.trigger(triggerEventId_, uint256 validityDuration_)` is called successfully with a valid controller and a unique triggerEventId:

* Protocol fees are dripped.
* The trigger event state for the controller and  triggerEventId is set to PENDING\_RAISE `triggerEventData[controller_][triggerEventId_].triggerEventState = TriggerEventState.PENDING_RAISE`
* `safetyModule.numPendingRaises` and `controllerData[controller_].numPendingRaises` is incremented by 1. An invariant of the protocol is that the Safety Module is triggered while `SafetyModule.numPendingRaises > 0 && SafetyModule.safetyModuleState != SafetyModuleState.PAUSED` (see [Safety Module States](/developer-guides/safety-module-states.md)).
* If the safety module is part of a shared safety module,  `SharedSafetyModule.propagateTrigger(controller_,triggerEventId_, expiresAt_)` is called to initiate trigger events across all sibling safety modules.
* `event Triggered(controller_, triggerEventId_, expiresAt_)` is emitted
* `SafetyModule.safetyModuleState()` is set to triggered if the Safety Module is not paused.

### Safety Module State Change

When `SafetyModule.trigger` is called with a valid controller and unique triggerEventId, the Safety Module's state becomes triggered if it is currently active and not paused (see [Safety Module States](/developer-guides/safety-module-states.md)). &#x20;

## Raising Safety Module Assets

Assets in a Safety Module can be raised either by an authorized controller or by the parent Shared Safety Module, provided the Safety Module is in the `TRIGGERED` state (`SafetyModule.safetyModuleState() == TRIGGERED`).

To raise assets, controllers can call `SafetyModule.requestRaise()`:

```solidity
interface IRaiseStrategy {
  /// @notice Converts asset needs to safety module specific raises
  /// @param originSafetyModule_ The safety module that triggered the raise
  /// @param assetNeeds_ The asset needs to be converted to raises
  /// @param data_ Arbitrary data that can be used to configure the raise strategy
  function calculateRaise(ISafetyModule originSafetyModule_, AssetNeed[] memory assetNeeds_, bytes calldata data_)
    external
    returns (SafetyModuleRaise[] memory);
}

struct AssetNeed {
  // Asset that needs to be tapped.
  IERC20 asset;
  // Amount of asset that needs to be tapped.
  uint256 amount;
}

struct Raise {
  // ID of the reserve pool.
  uint8 reservePoolId;
  // Asset amount that will be tapped from the reserve pool.
  uint256 amount;
}

/// @notice Requests the raise for a given trigger event id, by calling the raise strategy with the given asset needs
/// and then raising the SafetyModule.
/// @dev If the SafetyModule is in a SharedSafetyModule, the request raise call is delegated to the
/// SharedSafetyModule.
/// @dev Controllers can call this function once for a given trigger event id.
/// @param triggerEventId_ The trigger event id to raise for.
/// @param receiver_ The address to receive the tapped assets.
/// @param assetNeeds_ The asset needs for the trigger event
/// @param raiseStrategy_ The raise strategy for the asset needs.
/// @param data_ Arbitrary data that can be used to configure the raise strategy
function requestRaise(
  bytes32 triggerEventId_,
  address receiver_,
  AssetNeed[] memory assetNeeds_,
  IRaiseStrategy raiseStrategy_,
  bytes calldata data_
) external
```

While Shared Safety modules can call `sharedSafetyModuleRaise()`

```solidity
/// @notice Used by the SharedSafetyModule to raise the SafetyModule.
/// @dev Only the SharedSafetyModule can call this function.
function sharedSafetyModuleRaise(
    bytes32 triggerEventId_,
    Raise[] memory raises_,
    address receiver_,
    ISafetyModuleController originController_
 ) external
```

At a high-level, when `SafetyModule.requestRaise` is called by a valid controller

* `SafetyModule.numPendingRaises()` and `controllerData[controller_].numPendingRaises` are decremented by 1.
* If the safety module is part of a shared safety module, `SharedSafetyModule.requestRaise(triggerEventId_, receiver_, assetNeeds_, raiseStrategy_, controller_, data_)` is called to initiate raise events across all sibling safety modules.&#x20;
* Assets are tapped from each reserve pool according to the `raises_` specified, and transferred to `receiver_`.
  * If any of the raise amounts exceeds reserve pool deposit amounts, the transaction reverts (see [Define Safety Module Configuration](/developer-guides/creating-a-safety-module/define-safety-module-configuration.md#reserve-pool-maximum-slash-percentages)).
  * Assets pending withdrawal are also tapped (see [Safety Module Redemptions / Withdrawals](/developer-guides/safety-module-redemptions-withdrawals.md)).
* Internal asset accounting is updated for each reserve pool and underlying asset.
  * `SafetyModule.reservePool(reservePoolId_).depositAmount` is decreased by the amount tapped from the reserve pool.
  * `SafetyModule.assetPools(asset_).amount` is decreased by the amount of the underlying asset tapped.
* If `SafetyModule.numPendingRaises == 0`, `SafetyModule.safetyModuleState()` is set to active.
* For each reserve pool that is tapped, `event ReservePoolTapped( ISafetyModuleController originController_, bytes32 triggerEventId_, address receiver_, uint8 reservePoolId_. uint256 raiseAmount);` is emitted.
* `event SafetyModuleTapped(ISafetyModuleController originController_, bytes32 triggerEventId_, address receiver_)` is emitted.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://csm-docs.cozy.finance/developer-guides/safety-module-raises.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
