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).

/// @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).

  • 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).

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():

While Shared Safety modules can call sharedSafetyModuleRaise()

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.

  • Assets are tapped from each reserve pool according to the raises_ specified, and transferred to receiver_.

  • 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.

Last updated