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:
Redemption Function: Located in the vault contracts (BaseVault.sol), the main function is:
function redemption(address debtor, uint256 nusdAmount, uint256 minReceiveAmount) external
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 againstnusdAmount
: Amount of nUSD you want to redeemminReceiveAmount
: Minimum collateral you expect to receive (slippage protection)
Redemption Process Flow:
Validation:
Ensures you can't redeem against your own position
Checks if the debtor has enough debt
Verifies redemption is enabled for the vault
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
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:
Incentivize users to become redemption providers
Provide an arbitrage opportunity when nUSD trades below its peg
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
)
Last updated