FCM Architecture Overview
This document explains how Flow Credit Market's three core components - ALP, FYV, and MOET - integrate to create a complete yield-generating system with automated liquidation prevention.
High-Level Architecture
_46graph TB_46 subgraph "User Interface"_46 User[User/dApp]_46 end_46_46 subgraph "FCM System"_46 subgraph "ALP - Lending Layer"_46 Pool[Pool Contract]_46 Position[Position]_46 Oracle[Price Oracle]_46 end_46_46 subgraph "FYV - Yield Layer"_46 Strategy[Yield Strategy]_46 AutoBalancer[Auto Balancer]_46 Swapper[Token Swapper]_46 end_46_46 subgraph "MOET - Currency Layer"_46 MOET[MOET Token]_46 Pricing[Price Feeds]_46 end_46 end_46_46 subgraph "External Protocols"_46 DEX[DEXes/AMMs]_46 Farm[Yield Farms]_46 LP[Liquidity Pools]_46 end_46_46 User -->|Deposit Collateral| Position_46 Position -->|Auto-borrow| MOET_46 MOET -->|Via DrawDownSink| Strategy_46 Strategy -->|Deploy| DEX_46 Strategy -->|Deploy| Farm_46 Strategy -->|Deploy| LP_46_46 Oracle -->|MOET-denominated prices| Pool_46 Pricing -->|Price data| Oracle_46_46 AutoBalancer -->|Manage exposure| Strategy_46 Strategy -->|Via TopUpSource| Position_46_46 style ALP fill:#f9f,stroke:#333,stroke-width:3px_46 style FYV fill:#bfb,stroke:#333,stroke-width:3px_46 style MOET fill:#fbb,stroke:#333,stroke-width:3px
Component Integration
1. ALP ↔ MOET Integration
Purpose: MOET serves as the unit of account and primary borrowed asset for ALP.
Integration points:
_10ALP Pool_10├── defaultToken: Type<@MOET.Vault>_10├── priceOracle: Returns prices in MOET terms_10├── Auto-borrowing: Borrows MOET_10└── Debt tracking: Denominated in MOET
Key interactions:
-
Price Quotation: All token prices quoted in MOET
_10FLOW/MOET: 1.0_10USDC/MOET: 1.0_10stFLOW/MOET: 1.05 -
Health Calculations: All in MOET terms
_10Effective Collateral = FLOW amount × FLOW/MOET price × collateral factor_10Effective Debt = MOET borrowed_10Health Factor = Effective Collateral / Effective Debt -
Auto-Borrowing: Always borrows MOET
_10User deposits → ALP calculates capacity → Borrows MOET → User receives MOET
2. ALP ↔ FYV Integration
Purpose: FYV receives borrowed funds from ALP and provides liquidity for liquidation prevention.
Integration via DeFi Actions:
_10ALP Position_10├── DrawDownSink → FYV Strategy (when overcollateralized)_10└── TopUpSource ← FYV Strategy (when undercollateralized)
Interaction flow:
Overcollateralized (HF > 1.5)
_13Position detects: HF = 1.8 (too high)_13↓_13Position calculates: Can borrow $200 more MOET_13↓_13Position borrows: 200 MOET from Pool_13↓_13Position pushes: 200 MOET → DrawDownSink_13↓_13DrawDownSink = FYV Strategy_13↓_13FYV Strategy swaps: 200 MOET → 200 YieldToken_13↓_13AutoBalancer holds: YieldToken, generates yield
Undercollateralized (HF < 1.1)
_13Position detects: HF = 1.05 (too low)_13↓_13Position calculates: Need to repay $150 MOET_13↓_13Position pulls: Request 150 MOET from TopUpSource_13↓_13TopUpSource = FYV Strategy_13↓_13FYV Strategy swaps: 150 YieldToken → 150 MOET_13↓_13Position repays: 150 MOET to Pool_13↓_13New HF: 1.3 (restored to target)
Code integration:
_17// ALP side (simplified)_17access(all) struct Position {_17 access(self) var drawDownSink: {DeFiActions.Sink}?_17 access(self) var topUpSource: {DeFiActions.Source}?_17_17 // When overcollateralized_17 fun rebalanceDown() {_17 let borrowed <- pool.borrow(amount: excessCapacity)_17 self.drawDownSink?.deposit(vault: <-borrowed)_17 }_17_17 // When undercollateralized_17 fun rebalanceUp() {_17 let repayment <- self.topUpSource?.withdraw(amount: shortfall)_17 pool.repay(vault: <-repayment)_17 }_17}
_11// FYV side (simplified)_11access(all) struct TracerStrategy {_11 // Implements DeFi Actions interfaces_11 access(all) fun createSink(): {DeFiActions.Sink} {_11 // Returns sink that swaps MOET → YieldToken_11 }_11_11 access(all) fun createSource(): {DeFiActions.Source} {_11 // Returns source that swaps YieldToken → MOET_11 }_11}
3. FYV ↔ MOET Integration
Purpose: MOET is the medium of exchange between FYV and external yield sources.
Flow:
_10FYV receives MOET → Swaps to target token → Deploys to yield source_10↓_10Time passes, yield accumulates_10↓_10When needed: Exit yield source → Swap to MOET → Return to ALP
Example with TracerStrategy:
_161. Receive MOET from ALP_16 ├── DrawDownSink.deposit(moetVault)_16_162. Swap MOET → YieldToken_16 ├── Swapper.swap(moet → yieldToken)_16 └── AutoBalancer.hold(yieldToken)_16_163. Generate yield_16 ├── YieldToken appreciates_16 ├── Farming rewards accrue_16 └── Trading fees accumulate_16_164. Provide back to ALP (when needed)_16 ├── AutoBalancer.release(yieldToken)_16 ├── Swapper.swap(yieldToken → moet)_16 └── TopUpSource.withdraw() returns MOET
Data Flow Architecture
User Deposit Flow
_24sequenceDiagram_24 participant User_24 participant Position_24 participant Pool_24 participant Oracle_24 participant DrawDownSink_24 participant FYV_24_24 User->>Position: deposit(collateral)_24 Position->>Pool: updateCollateral(+amount)_24 Pool->>Pool: updateScaledBalance()_24_24 Position->>Oracle: getPrice(collateralToken)_24 Oracle-->>Position: priceInMOET_24_24 Position->>Position: calculateHealth()_24 alt HF > maxHealth_24 Position->>Pool: borrow(excessCapacity)_24 Pool-->>Position: MOET vault_24 Position->>DrawDownSink: deposit(MOET)_24 DrawDownSink->>FYV: swap & deploy_24 end_24_24 Position-->>User: success
Price Change & Rebalancing Flow
_29sequenceDiagram_29 participant Oracle_29 participant Position_29 participant Pool_29 participant TopUpSource_29 participant FYV_29_29 Oracle->>Oracle: Price update (collateral drops)_29_29 Note over Position: Periodic check or triggered_29_29 Position->>Oracle: getPrice(collateralToken)_29 Oracle-->>Position: newPrice (lower)_29_29 Position->>Position: calculateHealth()_29 Position->>Position: health < minHealth!_29_29 Position->>Position: calculate shortfall_29 Position->>TopUpSource: withdraw(shortfall)_29_29 TopUpSource->>FYV: swap YieldToken → MOET_29 FYV-->>TopUpSource: MOET vault_29 TopUpSource-->>Position: MOET vault_29_29 Position->>Pool: repay(MOET)_29 Pool->>Pool: updateDebt(-amount)_29_29 Position->>Position: calculateHealth()_29 Note over Position: health restored to 1.3
Component Responsibilities
ALP Responsibilities
| Function | Description |
|---|---|
| Position Management | Create, track, and manage user positions |
| Collateral Tracking | Monitor deposited collateral using scaled balances |
| Debt Tracking | Track borrowed amounts with interest accrual |
| Health Monitoring | Calculate and monitor position health factors |
| Auto-Borrowing | Automatically borrow MOET when overcollateralized |
| Auto-Repayment | Automatically repay when undercollateralized |
| Liquidation | Handle traditional liquidations if auto-repayment fails |
| Interest Calculation | Accrue interest on borrowed amounts |
| Oracle Integration | Query prices for health calculations |
FYV Responsibilities
| Function | Description |
|---|---|
| Strategy Management | Implement and manage yield strategies |
| Capital Deployment | Deploy received MOET to yield sources |
| Yield Generation | Generate returns through various mechanisms |
| Token Swapping | Swap between MOET and yield tokens |
| Auto-Balancing | Maintain optimal exposure to yield tokens |
| Liquidity Provision | Provide MOET when ALP needs rebalancing |
| Risk Management | Monitor and adjust strategy parameters |
| Yield Compounding | Reinvest returns for compound growth |
MOET Responsibilities
| Function | Description |
|---|---|
| Unit of Account | Provide standardized pricing unit |
| Value Transfer | Enable value flow between ALP and FYV |
| Price Stability | Maintain stable value (if stablecoin) |
| Oracle Integration | Provide price feeds for all assets |
| Liquidity | Ensure deep liquidity for swaps |
Communication Patterns
1. DeFi Actions Pattern (ALP ↔ FYV)
Sink Pattern (Push):
_10// ALP pushes to FYV_10access(all) resource interface Sink {_10 access(all) fun deposit(vault: @{FungibleToken.Vault})_10}_10_10// Usage_10let sink = fyvStrategy.createSink()_10sink.deposit(vault: <-moetVault)
Source Pattern (Pull):
_10// ALP pulls from FYV_10access(all) resource interface Source {_10 access(all) fun withdraw(amount: UFix64, type: Type): @{FungibleToken.Vault}_10}_10_10// Usage_10let source = fyvStrategy.createSource()_10let moet <- source.withdraw(amount: 100.0, type: Type<@MOET.Vault>())
2. Oracle Pattern (ALP ↔ MOET)
Price Query:
_10// ALP queries prices in MOET terms_10access(all) resource interface PriceOracle {_10 access(all) fun getPrice(token: Type): UFix64_10}_10_10// Usage_10let flowPrice = oracle.getPrice(Type<@FlowToken.Vault>())_10// Returns: 1.0 (1 FLOW = 1 MOET)
3. Event-Driven Pattern
Key events across components:
_14// ALP events_14access(all) event PositionCreated(pid: UInt64, owner: Address)_14access(all) event Borrowed(pid: UInt64, amount: UFix64)_14access(all) event Repaid(pid: UInt64, amount: UFix64)_14access(all) event Rebalanced(pid: UInt64, newHealth: UFix64)_14_14// FYV events_14access(all) event StrategyDeployed(amount: UFix64, strategy: String)_14access(all) event YieldGenerated(amount: UFix64)_14access(all) event LiquidityProvided(amount: UFix64, toALP: Bool)_14_14// MOET events_14access(all) event TokensMinted(amount: UFix64, recipient: Address)_14access(all) event TokensBurned(amount: UFix64)
System States
Normal Operation State
_11System State: Healthy_11├── ALP Positions: All HF between 1.1 and 1.5_11├── FYV Strategies: Generating yield normally_11├── MOET: Stable and liquid_11└── Oracles: Providing fresh prices_11_11Actions:_11- Accept new deposits_11- Allow withdrawals_11- Process rebalancing_11- Generate yield
Stress State (Price Volatility)
_11System State: Under Stress_11├── ALP Positions: Some HF approaching 1.1_11├── FYV Strategies: May need to provide liquidity_11├── MOET: May see increased trading volume_11└── Oracles: Prices updating frequently_11_11Actions:_11- Trigger frequent rebalancing_11- FYV provides liquidity to ALP_11- Some yield positions exited_11- Increased monitoring
Emergency State
_11System State: Emergency_11├── ALP Positions: Multiple HF < 1.0_11├── FYV Strategies: Emergency liquidation mode_11├── MOET: Potential depeg risk_11└── Oracles: Stale or unreliable_11_11Actions:_11- Circuit breakers activated_11- Liquidations triggered_11- Deposits paused_11- Admin intervention required
Scalability & Performance
Optimizations
-
Scaled Balance System (ALP):
- Avoids updating every position on interest accrual
- Single interest index update affects all positions
- Gas-efficient for large position counts
-
Batch Rebalancing (ALP):
- Multiple positions can be rebalanced in one transaction
- Keepers can optimize gas costs
-
Lazy Evaluation (All components):
- Prices only fetched when needed
- Health only calculated when accessed
- Interest only accrued when position touched
-
Event-Driven Updates (All components):
- Off-chain indexers track state
- UI updates without constant blockchain queries
- Reduces RPC load
Limits & Constraints
| Component | Limit | Reason |
|---|---|---|
| ALP Max Positions | Configurable | Gas limits for iteration |
| FYV Strategies per Vault | ~10-20 | Complexity management |
| Rebalancing Frequency | ~1 per block | Gas and Oracle freshness |
| Max Leverage | ~5x | Safety (1.0 HF = 100%, 1.1-1.5 range) |
Security Architecture
Defense in Depth
Layer 1: Input Validation
- All user inputs sanitized
- Type checking enforced
- Capability-based access control
Layer 2: Business Logic
- Health factor checks before operations
- Minimum/maximum limits enforced
- Oracle staleness checks
Layer 3: Circuit Breakers
- Emergency pause functionality
- Liquidation warm-up periods
- Admin override capabilities
Layer 4: Economic Security
- Over-collateralization requirements
- Liquidation incentives
- Oracle price deviation limits
Layer 5: Monitoring
- Event emission for all critical operations
- Off-chain monitoring systems
- Automated alerts
Next Steps
- Understand the math: Mathematical Foundations
- Explore ALP details: ALP Architecture
- Learn about FYV: FYV Documentation
- Deep dive into MOET: MOET Documentation
FCM's architecture is designed for composability and automation. Each component has clear responsibilities and communicates through standardized interfaces (DeFi Actions), enabling:
- Independent development and upgrades
- Third-party strategy integrations
- System resilience through modularity