RAAC Stablecoin Minting System (fx fork)¶
Overview¶
The RAAC Stablecoin Minting System is a fork of the f(x) protocol designed to use RWA-backed tokens as collateral to mint stablecoins and leverage tokens. This system enables the creation of stablecoins backed by real-world assets like fractionalized gold (fGOLD) and RWA NFTs.
f(x) Protocol Reference
You can read the original f(x) documentation at: https://fxprotocol.gitbook.io/fx-docs/
Purpose¶
- Use RWA-backed tokens as collaterals (fGOLD, fRWA NFTs) to mint stablecoins (fToken) and leverage tokens (xToken)
- Enable fractionalized gold as collateral to mint goldUSD (stablecoin) and xGOLD (leverage token)
- Maintain stability through collateral ratio management and automated rebalancing
- Provide a permissioned system for authorized managers to maintain system stability
Core Components¶
Using f(x) Components¶
- f(x)/v1/* - Core f(x) protocol contracts
- f(x)/math/FxLowVolatilityMath.sol - Mathematical calculations for low volatility scenarios
Key Contracts¶
Contract | Purpose |
---|---|
\(\text{Treasury}\) | Core treasury management with RWA oracle integration |
\(\text{Market}\) | Market operations (manager-only access) |
\(\text{MintManager}\) | Asset management for authorized keepers |
\(\text{FractionalToken}\) | fToken implementation with under-collateralized handling |
Use Case Example¶
fGOLD Integration:
- fGOLD represents fractionalized gold
- Instruxi provides oracle function \(\text{RWACoordinator::getSharePrice}\) and \(\text{BaseToken}\) address
- System mints: goldUSD (fToken) and xGOLD (xToken)
- xGOLD absorbs volatility while goldUSD maintains stability
Example Scenario:
- fGOLD NAV: $3000
- goldUSD NAV: $1
- xGOLD NAV: $1
- Minted: $150 worth of gold → $100 goldUSD + $50 xGOLD
- Collateral Ratio = 1.5 = Stability Ratio
When gold value increases to $200:
- Collateral ratio becomes 2.0
- Manager mints more goldUSD without adding fGOLD to restore stability ratio
System Restrictions¶
Upgradeability¶
- All contracts must be upgradeable
Access Control¶
- All \(\text{Market}\) actions are manager-only
- Authorized Silo managers can interact with the system
- Managers are multi-sig with RAAC as necessary signatory
- Prevents unauthorized minting, especially \(\text{mintFTokenWithoutCollateral}\)
Fee Structure¶
- No fees and incentives (all related parameters disabled)
- No \(\text{reservePool}\) and \(\text{registry}\)
- No liquidations or self-liquidation mechanisms
Beta Configuration¶
- \(\text{Treasury.beta}\): 1 (stablecoin)
- \(\text{Treasury.(constructor)}\): 0.9 (initialRatio - $0.9 for each $1 collateral)
- Since beta = 0, fToken multiple is 0, ensuring fNAV = \(10^{18}\) always
System Parameters¶
Enabled Parameters¶
Parameter | Value | Description |
---|---|---|
\(\text{Treasury.beta}\) | 1 | Stablecoin configuration |
\(\text{Treasury.initialRatio}\) | 0.9 | Initial collateral ratio |
\(\text{Market.MarketConfig.stabilityRatio}\) | Variable | Target stability ratio |
\(\text{fTokenMintInSystemStabilityModePaused}\) | true | Pauses fToken minting in stability mode |
\(\text{xTokenRedeemInSystemStabilityModePaused}\) | true | Pauses xToken redemption in stability mode |
\(\text{mintBothInSystemStabilityModePaused}\) | true | Pauses both token operations in stability mode |
Constructor Parameters
For detailed constructor parameters, refer to \(\text{scripts/deploy_gold.ts}\)
Under-Collateralized System Handling¶
When the system becomes under-collateralized, the following mechanisms activate:
System State Changes¶
- xNAV = 0 - Negative xNAV is not allowed
- Equality \(n \cdot v = n_f \cdot v_f + n_x \cdot v_x\) no longer holds
- Blocked operations: \(\text{mint}\), \(\text{addBaseToken}\), \(\text{liquidation}\)
- Allowed operations: \(\text{redeem}\) for fToken (pro-rata redemption)
Pro-rata Redemption¶
If there are 100 baseToken and you have 200 fToken out of 1000 fToken supply:
- You are entitled to 20% of the baseToken (20 baseToken)
RAAC-Specific Actions¶
- \(\text{donateBaseToken}\) - Allows silos to provide collateral to stabilize the system
- Amount calculation: \(CR = \frac{(n + dn) \cdot v}{n_f \cdot v_f}\) to find required \(dn\)
fNAV Calculation¶
- Collateralized state: Returns 1 (if beta=0)
- Under-collateralized state: Returns \(\frac{n \cdot v}{n_f}\)
- Example: $20,000 collateral with 40,000 fToken → fNAV = $0.5
Key Modifications from f(x)¶
New Functions Added¶
Function | Purpose |
---|---|
\(\text{FxLowVolatilityMath::maxMintableFTokenWithoutBaseToken}\) | Calculate max fToken mintable without collateral |
\(\text{FxLowVolatilityMath:maxBaseDonationForCollateralRatio}\) | Compute the amount of base token needed to reach the new collateral ratio. |
\(\text{Treasury::mintFTokenWithoutBaseToken}\) | Mint fToken without base token |
\(\text{Treasury::maxMintableFTokenWithoutBaseToken}\) | Get maximum mintable amount |
\(\text{Treasury::maxBaseForCollateralRatio}\) | Get maximum base amount for target collateral ratio |
\(\text{Market::mintFTokenWithoutBaseToken}\) | Market-level minting function |
\(\text{Market::donateBaseToken}\) | Supply base token to the system to increase collateral |
Oracle Integration¶
- Uses \(\text{Treasury::_fetchRWAOraclePrice}\) instead of \(\text{TWAPOracle}\)
- Simplified \(\text{_loadSwapState}\) without min/max parameters
Access Control¶
- Added \(\text{AccessControl}\) to all \(\text{Market}\) methods
- Ensured system works without \(\text{reservePool}\) and \(\text{registry}\)
- Disabled fee collection mechanisms
MintManager Contract¶
- Asset owners deposit assets (e.g., fGOLD)
- Authorized keepers can run market methods
- Automated rebalancing through bot operators
Mathematical Foundation (Optional)¶
Core Invariant¶
Where:
- \(n\) = number of base tokens (fGOLD)
- \(v\) = NAV of base asset (gold price)
- \(n_f\) = number of stable assets (goldUSD)
- \(v_f\) = NAV of stable asset
- \(n_x\) = number of leveraged assets (xGOLD)
- \(v_x\) = NAV of leveraged asset
Collateral Ratio¶
Example:
- $150 fGOLD → $100 goldUSD + $50 xGOLD
- Collateral Ratio = \(\frac{150}{100} = 1.5\)
Price Impact Scenarios¶
Gold Price Increase:
- fGOLD NAV: $6000
- Position: $300 fGOLD → $100 goldUSD + $200 xGOLD
- Collateral Ratio = \(\frac{300}{100} = 3.0\) (safer)
Gold Price Decrease:
- fGOLD NAV: $1500
- Position: $75 fGOLD → $100 goldUSD - $25 xGOLD
- Collateral Ratio = \(\frac{75}{100} = 0.75\) (undercollateralized)
MaxMintableFToken Formula¶
The formula calculates how much fToken can be minted to reduce collateral ratio:
Solving for \(df\) (fToken to mint):
Leverage Ratio Formula¶
function leverageRatio(
SwapState memory state,
uint256 beta,
int256 earningRatio
) internal pure returns (uint256 ratio) {
uint256 rho = state.fSupply.mul(state.fNav).mul(PRECISION).div(state.baseSupply.mul(state.baseNav));
uint256 x = rho.mul(beta).mul(uint256(PRECISION_I256 + earningRatio)).div(PRECISION * PRECISION);
ratio = PRECISION.sub(x).mul(PRECISION).div(PRECISION - rho);
if (ratio > MAX_LEVERAGE_RATIO) ratio = MAX_LEVERAGE_RATIO;
}
Formula Breakdown¶
- \(\rho\) = fAsset value / base asset value
- \(\beta\) = fAsset sensitivity to base asset price changes
- \(r\) = earning ratio (percentage price change)
Beta = 0 Scenario (Stablecoin)¶
When \(\beta = 0\) (goldUSD has no sensitivity to fGOLD price):
- fAssets don't absorb base asset movements
- All volatility flows to xAssets
- Leverage ratio = \(\frac{1}{1 - \rho}\)
Known Issues¶
Treasury.mintFTokenWithoutBaseToken Issue¶
Problem: The function calculates max mintable fToken for the entire treasury, not individual positions.
Example:
- User 1: 500 fGOLD → 400 goldUSD + 100 xGOLD
- User 2: 300 fGOLD → 240 goldUSD + 60 xGOLD
- Treasury: 800 fGOLD × $10 = $8000 base value, 640 goldUSD × $1 = $640 fAsset value
- Collateral ratio: \(\frac{8000}{640} = 12.5\)
If User 2 calls \(\text{mintFTokenWithoutBaseToken}\) with target ratio = 5:
- Max mintable = \(\frac{8000}{5} = 1600\)
- Available to mint = \(1600 - 640 = 960\) goldUSD
- User 2 gets 960 goldUSD but only supplied $300 fGOLD
Mitigation: Multi-sig managers with RAAC oversight monitor all operations to prevent lopsided positions.
System Invariants¶
- Access Control: All external state-changing functions in \(\text{Market.sol}\) must be gated to \(\text{onlyManager}\)
- Total Balance: \(\text{totalBaseToken}\) must always equal the amount of base assets in the system
- Stability: fToken value never changes unless user mints more fTokens (assuming stable asset)