USD0++

High-Level Overview

This smart contract manages a staking-like financial instrument for the UsualDAO ecosystem. It provides functionality for minting, transferring, and unstaking the liquid token. The contract complies with ERC20 standards and allows users to stake USD0 to mint USD0++ or acquire it on the secondary market.

USD0 Liquid Staking Token (USD0++) is issued when a user stakes their USD0 for up to 4 years. In return, they receive a composable, transferable, and yield-bearing* USD0++.

Minting USD0++

Users can stake their USD0 to convert them into USD0++. The issuance of USD0++ follows a 1:1 ratio with the staked USD0. Once staked, the assets remain immobilized for the maturity period of the USD0++ liquid stake, ensuring stability and predictability.

Staking and Issuance

  • Locking USD0: Users stake their USD0 to mint USD0++.

  • 1:1 Issuance: USD0++ is issued on a 1:1 basis with the locked USD0.

  • Locked Duration: Assets are locked for the maturity period of the USD0++ liquid staking token.

Floor Price Mechanism

USD0++ includes a floor price mechanism, allowing users to unstake their USD0++ for USD0 at a guaranteed minimum rate.

  • updateFloorPrice(uint256 newFloorPrice): Allows authorized admins to update the floor price. Only callable by the FLOOR_PRICE_UPDATER_ROLE role.

  • unlockUsd0ppFloorPrice(uint256 usd0ppAmount): Allows users to unstake their USD0++ at the current floor price.

USUAL Burn Mechanism

USD0++ includes an early redemption mechanism that allows users to unlock their USD0++ before maturity by burning USUAL tokens. The amount of USUAL required for redemption is dynamically calculated based on several factors:

Key Functions

  • unlockUSD0ppWithUsual(uint256 usd0ppAmount, uint256 maxUsualAmount): Allows users to redeem USD0++ by burning USUAL tokens

  • unlockUSD0ppWithUsualWithPermit(...): Same as above but includes permit functionality for gasless approvals

  • calculateRequiredUsual(uint256 usd0ppAmount): Calculates the amount of USUAL needed to redeem a given amount of USD0++

Calculation Factors

The required USUAL amount is determined by:

  1. Base Distribution Rate: Amount of USUAL distributed per USD0++ per day

  2. Duration Cost: Adjusts cost based on time window

  3. Net Outflows: Considers weekly redemption volume

  4. Treasury Allocation: A portion of burned USUAL is sent to treasury instead of being burned

Parameters (Configurable by governance)

  • usualDistributionPerUsd0pp: Base USUAL distribution rate

  • durationCostFactor: Multiplier for time-based cost adjustment

  • treasuryAllocationRate: Percentage of USUAL sent to treasury (in basis points)

  • targetRedemptionRate: Target weekly redemption rate (in basis points of total supply)

Example Flow

  1. User calls calculateRequiredUsual() to determine USUAL cost

  2. User approves USUAL spend (or uses permit)

  3. User calls unlockUSD0ppWithUsual() with desired USD0++ amount and maximum USUAL willing to burn

  4. Contract burns portion of USUAL, sends portion to treasury, and returns USD0 to user

The mechanism helps maintain protocol stability by adjusting costs based on redemption volume and ensuring controlled unwinding of USD0++ positions.

Peg Maintainer

  • unwrapPegMaintainer(uint256 amount): Allows peg maintainers to unwrap liquid staking tokens at any time. Only callable by the PEG_MAINTAINER_ROLE role.

Early Unlock Period

The contract includes functionality for a temporary early unlock period, allowing users to unwrap their liquid staking tokens before the full maturity period under certain conditions. This is a temporary mechanism specifically related to the airdrop

  • setupEarlyUnlockPeriod(uint256 bondEarlyUnlockStart, uint256 bondEarlyUnlockEnd): Sets up the early unlock period. Only callable by the EARLY_BOND_UNLOCK_ROLE role.

  • temporaryOneToOneExitUnwrap(uint256 amountToUnwrap): Allows users to unwrap their bonds during the early unlock period. This voids any USUAL airdrop that they are entitled to

  • allocateEarlyUnlockBalance(address[] calldata addressesToAllocateTo, uint256[] calldata balancesToAllocate): Allocates early unlock balances to specific addresses that have accumulated potential airdrop rewards. Only callable by the EARLY_BOND_UNLOCK_ROLE role.

Regulatory Compliance

The contract includes a blacklist feature to ensure regulatory compliance. Sanctioned addresses are prevented from interacting with the contract and are kept up to date.

Functionality Breakdown

The contract flow begins with the initialization of liquid staking token parameters and related registry and token information. Liquid staking tokens can be minted, transferred, and unstaked. The contract also allows for emergency withdrawals of the underlying token.

Functions Description

Public/External Functions (non-view / non-pure)

  • pause(): Pauses all token transfer operations; callable only by the PAUSING_CONTRACTS_ROLE.

  • unpause(): Resumes all token transfer operations; callable only by the DEFAULT_ADMIN_ROLE.

  • setupEarlyUnlockPeriod(uint256 bondEarlyUnlockStart, uint256 bondEarlyUnlockEnd): Sets up the early unlock period. Only callable by the EARLY_BOND_UNLOCK_ROLE role.

  • mint(uint256 amountUsd0): Mints new bonds by locking the specified amount of collateral token.

  • mintWithPermit(uint256 amountUsd0, uint256 deadline, uint8 v, bytes32 r, bytes32 s): Mints new bonds with a permit signature.

  • unwrap(): Unwraps the bonds and transfers the underlying collateral token to the user.

  • temporaryOneToOneExitUnwrap(uint256 amountToUnwrap): Allows users to unwrap their bonds during the early unlock period.

  • allocateEarlyUnlockBalance(address[] calldata addressesToAllocateTo, uint256[] calldata balancesToAllocate): Allocates early unlock balances to specific addresses. Only callable by the EARLY_BOND_UNLOCK_ROLE role.

  • unwrapPegMaintainer(uint256 amount): Allows peg maintainers to unwrap bonds at any time. Only callable by the PEG_MAINTAINER_ROLE role.

  • triggerPARMechanismCurvepool(uint256 parUsd0Amount, uint256 minimumPARMechanismGainedAmount): Triggers the PAR mechanism in the Curve pool.

  • emergencyWithdraw(address safeAccount): Allows for the emergency withdrawal of the underlying collateral token.

  • updateFloorPrice(uint256 newFloorPrice): Allows authorized users to update the floor price. Only callable by the FLOOR_PRICE_UPDATER_ROLE role.

  • unlockUsd0ppFloorPrice(uint256 usd0ppAmount): Allows users to unlock their USD0++ at the current floor price.

  • transfer(address recipient, uint256 amount): Transfers bonds from the sender to the recipient.

  • transferFrom(address sender, address recipient, uint256 amount): Transfers bonds from the sender to the recipient on behalf of the sender.

View Functions

  • totalBondTimes(): Returns the total staking duration.

  • getBondEarlyUnlockDisabled(address user): Checks if early unlock is disabled for a user.

  • getStartTime(): Returns the start time of the staking period.

  • getEndTime(): Returns the end time of the staking period.

  • getFloorPrice(): Returns the current floor price.

  • getTemporaryUnlockStartTime(): Returns the start time of the temporary unstaking period.

  • getTemporaryUnlockEndTime(): Returns the end time of the temporary unstaking period.

  • getAllocationEarlyUnlock(address addressToCheck): Returns the early unstaking allocation for an address.

Last updated