Unstable Protocol
  • Introduction
  • Users
    • Mint nUSD
    • Repay nUSD
    • Interest and Fees
    • Collateralization and Liquidation
    • Redemption
  • Developers
    • Architecture
    • Position Management
    • Interest and Fees
    • Price Oracle
    • Liquidation System
    • Redemption System
    • Emergency Controls
    • Deployments
    • Security & Audits
Powered by GitBook
On this page
  • How Redemption Works
  • Redemption Process
  • Checking if Redemption is Enabled/Disabled
  • How to Execute Redemption
  • Redemption Fees
  • How Redeemability Status Works:
Export as PDF
  1. Users

Redemption

Redemption is a mechanism that allows nUSD holders to exchange their nUSD directly for collateral from the protocol at a slight discount. This feature helps maintain the peg of nUSD to $1 and provides an exit mechanism for nUSD holders.

How Redemption Works

For example, if you redeem 1,000 nUSD and the redemption fee is 0.5%, you would receive collateral worth 995 nUSD (1,000 nUSD minus the 0.5% fee).

Redemption allows you to exchange nUSD for underlying collateral at face value (minus fees), providing an arbitrage opportunity when nUSD trades below its peg.

Redemption Process

Key Components:

  1. Redemption Function: Located in the vault contracts (BaseVault.sol), the main function is:

    function redemption(address debtor, uint256 nusdAmount, uint256 minReceiveAmount) external
  2. How it works:

    • Users can redeem nUSD by targeting a specific debtor's position

    • The redeemer pays nUSD and receives the debtor's collateral

    • A fee structure applies based on the debtor's collateral ratio

    • The debtor's debt is reduced by the redeemed amount

Checking if Redemption is Enabled/Disabled

You can check redemption status using these functions:

1. Check if redemption is enabled for a vault:

// From UnstableConfigurator.sol
function getRedemptionConfig(address vault) public view returns(RedemptionConfig memory)
    function getRedemptionConfig(address vault) public view returns(RedemptionConfig memory) {
        RedemptionConfig memory config = vaultRedemptionConfig[vault];
        if(config.enabled == false && config.providerShare == 0 && config.baseFee == 0 && config.maxCollateralRatio == 0 && config.maxMultiplier == 0) {
            return defaultRedemptionConfig;
        }
        else return config;
    }

2. Check how much you can redeem from a specific provider:

// From vault contracts
function getRedeemableAmount(address provider) public view returns(uint256)

From BaseVault.sol:

function getRedeemableAmount(address provider) public view returns(uint256) {
    IConfigurator.RedemptionConfig memory config = configurator.getRedemptionConfig(address(this));
    if(!config.enabled) return 0;
    if(getBorrowedOf(provider) == 0) return 0;
    if(getCollateralRatio(provider) > config.maxCollateralRatio || getCollateralRatio(provider) < 10_000) return 0;
    return getBorrowedOf(provider);
}

How to Execute Redemption

1. Calculate redemption first:

function calculateRedemption(address debtor, uint256 nusdAmount) public view returns (
    uint256 providerFee, 
    uint256 protocolFee, 
    uint256 nusdToProtocol, 
    uint256 nusdToRepay, 
    uint256 nusdToConvert, 
    uint256 collateralReceived
)

2. Execute the redemption:

function redemption(address debtor, uint256 nusdAmount, uint256 minReceiveAmount) external

Parameters:

  • debtor: Address of the position you want to redeem against

  • nusdAmount: Amount of nUSD you want to redeem

  • minReceiveAmount: Minimum collateral you expect to receive (slippage protection)

Redemption Process Flow:

  1. Validation:

    • Ensures you can't redeem against your own position

    • Checks if the debtor has enough debt

    • Verifies redemption is enabled for the vault

  2. Fee Calculation: Based on the debtor's collateral ratio:

    • Below bad collateral ratio: Base fee goes to protocol, no provider fee

    • Between bad and safe ratios: Proportional provider fee based on proximity to safe ratio

    • Above safe ratio: Higher fees with linear multiplier up to max collateral ratio

  3. Execution:

    • Protocol fee (if any) is sent to the configurator

    • Remaining nUSD repays the debtor's debt

    • Collateral is transferred to the redeemer

    • Debtor's position is updated

Example Usage:

// 1. Check if redemption is enabled
RedemptionConfig memory config = configurator.getRedemptionConfig(vaultAddress);
require(config.enabled, "Redemption not enabled");

// 2. Check redeemable amount for a specific debtor
uint256 maxRedeemable = vault.getRedeemableAmount(debtorAddress);

// 3. Calculate redemption details
(,, uint256 nusdToProtocol, uint256 nusdToRepay,, uint256 collateralReceived) = 
    vault.calculateRedemption(debtorAddress, nusdAmount);

// 4. Execute redemption (requires nUSD approval first)
nUSD.approve(vaultAddress, nusdAmount);
vault.redemption(debtorAddress, nusdAmount, minCollateralReceived);

Notes:

  • Redemption provides an arbitrage mechanism to maintain nUSD's peg

  • Users with higher collateral ratios are more attractive redemption targets (lower fees)

  • The system prevents self-redemption

  • Redemption fees benefit both the protocol and the position provider being redeemed against

Redemption Fees

A redemption fee is applied when you redeem nUSD for collateral. In the Unstable Protocol:

  • The standard redemption fee is 0.5% of the redeemed amount

  • This fee is paid directly to the redemption provider whose collateral you're redeeming

  • The fee compensates providers for offering their collateral for redemption

For example, if you redeem 1,000 nUSD:

  • 5 nUSD (0.5%) goes to the redemption provider as a fee

  • You receive collateral worth 995 nUSD

The fee structure is designed to:

  1. Incentivize users to become redemption providers

  2. Provide an arbitrage opportunity when nUSD trades below its peg

  3. Ensure the system maintains sufficient redemption capacity

How Redeemability Status Works:

Vault-Level Configuration

Redemption is enabled/disabled at the vault level by the protocol owner:

function getRedemptionConfig(address vault) public view returns(RedemptionConfig memory) {
    RedemptionConfig memory config = vaultRedemptionConfig[vault];
    if(config.enabled == false && config.providerShare == 0 && config.baseFee == 0 && config.maxCollateralRatio == 0 && config.maxMultiplier == 0) {
        return defaultRedemptionConfig;
    }
    else return config;
}

Redemption Provider Status

Once redemption is enabled for a vault, any user with a debt position automatically becomes a potential redemption target. This is evident from the getRedeemableAmount function:

function getRedeemableAmount(address provider) public view returns(uint256) {
    IConfigurator.RedemptionConfig memory config = configurator.getRedemptionConfig(address(this));
    if(!config.enabled) return 0;                    // Vault-level check
    if(getBorrowedOf(provider) == 0) return 0;       // Must have debt
    if(getCollateralRatio(provider) > config.maxCollateralRatio || getCollateralRatio(provider) < 10_000) return 0;
    return getBorrowedOf(provider);                  // Can redeem up to full debt amount
}

Redeemability Criteria

A user automatically becomes a redemption provider if:

  • The vault has redemption enabled (config.enabled = true)

  • They have an outstanding debt position (getBorrowedOf(provider) > 0)

  • Their collateral ratio is within the allowed range (between 100% and maxCollateralRatio)

PreviousCollateralization and LiquidationNextArchitecture

Last updated 3 days ago