LLM Notice: This documentation site supports content negotiation for AI agents. Request any page with Accept: text/markdown or Accept: text/plain header to receive Markdown instead of HTML. Alternatively, append ?format=md to any URL. All markdown files are available at /md/ prefix paths. For all content in one file, visit /llms-full.txt
Skip to main content

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


_46
graph 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:


_10
ALP 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:

  1. Price Quotation: All token prices quoted in MOET


    _10
    FLOW/MOET: 1.0
    _10
    USDC/MOET: 1.0
    _10
    stFLOW/MOET: 1.05

  2. Health Calculations: All in MOET terms


    _10
    Effective Collateral = FLOW amount × FLOW/MOET price × collateral factor
    _10
    Effective Debt = MOET borrowed
    _10
    Health Factor = Effective Collateral / Effective Debt

  3. Auto-Borrowing: Always borrows MOET


    _10
    User 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:


_10
ALP Position
_10
├── DrawDownSink → FYV Strategy (when overcollateralized)
_10
└── TopUpSource ← FYV Strategy (when undercollateralized)

Interaction flow:

Overcollateralized (HF > 1.5)


_13
Position detects: HF = 1.8 (too high)
_13
_13
Position calculates: Can borrow $200 more MOET
_13
_13
Position borrows: 200 MOET from Pool
_13
_13
Position pushes: 200 MOET → DrawDownSink
_13
_13
DrawDownSink = FYV Strategy
_13
_13
FYV Strategy swaps: 200 MOET → 200 YieldToken
_13
_13
AutoBalancer holds: YieldToken, generates yield

Undercollateralized (HF < 1.1)


_13
Position detects: HF = 1.05 (too low)
_13
_13
Position calculates: Need to repay $150 MOET
_13
_13
Position pulls: Request 150 MOET from TopUpSource
_13
_13
TopUpSource = FYV Strategy
_13
_13
FYV Strategy swaps: 150 YieldToken → 150 MOET
_13
_13
Position repays: 150 MOET to Pool
_13
_13
New HF: 1.3 (restored to target)

Code integration:


_17
// ALP side (simplified)
_17
access(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)
_11
access(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:


_10
FYV receives MOET → Swaps to target token → Deploys to yield source
_10
_10
Time passes, yield accumulates
_10
_10
When needed: Exit yield source → Swap to MOET → Return to ALP

Example with TracerStrategy:


_16
1. Receive MOET from ALP
_16
├── DrawDownSink.deposit(moetVault)
_16
_16
2. Swap MOET → YieldToken
_16
├── Swapper.swap(moet → yieldToken)
_16
└── AutoBalancer.hold(yieldToken)
_16
_16
3. Generate yield
_16
├── YieldToken appreciates
_16
├── Farming rewards accrue
_16
└── Trading fees accumulate
_16
_16
4. 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


_24
sequenceDiagram
_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


_29
sequenceDiagram
_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

FunctionDescription
Position ManagementCreate, track, and manage user positions
Collateral TrackingMonitor deposited collateral using scaled balances
Debt TrackingTrack borrowed amounts with interest accrual
Health MonitoringCalculate and monitor position health factors
Auto-BorrowingAutomatically borrow MOET when overcollateralized
Auto-RepaymentAutomatically repay when undercollateralized
LiquidationHandle traditional liquidations if auto-repayment fails
Interest CalculationAccrue interest on borrowed amounts
Oracle IntegrationQuery prices for health calculations

FYV Responsibilities

FunctionDescription
Strategy ManagementImplement and manage yield strategies
Capital DeploymentDeploy received MOET to yield sources
Yield GenerationGenerate returns through various mechanisms
Token SwappingSwap between MOET and yield tokens
Auto-BalancingMaintain optimal exposure to yield tokens
Liquidity ProvisionProvide MOET when ALP needs rebalancing
Risk ManagementMonitor and adjust strategy parameters
Yield CompoundingReinvest returns for compound growth

MOET Responsibilities

FunctionDescription
Unit of AccountProvide standardized pricing unit
Value TransferEnable value flow between ALP and FYV
Price StabilityMaintain stable value (if stablecoin)
Oracle IntegrationProvide price feeds for all assets
LiquidityEnsure deep liquidity for swaps

Communication Patterns

1. DeFi Actions Pattern (ALP ↔ FYV)

Sink Pattern (Push):


_10
// ALP pushes to FYV
_10
access(all) resource interface Sink {
_10
access(all) fun deposit(vault: @{FungibleToken.Vault})
_10
}
_10
_10
// Usage
_10
let sink = fyvStrategy.createSink()
_10
sink.deposit(vault: <-moetVault)

Source Pattern (Pull):


_10
// ALP pulls from FYV
_10
access(all) resource interface Source {
_10
access(all) fun withdraw(amount: UFix64, type: Type): @{FungibleToken.Vault}
_10
}
_10
_10
// Usage
_10
let source = fyvStrategy.createSource()
_10
let moet <- source.withdraw(amount: 100.0, type: Type<@MOET.Vault>())

2. Oracle Pattern (ALP ↔ MOET)

Price Query:


_10
// ALP queries prices in MOET terms
_10
access(all) resource interface PriceOracle {
_10
access(all) fun getPrice(token: Type): UFix64
_10
}
_10
_10
// Usage
_10
let 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
_14
access(all) event PositionCreated(pid: UInt64, owner: Address)
_14
access(all) event Borrowed(pid: UInt64, amount: UFix64)
_14
access(all) event Repaid(pid: UInt64, amount: UFix64)
_14
access(all) event Rebalanced(pid: UInt64, newHealth: UFix64)
_14
_14
// FYV events
_14
access(all) event StrategyDeployed(amount: UFix64, strategy: String)
_14
access(all) event YieldGenerated(amount: UFix64)
_14
access(all) event LiquidityProvided(amount: UFix64, toALP: Bool)
_14
_14
// MOET events
_14
access(all) event TokensMinted(amount: UFix64, recipient: Address)
_14
access(all) event TokensBurned(amount: UFix64)

System States

Normal Operation State


_11
System 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
_11
Actions:
_11
- Accept new deposits
_11
- Allow withdrawals
_11
- Process rebalancing
_11
- Generate yield

Stress State (Price Volatility)


_11
System 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
_11
Actions:
_11
- Trigger frequent rebalancing
_11
- FYV provides liquidity to ALP
_11
- Some yield positions exited
_11
- Increased monitoring

Emergency State


_11
System 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
_11
Actions:
_11
- Circuit breakers activated
_11
- Liquidations triggered
_11
- Deposits paused
_11
- Admin intervention required

Scalability & Performance

Optimizations

  1. Scaled Balance System (ALP):

    • Avoids updating every position on interest accrual
    • Single interest index update affects all positions
    • Gas-efficient for large position counts
  2. Batch Rebalancing (ALP):

    • Multiple positions can be rebalanced in one transaction
    • Keepers can optimize gas costs
  3. Lazy Evaluation (All components):

    • Prices only fetched when needed
    • Health only calculated when accessed
    • Interest only accrued when position touched
  4. Event-Driven Updates (All components):

    • Off-chain indexers track state
    • UI updates without constant blockchain queries
    • Reduces RPC load

Limits & Constraints

ComponentLimitReason
ALP Max PositionsConfigurableGas limits for iteration
FYV Strategies per Vault~10-20Complexity management
Rebalancing Frequency~1 per blockGas and Oracle freshness
Max Leverage~5xSafety (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


Key Insight

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