USPD Architecture
Overview
USPD (US Permissionless Dollar) is designed as a decentralized, yield-bearing stablecoin pegged 1:1 to the US Dollar. Its value is backed by overcollateralized stETH (Lido Staked Ether), and it natively accrues the yield generated by this underlying stETH collateral. The system aims to provide a stable store of value while offering passive income derived directly from Ethereum’s staking rewards.
This document provides a technical and economic overview of the USPD system, targeting developers and economists interested in its mechanics, stability, and security.
Core Concepts
- USD Peg: USPD aims to maintain a stable 1:1 peg with the US Dollar.
- Native Yield: USPD holders benefit from the staking yield generated by the underlying stETH collateral. This yield is reflected through a rebasing mechanism in the user-facing
USPDToken. - Overcollateralization: All minted USPD is backed by stETH collateral held in dedicated escrow contracts. The minimum collateralization ratio required to avoid liquidation is 125% for the most senior stabilizer, and this threshold decreases by 0.5% for each subsequent stabilizer.
- Decentralized Stabilization: The system relies on independent actors (“Stabilizers”) to provide the excess collateral required for overcollateralization.
- Capital Efficiency: By utilizing yield-bearing stETH as collateral, the system aims for greater capital efficiency compared to non-yielding collateral types.
System Actors
- Users: Individuals or entities who mint, burn, hold, or transfer USPD. They benefit from the stable value and native yield.
- Stabilizers: Entities that provide stETH collateral to the system to ensure overcollateralization. They are incentivized by earning fees from running leveraged, delta-neutral trading strategies. Each stabilizer position is represented by a
StabilizerNFT. - Liquidators: A crucial part of the system. Actors who monitor for undercollateralized stabilizer positions and initiate liquidations to maintain system solvency, earning a reward in the process. The economics of liquidation are detailed in the Economics documentation.
- Keepers/Signers: Off-chain actors running the USPD price oracle, which provides a real-time ETH/USD price. To ensure reliability, this price is cross-referenced with on-chain sources like Chainlink and the WETH/USDC Uniswap pool on mainnet. The price is invalidated if it deviates by more than 5% from these on-chain sources.
- Owner/Upgrader: The contracts are upgradeable using the UUPS proxy pattern. The ownership, which allows for upgrades, is managed by a secure address (e.g., a multisig). There is a defined path for renouncing ownership to make contracts immutable, as described in the contracts documentation.
Token Structure: cUSPD vs USPD
The system employs a two-token structure to manage yield distribution cleanly:
-
cUSPDToken(Core USPD Share):- This is the core, non-rebasing ERC20 token.
- It represents a proportional share of the underlying stETH collateral pool managed by the system.
- The value of
cUSPDaccrues over time as the underlying stETH generates yield. - It’s designed for DeFi integrations, bridging, and internal system accounting where a non-rebasing unit is preferred.
- Minting and burning operations interact directly with this token.
-
USPDToken(Rebasing View Layer):- This is the user-facing ERC20 token that maintains the 1:1 USD peg.
- It rebases its balance to reflect the accrued stETH yield.
USPDTokenacts as a view layer on top ofcUSPDToken. ItsbalanceOfandtotalSupplyfunctions calculate the USPD equivalent based on the user’scUSPDshare balance and the current stETH yield factor obtained from thePoolSharesConversionRatecontract.- Transfers and approvals initiated via
USPDTokenare converted into correspondingcUSPDshare amounts before interacting with thecUSPDTokencontract.
This separation allows the core accounting (cUSPD) to remain simple while providing the desired user experience (stable peg + yield) through the USPDToken view.
Key Contracts and Architecture
The USPD system comprises several interconnected smart contracts:
-
StabilizerNFT(StabilizerNFT.sol):- An ERC721 contract where each token represents a unique stabilizer position.
- Manages the lifecycle of stabilizer positions, including minting NFTs, tracking collateral preferences (min ratio), and linking to dedicated escrow contracts.
- Orchestrates the allocation and unallocation of collateral during USPD minting and burning by interacting with
StabilizerEscrow,PositionEscrow, andcUSPDToken. - Deploys
StabilizerEscrowandPositionEscrowclones for each NFT usingClones.clone. - Maintains linked lists (
lowest/highestUnallocatedId,lowest/highestAllocatedId) to efficiently find available stabilizer collateral. - Receives collateral addition/removal reports from
PositionEscrowvia callbacks (reportCollateralAddition,reportCollateralRemoval) to update the global collateral snapshot via theOvercollateralizationReporter.
-
StabilizerEscrow(StabilizerEscrow.sol):- A dedicated vault holding unallocated stETH for a single
StabilizerNFT. - Deployed as a clone by
StabilizerNFT. - Receives initial and subsequent stETH deposits (via ETH conversion using Lido) from the stabilizer owner, forwarded by
StabilizerNFT. - Allows
StabilizerNFTto approve collateral (approveAllocation) for transfer to aPositionEscrowduring allocation. - Allows
StabilizerNFTto withdraw unallocated stETH (withdrawUnallocated) back to the stabilizer owner.
- A dedicated vault holding unallocated stETH for a single
-
PositionEscrow(PositionEscrow.sol):- Holds the combined, allocated stETH collateral (user’s staked ETH + stabilizer’s contribution) backing a specific portion of the minted USPD liability.
- Deployed as a clone by
StabilizerNFT. - Receives stETH from the user (via ETH conversion using Lido in
addCollateralFromStabilizeroraddCollateralEth) and from theStabilizerEscrow(transferred byStabilizerNFT). - Tracks the amount of
cUSPDliability (backedPoolShares) it is responsible for collateralizing. - Allows the stabilizer owner (
EXCESSCOLLATERALMANAGER_ROLE) to remove excess collateral (removeExcessCollateral) if the position’s ratio is above their personally set minimum. - Allows
StabilizerNFT(STABILIZER_ROLE) to remove collateral during unallocation (removeCollateral). - Provides a view function (
getCollateralizationRatio) to calculate its current collateralization ratio. - Reports direct collateral additions/removals back to
StabilizerNFTvia callbacks.
-
PoolSharesConversionRate(PoolSharesConversionRate.sol):- Tracks the yield generated by stETH.
- Holds an initial stETH deposit made during deployment.
- Calculates the
yieldFactorby comparing the current stETH balance (affected by rebasing) to its initial stETH balance. yieldFactor = (current_stETH_balance * FACTOR_PRECISION) / initial_stETH_balance.- Used by
USPDTokento calculate rebasing balances and bycUSPDTokenduring mint/burn calculations.
-
cUSPDToken(cUSPDToken.sol):- The core ERC20 share token.
- Handles the primary mint (
mintShares) and burn (burnShares) logic. - Interacts with
PriceOracleto get the current ETH/USD price. - Interacts with
StabilizerNFTto trigger collateral allocation (allocateStabilizerFunds) or unallocation (unallocateStabilizerFunds). - Interacts with
PoolSharesConversionRateto get theyieldFactorfor share calculations. - Deployed using CREATE2 for a deterministic address across chains.
-
USPDToken(UspdToken.sol):- The rebasing ERC20 view-layer token.
- Overrides standard ERC20 functions (
balanceOf,totalSupply,transfer,approve,transferFrom,allowance). - Calculates USPD amounts by converting
cUSPDshares using theyieldFactorfromPoolSharesConversionRate. - Delegates actual share transfers/approvals to the
cUSPDTokencontract. - Deployed using CREATE2 for a deterministic address across chains.
-
PriceOracle(PriceOracle.sol):- Provides validated ETH/USD price information.
- Uses an
attestationServicerequiring signed price data from authorized off-chain signers. - Upgradeable via the UUPS proxy pattern. On Ethereum Mainnet, it validates its price against Chainlink and Uniswap. On testnets like Sepolia, these on-chain checks are disabled due to unstable price feeds.
-
OvercollateralizationReporter(OvercollateralizationReporter.sol):- Tracks a global snapshot of the system’s total collateral value (in ETH equivalent) and the yield factor at the time of the last update.
- Receives updates (
updateSnapshot) fromStabilizerNFTwhenever collateral is added or removed from the active pool (PositionEscrows). - Calculates an approximate system-wide collateralization ratio (
getSystemCollateralizationRatio) based on the projected snapshot value and the totalcUSPDsupply. This provides a general health indicator but doesn’t replace individualPositionEscrowratio checks for liquidations. - Upgradeable via the UUPS proxy pattern.
Core Mechanisms
Stabilizer Setup
- An entity wishing to become a Stabilizer mints a new
StabilizerNFT. This is a permissionless action and can be performed by anyone. - The
StabilizerNFTcontract automatically deploys dedicatedStabilizerEscrowandPositionEscrowclones for this NFT. - The Stabilizer deposits collateral (ETH or stETH) into their
StabilizerEscrowvia theStabilizerNFT’saddUnallocatedFundsEthoraddUnallocatedFundsStETHfunctions. ETH deposits are automatically staked into stETH via Lido within theStabilizerEscrow. - The Stabilizer can set a minimum desired collateralization ratio for their position using
StabilizerNFT.setMinCollateralizationRatioto manage their own risk, which must be above the system’s liquidation threshold for their NFT.
Minting USPD
- A user initiates a mint transaction by sending ETH to
cUSPDToken.mintShares, specifying the recipient address and providing a recent, signed price attestation (PriceAttestationQuery) from an authorized oracle signer. cUSPDTokenvalidates the price attestation viaPriceOracle.attestationService.cUSPDTokencalculates the targetcUSPDshares based on the user’s ETH value (using the validated price) and the currentyieldFactorfromPoolSharesConversionRate.cUSPDTokencallsStabilizerNFT.allocateStabilizerFunds, forwarding the user’s ETH and the validated price.StabilizerNFTiterates through theunallocatedlist of Stabilizer NFTs (starting fromlowestUnallocatedId).- For each available Stabilizer,
StabilizerNFTcalculates the stETH needed from the stabilizer to back a portion of the user’s ETH at the stabilizer’sminCollateralRatio. StabilizerNFTinstructs the relevantStabilizerEscrowto approve the transfer of the required stabilizer stETH.StabilizerNFTtransfers the approved stETH fromStabilizerEscrowto the correspondingPositionEscrow.StabilizerNFTcallsPositionEscrow.addCollateralFromStabilizer, sending the user’s ETH portion. InsidePositionEscrow, the user’s ETH is staked via Lido, and the total stETH (user’s + stabilizer’s) is acknowledged (CollateralAddedevent).StabilizerNFTcalculates thecUSPDshares corresponding to the user’s ETH portion allocated to this position and callsPositionEscrow.modifyAllocationto update itsbackedPoolShares.StabilizerNFTadds the Stabilizer NFT to theallocatedlist if it wasn’t already there and removes it from theunallocatedlist if itsStabilizerEscrowis now empty.StabilizerNFTaccumulates the total ETH equivalent added across all involved positions and callsOvercollateralizationReporter.updateSnapshot.StabilizerNFTreturns the total user ETH successfully allocated (result.allocatedEth) tocUSPDToken.cUSPDTokencalculates the finalcUSPDshares based onresult.allocatedEthand mints them to the recipient.- Any leftover user ETH (if not enough stabilizer collateral was found) is refunded to the original minter (
msg.senderofmintShares). - The user now holds
cUSPDshares. They can view their equivalent USPD balance via theUSPDTokencontract.
Yield Generation & Distribution
- The stETH held within all
PositionEscrowcontracts (and thePoolSharesConversionRatecontract itself) receives staking rewards through Lido’s rebasing mechanism. - The
PoolSharesConversionRatecontract’sgetYieldFactor()function reflects the overall growth of stETH relative to the initial deposit. - The
USPDTokencontract reads thisyieldFactorwhen calculating balances (balanceOf,totalSupply). - As the
yieldFactorincreases, the USPD balance corresponding to a fixed amount ofcUSPDshares increases, effectively distributing the yield to USPD holders through balance rebasing.
Burning USPD (Redeeming Collateral)
- A user initiates a burn by calling
cUSPDToken.burnShares, specifying the amount ofcUSPDshares to burn, the recipient for the collateral, and a validPriceAttestationQuery. cUSPDTokenvalidates the price query viaPriceOracle.cUSPDTokenburns the specifiedsharesAmountfrom the caller (msg.sender).cUSPDTokencallsStabilizerNFT.unallocateStabilizerFunds, passing thesharesAmountand the validated price response.StabilizerNFTiterates through theallocatedlist (starting fromhighestAllocatedId).- For each allocated Stabilizer,
StabilizerNFTdetermines how many shares (poolSharesSliceToUnallocate) can be unbacked by this position. StabilizerNFTcalls_calculateUnallocationFromEscrowwhich uses thePositionEscrow.getCollateralizationRatioto determine the total stETH (stEthToRemove) to withdraw based on the shares being unallocated and the current ratio. It also calculates the user’s proportional share (userStEthShare) based on the par value (derived from the oracle price and yield factor).StabilizerNFTcallsPositionEscrow.modifyAllocationto decrease itsbackedPoolShares.StabilizerNFTcallsPositionEscrow.removeCollateral, instructing it to send thestEthToRemove(both user and stabilizer portions) back to theStabilizerNFTcontract address.StabilizerNFTreceives the stETH. It transfers theuserStEthShareportion to thecUSPDTokencontract and the stabilizer’s portion back to the correspondingStabilizerEscrow.StabilizerNFTupdates theallocatedandunallocatedlists as needed.StabilizerNFTaccumulates the total ETH equivalent removed and callsOvercollateralizationReporter.updateSnapshotwith a negative delta.StabilizerNFTreturns the totaluserStEthSharecollected tocUSPDToken.cUSPDTokenreceives the total user stETH share fromStabilizerNFTand transfers it to the recipient specified by the user.- Events (
SharesBurned,Payout) are emitted.
Maintaining Overcollateralization
- Stabilizer Action (Price Increase): If the ETH/USD price increases, the value of the stETH collateral in a
PositionEscrowrises relative to the fixed USD liability. The collateralization ratio increases. The stabilizer owner can callPositionEscrow.removeExcessCollateralto withdraw the surplus collateral above their personally set minimum ratio. - Stabilizer Action (Price Decrease): If the ETH/USD price decreases, the collateralization ratio drops. The stabilizer is responsible for monitoring their position. If the ratio approaches their liquidation threshold, they should add more collateral (ETH or stETH) directly to the
PositionEscrowto avoid being liquidated.
Liquidation
- Trigger: A stabilizer’s position falls below its specific liquidation threshold (starting at 125% for the most senior position and decreasing by 0.5% for each subsequent one).
- Action: A liquidator can call the liquidation function on the
StabilizerNFTcontract, targeting the undercollateralized position. - Process: The liquidator repays a portion of the debt associated with the undercollateralized position. In return, the liquidator receives the position’s stETH collateral at a discount, earning a profit. This process removes the risky position from the system and ensures that the total value of collateral in the system remains greater than the value of all minted USPD. For a detailed breakdown of the incentives and mechanics, see the Economics documentation.
Security Considerations
- Oracle Security: The system heavily relies on the
PriceOracle.- Mitigation: Requires signed attestations, validates against on-chain sources (Chainlink, Uniswap) on mainnet, and enforces staleness checks and deviation limits. Signer key security is crucial. Oracle contract upgradeability requires careful governance.
- Smart Contract Risk: Bugs in any core contract could lead to loss of funds or system malfunction.
- Mitigation: Code audits, extensive testing (unit, integration, fuzzing), adherence to best practices, use of established libraries (OpenZeppelin), and UUPS upgradeability for bug fixes.
- stETH De-peg Risk: While stETH generally tracks ETH price, a significant de-peg could impact collateral value calculations and potentially trigger liquidations even if ETH price is stable.
- Mitigation: System relies on stETH maintaining its peg. Overcollateralization provides a buffer. Monitoring stETH health is important.
- Yield Dependency: The yield mechanism relies on Lido continuing to generate staking rewards.
- Mitigation: Lido is a mature protocol, but this is an external dependency.
- Centralization Risks: The ability to upgrade contracts via the UUPS proxy pattern is a powerful privilege.
- Mitigation: This power is managed by a secure address (e.g., a multisig with a timelock). The system is designed with a path to renounce this upgradeability, which would make the contracts immutable. This process is detailed in our contracts documentation. The security of oracle signer keys is also critical.
- Gas Costs: The allocation/unallocation loops in
StabilizerNFTcould consume significant gas, potentially limiting the number of positions processed in one transaction or making mint/burn operations expensive during high activity.- Mitigation: Gas optimizations in loops, potential for off-chain matching or alternative allocation mechanisms in future versions.
MIN_GASchecks provide a basic safeguard against running out of gas mid-loop.
- Mitigation: Gas optimizations in loops, potential for off-chain matching or alternative allocation mechanisms in future versions.
- Liquidation Mechanism Design: The liquidation mechanism is designed to be profitable for liquidators and fair to stabilizers, while preventing cascading failures. Front-running risks during liquidations must be considered.
- Proxy Upgradeability: While allowing fixes, improper upgrade procedures or malicious upgrades by the owner can introduce vulnerabilities.
- Mitigation: Use of the UUPS proxy pattern, and governance procedures around upgrades (timelocks, community review).
Economic Considerations
- Peg Stability: Primarily maintained by the overcollateralization and the liquidation mechanism. Arbitrage opportunities (minting/burning vs. market price) should also help maintain the peg.
- Yield Source: Directly tied to Ethereum staking rewards via stETH. Changes in staking APR will affect the USPD yield.
- Stabilizer Incentives: Stabilizers lock up capital (stETH) and take on price risk. Their incentive is primarily earning fees from running leveraged, delta-neutral trading strategies. The ability to withdraw excess collateral allows them to manage capital.
- Liquidity: Sufficient liquidity on DEXs (e.g., Uniswap) for USPD/cUSPD is crucial for peg stability and for liquidators to operate effectively.
- Scalability: The system’s ability to scale depends on attracting sufficient stabilizer collateral to meet minting demand and the gas efficiency of the allocation/unallocation mechanisms.
Cross-Chain Strategy
- Deterministic Addresses:
cUSPDTokenandUSPDTokenare deployed using CREATE2, ensuring the same contract addresses on all supported EVM chains. - Bridging:
cUSPD(the non-rebasing token) is intended for bridging between L1 (Mainnet) and L2s (e.g., Base, Arbitrum). A cross-chain messaging protocol like LayerZero is planned for facilitating these transfers. - L1 Hub: The core stabilization logic (StabilizerNFT, Escrows, Reporter, RateContract) resides on L1 where the primary stETH collateral is held. L2 deployments primarily serve as access points for the token itself.