RUSD & YUSD
This document describes the on-chain implementation of RUSD & YUSD Tokens
RUSD is an omnichain stablecoin backed by diversified commodities with overcollateralization and third‑party attestations. RUSD is currently deployed on Ethereum Mainnet with a planned deployment on Solana.
YUSD is a yield-bearing token that allows holders to earn rewards.
The system is built with omnichain capabilities using the LayerZero protocol, enabling seamless transfer of RUSD tokens across various blockchain networks. All core contracts are implemented using an upgradeable proxy pattern (UUPS) to allow for future improvements.
Core components
RUSD.sol: The implementation of the RUSD stablecoin, an ERC20 token with 6 decimals. Its supply is managed through restricted minting and burning operations. The contract also includes features for security and convenience, such as address blacklisting and EIP-2612 permit functionality.
YUSD.sol: The implementation of the YUSD yield-bearing token. Holders earn rewards in RUSD based on their Time-Weighted Average Balance (TWAB). The reward system is structured into "rounds" with configurable APR and duration.
RUSDDataHub.sol: A central registry and access control contract. It stores and manages the addresses of all critical system components, including the RUSD and YUSD contracts, the omnichain adapter, the administrator, and the minter. This simplifies contract interactions and centralizes configuration.
RUSDOmnichainAdapter.sol: A LayerZero OApp that facilitates the cross-chain transfer of RUSD tokens. It handles the burning of tokens on a source chain and coordinates the minting of an equivalent amount on the destination chain.
RUSD technical overview
Key points
- Rusd is a stablecoin with a 1:1 peg to USD, minted by one entity.
- All issued RUSD is backed by USD reserves with more than 100% collateral.
- RUSD is backed by commodities and fiat reserves.
- Minting platform is a platform that allows whitelisted users (banks) to mint/burn RUSD.
- Rusd can be bridged to other chains via LayerZero OApp.
- Rusd can be converted 1:1 to YUSD.
- YUSD is a yield-bearing token with fixed apr.
Main diagrams entities
- RUSD - stablecoin with 1:1 peg to USD, minted by one entity.
- YUSD - yield-bearing token with fixed apr.
- RUSDDataHub - The central registry and access control contract for the RUSD ecosystem on all chains.
- RUSDDataHubMainChain - RUSDDataHub on main chain, that also have YUSD address.
- Minting platform - platform that allows whitelisted users (banks) to mint/burn RUSD.
- Omnichain Adapter (Oapp) - contract that allows bridging RUSD via LayerZero.
- Organizations - whitelisted organizations that can mint/burn RUSD.
- API - Main service that performs all off-chain actions on the minting platform.
- SSO - Single sign on service that manages user sessions and permissions.
- DB - Database that stores all the data.
- Custody - Custody service that manages user's crypto assets.
- Indexer - Master indexer service that indexes all the events from blockchain and notifies API when new events are available.
- Indexer_ETH - Indexer on Ethereum chain, Indexer_SOL - Indexer on Solana chain and etc.
- RUSD_ETH - RUSD contract on Ethereum, RUSD_SOL - RUSD contract on Solana and etc.
Contracts Architecture
Mint scenarios
Mint with Fiat
- USD - Organization account in bank (USD)
- USDT/USDC - Organization crypto wallet (USDT/USDC)
- RUSD - Organization crypto wallet (RUSD)
- RUSD Mint (RUSD) - Organization RUSD balance on platform
- RUSD Mint (YUSD) - Organization YUSD balance on platform
- RUSD supply - RUSD total supply
- YUSD supply - YUSD total supply
| State | USD | USDT/USDC | RUSD | RUSD Mint (RUSD) | RUSD Mint (YUSD) | RUSD supply | YUSD supply |
|---|---|---|---|---|---|---|---|
| Before | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| After | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
sequenceDiagram
title Mint with Fiat
Bank->>+Bank: usd transferred to Remium account
Bank->>+API: webhook notification
API->>+SSO: validate request
SSO->>-API: valid
API->>+Reconciliation: start mint
Reconciliation->>+Custody: mint RUSD request
Custody->>+RUSD_ETH: send mint tx
RUSD_ETH->>+EventList: mint event
EventList->>+Indexer_ETH: index event
Indexer_ETH->>+Indexer: index event
Indexer->>+Reconciliation: index event
Reconciliation->>+DB: update RUSD balance
Mint with Crypto
| State | USD | USDT/USDC | RUSD | RUSD Mint (RUSD) | RUSD Mint (YUSD) | RUSD supply | YUSD supply |
|---|---|---|---|---|---|---|---|
| Before | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| After | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
sequenceDiagram
title Mint with Crypto
Organization->>+API: get deposit address
API->>-Organization: return deposit address
Organization->>USDC_ETH/USDT_ETH: transfer USDT/USDC to deposit address
USDC_ETH/USDT_ETH->>+Indexer_ETH: transfer event
Indexer_ETH->>+Indexer: index transfer event
Indexer->>+Reconciliation: index transfer event
Reconciliation->>+Custody: mint RUSD request
Custody->>+RUSD_ETH: send mint tx
RUSD_ETH->>+EventList: mint event
EventList->>+Indexer: index mint event
Indexer->>+Reconciliation: index mint event
Reconciliation->>+DB: update RUSD balance
Burn
Burn to Fiat
| State | USD | USDT/USDC | RUSD | RUSD Mint (RUSD) | RUSD Mint (YUSD) | RUSD supply | YUSD supply |
|---|---|---|---|---|---|---|---|
| Before | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
| After | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
sequenceDiagram
title Burn to Fiat
Organization->>+API: burn request
API->>+SSO: validate request
SSO->>-API: valid
API->>+Reconciliation: start burn
Reconciliation->>+Custody: burn RUSD request
Custody->>+RUSD_ETH: send burn tx
RUSD_ETH->>+EventList: burn event
EventList->>+Indexer_ETH: index burn event
Indexer_ETH->>+Indexer: index burn event
Indexer->>+Reconciliation: index burn event
Reconciliation->>+DB: update RUSD balance
Reconciliation->>+Banking: transfer usd to organization account
Banking->>+BankAPI: transfer usd to organization account
Deposit RUSD
| State | USD | USDT/USDC | RUSD | RUSD Mint (RUSD) | RUSD Mint (YUSD) | RUSD supply | YUSD supply |
|---|---|---|---|---|---|---|---|
| Before | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
| After | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
sequenceDiagram
title Deposit RUSD
Organization->>+API: get deposit address
API->>-Organization: return deposit address
Organization->>RUSD_ETH: transfer RUSD to deposit address
RUSD_ETH->>+Indexer_ETH: transfer event
Indexer_ETH->>+Indexer: index transfer event
Indexer->>+Reconciliation: index transfer event
Reconciliation->>+DB: update RUSD balance
Withdraw RUSD
| State | USD | USDT/USDC | RUSD | RUSD Mint (RUSD) | RUSD Mint (YUSD) | RUSD supply | YUSD supply |
|---|---|---|---|---|---|---|---|
| Before | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
| After | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
sequenceDiagram
title Withdraw RUSD
Organization->>+API: withdraw request
API->>+SSO: validate request
SSO->>-API: valid
API->>+Reconciliation: start withdraw
Reconciliation->>+Custody: withdraw RUSD request
Custody->>+RUSD_ETH: send withdraw tx
RUSD_ETH->>+EventList: withdraw event
EventList->>+Indexer_ETH: index withdraw event
Indexer_ETH->>+Indexer: index withdraw event
Indexer->>+Reconciliation: index withdraw event
Reconciliation->>+DB: update RUSD balance
Stake
Stake with RUSD (convert RUSD to YUSD)
| State | USD | USDT/USDC | RUSD | RUSD Mint (RUSD) | RUSD Mint (YUSD) | RUSD supply | YUSD supply |
|---|---|---|---|---|---|---|---|
| Before | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
| After | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
sequenceDiagram
title Stake
Organization->>+API: get deposit address
API->>-Organization: return deposit address
Organization->>RUSD_ETH: transfer RUSD to deposit address
RUSD_ETH->>+Indexer_ETH: transfer event
Indexer_ETH->>+Indexer: index transfer event
Indexer->>+Reconciliation: index transfer event
Reconciliation->>+Custody: stake RUSD request
Custody->>+YUSD: send stake tx
YUSD->>+EventList: stake event
EventList->>+Indexer: index stake event
Indexer->>+Reconciliation: index stake event
Reconciliation->>+DB: update YUSD balance
Stake with Stablecoins
| State | USD | USDT/USDC | RUSD | RUSD Mint (RUSD) | RUSD Mint (YUSD) | RUSD supply | YUSD supply |
|---|---|---|---|---|---|---|---|
| Before | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| After | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
sequenceDiagram
title Stake
Organization->>+API: get deposit address
API->>-Organization: return deposit address
Organization->>+USDC_ETH/USDT_ETH: transfer USDT/USDC to deposit address
USDC_ETH/USDT_ETH->>+Indexer_ETH: transfer event
Indexer_ETH->>+Indexer: index transfer event
Indexer->>+Reconciliation: index transfer event
Reconciliation->>+Custody: stake RUSD request
Custody->>+RUSD_ETH: send mint tx
RUSD_ETH->>+EventList: mint event
EventList->>+Indexer_ETH: index mint event
Indexer_ETH->>+Indexer: index mint event
Indexer->>+Reconciliation: index mint event
Reconciliation->>+Custody: stake YUSD request
Custody->>+YUSD: send stake tx
YUSD->>+EventList: stake event
EventList->>+Indexer: index stake event
Indexer->>+Reconciliation: index stake event
Reconciliation->>+DB: update YUSD balance
Stake with Fiat
| State | USD | USDT/USDC | RUSD | RUSD Mint (RUSD) | RUSD Mint (YUSD) | RUSD supply | YUSD supply |
|---|---|---|---|---|---|---|---|
| Before | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| After | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
sequenceDiagram
title Stake with Fiat
Bank->>+Bank: usd transferred to Remium account
Bank->>+API: webhook notification
API->>+SSO: validate request
SSO->>-API: valid
API->>+Reconciliation: start mint
Reconciliation->>+Custody: mint RUSD request
Custody->>+RUSD_ETH: send mint tx
RUSD_ETH->>+EventList: mint event
EventList->>+Indexer_ETH: index event
Indexer_ETH->>+Indexer: index event
Indexer->>+Reconciliation: index event
Reconciliation->>+Custody: stake YUSD request
Custody->>+YUSD: send stake tx
YUSD->>+EventList: stake event
EventList->>+Indexer: index stake event
Indexer->>+Reconciliation: index stake event
Reconciliation->>+DB: update YUSD balance
YUSD
-
Staking RUSD -> YUSD:
- Users stake RUSD tokens and receive YUSD in a 1:1 ratio.
-
TWAB-based Rewards:
- Utilizes a Time-Weighted Average Balance (TWAB) mechanism to ensure fair reward distribution.
- It tracks the weighted average of a user's token balance over time.
- New balance observations are recorded in a ring buffer upon balance changes (e.g., transfers, staking, unstaking).
-
Reward Rounds:
- Rewards are distributed in rounds, typically lasting 13 weeks (a quarter of a year).
- Each round has a fixed Annual Percentage Rate (APR), which is used to calculate rewards.
- The reward for a user is calculated as:
average_balance_in_round * APR.
-
Round Funding:
- At the end of each round, the
finalizeRoundfunction is called by the admin. - This function calculates the total rewards for all users.
- The funding party is then required to transfer the total RUSD reward amount to the
YUSDcontract.
- At the end of each round, the
-
Reward Claims:
- Users can claim their rewards by calling the
claimRewardsfunction with theroundId. - The system calculates the total rewards owed to the user for the specified round and subtracts any amount already claimed.
- The rewards are minted as RUSD and transferred directly to the user.
- Users can claim their rewards by calling the
Example Calculation
Conditions:
- APR = 10% (represented as 1000 with a
BP_PRECISIONof 10000) - Round duration: 13 weeks
- User stakes 1000 RUSD at the beginning of the round.
Calculation:
- User's TWAB for the round: 1000 (since the balance is constant)
- Reward:
(1000 * 1000) / 10000 = 100 RUSD(approximately 2.5% quarterly)
If a user changes their balance mid-round:
- Stakes 1000 RUSD at the start.
- Adds another 1000 RUSD after 6.5 weeks.
Calculation:
- TWAB:
((1000 * 6.5 weeks) + (2000 * 6.5 weeks)) / 13 weeks = 1500 - Reward:
(1500 * 1000) / 10000 = 150 RUSD
System Benefits
- Fair Distribution: Rewards are proportional to the token holding time, preventing users from farming rewards by staking just before a round ends.
- Efficiency: The TWAB mechanism uses a ring buffer to store balance history, ensuring at least one year of data is available for reward calculations (with a 1-hour period length).
- Predictability: Fixed APR and round durations allow for accurate reward forecasting.
- Scalability: The system supports multiple reward rounds with different parameters, allowing for flexibility in future promotions.
Updated 13 days ago
