Safety Module Slashing
Triggering a Safety Module
Assets in a Safety Module can be slashed in the event that any of the Safety Module's configured triggers are used to trigger it. To trigger a Safety Module, SafetyModule.trigger(trigger_)
can be called permissionlessly with a trigger in the triggered state that the Safety Module has been configured to use (see Create a Trigger).
Each trigger is allowed to be successfully used with SafetyModule.trigger(trigger_)
once.
At a high-level, when SafetyModule.trigger(trigger_)
is called with a valid trigger successfully:
Protocol fees are dripped.
SafetyModule.numPendingSlashes
is incremented by 1. An invariant of the protocol is that the Safety Module is triggered whileSafetyModule.numPendingSlashes > 0 && SafetyModule.safetyModuleState != SafetyModuleState.PAUSED
(see Safety Module States).SafetyModule.triggerData(trigger_).triggered
is set to true, disallowing the trigger to be used to trigger the Safety Module again.SafetyModule.payoutHandlerNumPendingSlashes(triggerData_.payoutHandler)
is incremented by 1 (see Payout Handlers).event Triggered(trigger_)
is emittedSafetyModule.safetyModuleState()
is set to triggered if the Safety Module is not paused.
Safety Module State Change
When SafetyModule.trigger
is called with a valid trigger in the triggered state, the Safety Module's state becomes triggered if it is currently active and not paused (see Safety Module States).
Payout Handlers
Safety Modules require that each trigger is configured with a payout handler address, which is allowed to slash assets from each reserve pool in the Safety Module in the case that the trigger is used to successfully call SafetyModule.trigger(trigger_)
(see Define Safety Module Configuration).
To determine the payout handler for a trigger configured for the Safety Module, integrators can use SafetyModule.triggerData(trigger_)
:
When a trigger is successfully triggers the Safety Module, the amount of times its assigned payout handler is allowed to slash assets is incremented by one. When the payout handler slashes assets, the amount of times they are allowed to slash assets is decremented by one.
To determine how many times a specific payout handler can slash assets at the current block (which requires a trigger has configured it as its payout handler and has been used to trigger the Safety Module), integrators can call SafetyModule.payoutHandlerNumPendingSlashes(triggerData_.payoutHandler)
.
Slashing Safety Module Assets
Safety Module assets can only be slashed by valid payout handlers, and the Safety Module must be in the triggered state (SafetyModule.safetyModuleState() == TRIGGERED
).
To slash assets, payout handlers can call SafetyModule.slash(Slash[] memory slashes_, address receiver_)
:
At a high-level, when SafetyModule.slash
is called by a valid payout handler:
SafetyModule.numPendingSlashes()
is decremented by 1.SafetyModule.payoutHandlerNumPendingSlashes(payoutHandler)
is decremented by 1.Assets are slashed from each reserve pool according to the
slashes_
specified, and transferred toreceiver_
.If any of the slash amounts exceeds
SafetyModule.reservePool(reservePoolId_).maxSlashPercentage
, the transaction reverts (see Define Safety Module Configuration).Assets pending withdrawal are also slashed (see Safety Module Redemptions / Withdrawals).
Internal asset accounting is updated for each reserve pool and underlying asset.
SafetyModule.reservePool(reservePoolId_).depositAmount
is decreased by the amount slashed from the reserve pool.SafetyModule.assetPools(asset_).amount
is decreased by the amount of the underlying asset slashed.
If
SafetyModule.numPendingSlashes == 0
,SafetyModule.safetyModuleState()
is set to active.For each reserve pool that is slashed,
event Slashed( address indexed payoutHandler_, address indexed receiver_, uint256 indexed reservePoolId_, uint256 assetAmount_ );
is emitted.
Last updated