🦥
Cozy Safety Module
  • User Guides
    • Introduction
    • User FAQs
  • Developer Guides
    • Creating a Safety Module
      • Define Safety Module Configuration
      • Deploy a Safety Module
    • Manage a Safety Module
      • Replacing Triggers
    • Safety Module Deposits
    • Safety Module Redemptions / Withdrawals
    • Safety Module States
    • Safety Module Fees
    • Safety Module Slashing
    • Shared Safety Module Functionality
    • Create a Rewards Manager
      • Define a Rewards Manager Configuration
      • Deploy a Rewards Manager
      • Reward Pool Drip Models
    • Manage a Rewards Manager
      • Deposit Rewards
      • Update a Rewards Manager Configuration
    • Stake into a Rewards Manager
      • Stake
      • Claim Rewards
      • Unstake
    • Rewards Manager Accounting
    • Rewards Manager States
    • Create a Trigger
      • UMA Trigger Factory
      • Chainlink Trigger Factory
      • Ownable Trigger Factory
    • Permissions and Authorization
    • Token Integration Guidelines
    • Contract Deployments Registry
    • Payout Vaults
  • FAQ
    • Security FAQ
Powered by GitBook
On this page
  1. Developer Guides

Safety Module Redemptions / Withdrawals

PreviousSafety Module DepositsNextSafety Module States

Last updated 10 months ago

Depositors are able to redeem deposit receipt tokens / withdraw assets from Safety Modules. Redemptions follow a two-step process in which the redemption is queued and then completed after a delay (see ). Note: redemptions cannot be queued or completed when the Safety Module is triggered (see ).

SafetyModule.redeem is used to queue a redemption:

/// @notice Queues a redemption by burning `depositReceiptTokenAmount_` of `reservePoolId_` reserve pool deposit
/// tokens.
/// When the redemption is completed, `reserveAssetAmount_` of `reservePoolId_` reserve pool assets will be sent
/// to `receiver_` if the reserve pool's assets are not slashed. If the SafetyModule is paused, the redemption
/// will be completed instantly.
/// @dev Assumes that user has approved the SafetyModule to spend its deposit tokens.
/// @param reservePoolId_ The ID of the reserve pool to redeem from.
/// @param depositReceiptTokenAmount_ The amount of deposit receipt tokens to redeem.
/// @param receiver_ The address to receive the reserve assets.
/// @param owner_ The address that owns the deposit receipt tokens.
function redeem(uint8 reservePoolId_, uint256 depositReceiptTokenAmount_, address receiver_, address owner_)
    external
    returns (uint64 redemptionId_, uint256 reserveAssetAmount_);

When a redemption is queued:

  • The user's deposit receipt tokens are burned.

  • The Safety Module's internal accounting for the reserve pool is updated - SafetyModule.reservePools(reservePoolId_).pendingWithdrawalsAmount gets incremented.

  • A Redemption struct is inserted into the Safety Module's redemptions mapping. The redemption has an associated redemptionId_ determined by a state variable redemptionCounter which gets incremented by 1 on each new redemption. The redemptionId_

struct Redemption {
  uint40 queueTime; // Timestamp at which the redemption was requested.
  uint40 delay; // Protocol redemption delay at the time of request.
  uint176 shares; // Shares burned to queue the redemption.
  uint128 assets; // Amount of assets that will be paid out upon completion of the redemption.
  address owner; // Owner of the shares.
  address receiver; // Receiver of redeemed assets.
  uint32 queuedAccISFsLength; // Length of pendingRedemptionAccISFs at queue time.
  uint256 queuedAccISF; // Last pendingRedemptionAccISFs value at queue time.
}
  • If the Safety Module is PAUSED, the redemption gets immediately completed. Else, a RedemptionPending event is emitted. This event includes the redemptionId_ necessary to complete the redemption.

Once a redemption is queued, anyone can complete the redemption on behalf of the user. The completion relies on the cached Redemption.receiver to know where to send the redemption assets. When the redemption is completed:

  • The queued redemption data is obtained from the mapping, redemptions[redemptionId_]. It is then deleted from the mapping to ensure that redemption cannot be completed again.

  • The contract checks that either the Safety Module is PAUSED or at least SafetyModule.delays().withdrawDelay amount of time has elapsed since Redemption.queueTime.

  • SafetyModule.assetPool(asset_).amount , SafetyModule.reservePool(reservePoolId_).pendingWithdrawalsAmount , and SafetyModule.reservePool(reservePoolId_).depositAmount are decreased.

  • The final redemption assets are transferred to the receiver.

  • A Redemption event is emitted.

Queued vs final redemption assets

factor = 1 - slashAmount / (reservePool.depositAmount)

This scaling factor may compound if multiple slashes occur before a pending redemption is completed.

The final redemption assets gets computed, which may have decreased if reserve pool assets were slashed (see ).

If the reserve pool assets have been since a redemption was queued, the final redemption assets a user receives on completion may be smaller than the queued redemption assets.

All assets in the reserve pool, up to the , are made available to process payouts for slashes. This includes any pending redemption assets. So, the following scaling factor is retroactively applied to all pending redemptions on completion:

Safety Module Slashing
slashed
Safety Module States
Withdraw Delay
maxSlashPercentage