Skip to content
Protocol

Architecture

How the nineteen immutable modules of Fyber fit together, what each layer owns, and which invariants hold the system in one piece.

Fyber is a collateralised debt position (CDP) protocol deployed on Robinhood Chain (an Arbitrum Nitro rollup, chain id 4663; testnet 46630). It issues a stablecoin, fyUSD, against Robinhood Stock Tokens issued by Robinhood Assets (Jersey) Ltd, held raw in the protocol. Borrowers set their own interest rate. Interest is minted at accrual and paid to the Stability Pool of the branch that produced it. A USDG peg stability module bounds the price of fyUSD in both directions and provides a permanent exit.

The five layers

Asset layer. FYUSD is a plain ERC-20 with ERC20Permit, no rebase, no transfer fee, no blocklist, no owner. Its minter set — five branches and the PSM — is passed to the constructor and frozen there (Rule R-2.1.2). Stock tokens are held raw: the protocol never wraps them and never uses balanceOf for accounting (Rule R-2.4.1).

Price and calendar layer. One OracleAdapter per branch reads a single Chainlink proxy feed and returns a Quote carrying three distinct prices, a market state, and three permission booleans. A single pure MarketCalendar, shared by all adapters, computes NYSE sessions algorithmically. See Oracle and Price regimes.

Position layer. One Branch per stock token owns positions, the interest clock, minting and burning, per-state rules, mint freeze, activation, and shutdown. Each branch has its own SortedTroves (ordered by borrower rate, for redemptions) and its own StabilityPool.

Execution layer. LiquidationEngine (one instance, onlyBranch, with per-branch flag and bucket state) and RedemptionRouter (one instance, routing across branches) execute the two ways a position can be reduced without its owner acting.

Value layer. InterestRouter splits every fyUSD minted outside principal between the Stability Pool, the Backstop, the Endowment and PoolIncentive, by formula. PSM swaps USDG against fyUSD and lets borrowers repay in USDG. sfyUSD (an ERC-4626 wrapper per pool), CollateralSale and Router make the deposit side a one-transaction product.

Module map

graph TD
  subgraph Assets
    FYUSD[FYUSD - stablecoin, 6 frozen minters]
    STOCK[Stock token - raw ERC-20 + ERC-8056]
    USDG[USDG - Paxos]
  end

  subgraph Price
    CAL[MarketCalendar - pure, shared]
    ORA[OracleAdapter - 1 per branch]
    LIQO[LiquidityOracle - 1 per branch]
    RF[RateFloor - 1 global]
  end

  subgraph Positions
    BR[Branch - 1 per stock token, 5 deployed]
    ST[SortedTroves - 1 per branch]
    SP[StabilityPool - 1 per branch]
  end

  subgraph Execution
    LE[LiquidationEngine]
    RR[RedemptionRouter]
    REG[BranchRegistry - 10 immutable slots]
  end

  subgraph Value
    IR[InterestRouter]
    BS[Backstop]
    PIL[PoolIncentive]
    PSM[PSM - USDG gate]
    SFY[sfyUSD - ERC-4626 per pool]
    CS[CollateralSale - 1 per wrapper]
    RTR[Router - USDG to sfyUSD]
    END[Endowment - immutable address]
  end

  CLOSER[Closer - Safe 2 of 3, expires at J0 + 365 d]

  CAL --> ORA
  ORA --> BR
  LIQO --> BR
  RF --> BR
  ORA --> LIQO
  BR --> ST
  BR --> SP
  BR --> FYUSD
  BR --> LE
  LE --> SP
  LE --> BS
  RR --> BR
  REG --> RR
  REG --> BR
  BR --> IR
  PSM --> IR
  IR --> SP
  IR --> BS
  IR --> PIL
  IR --> END
  PSM --> FYUSD
  PSM --> USDG
  SFY --> SP
  SFY --> CS
  RTR --> PSM
  RTR --> SFY
  STOCK --> BR
  CLOSER -.freeze / shutdown only.-> BR
  CLOSER -.freeze intake only.-> PSM
  CLOSER -.shutdownAll.-> REG

What holds it together

Five structural properties do the work that governance does in other protocols.

Guarantee

Supply always has debt behind it. fyUSD.totalSupply == Σ getEntireDebt + Σ badDebt + minted[PSM], by construction, because interest is minted at accrual rather than accounted for as an index (Rule R-2.1.3, principle P5).

Guarantee

Risk reduction is never blocked. repay, addCollateral, close, claimSurplus, Stability Pool withdrawal, PSM.swapOut, sfyUSD.redeem and urgentRedeem work in every state, under every freeze, including one set by the Closer, and those that need no price never call the oracle (Rule R-4.4.1, principle P2).

Guarantee

The price cannot be moved by a caller. quote().price depends on the Chainlink proxy, the calendar and the adapter's own snapshots — never on protocol state a caller can change. This is fuzzed as invariant_priceIndependentOfCallerState (Rule R-3.2.11, principle P4).

Guarantee

Nothing changes after deployment. Every risk constant is immutable or constant, every variable term is a formula read on-chain or a dated tier. There is no setter, no timelock, no proxy, no admin role. The single human power is to close, and it expires (principle P7, Rule R-12.2.1).

Guarantee

The protocol runs without anybody. Every maintenance function is permissionless and is also called at the head of the user operation that depends on it, so no keeper is required for the system to function (Rule R-1.4.2, Rule R-12.6.1).

Isolation model

There is no global recovery mode. Risk is isolated per branch: each branch has its own collateral, its own debt ceiling, its own Stability Pool, its own oracle, its own liquidity oracle, its own thresholds and its own shutdown. The only global states are MINT_FREEZE propagation through the aggregate TCR check and Sunset, and both are mechanical (Rules R-6.8.1, R-6.9.7).

Deployment is one atomic script that deploys the nineteen modules, resolves the address cycles with precomputed CREATE2 addresses, activates SPY and QQQ, seeds the transferability Probe contracts, and asserts the final state. The deployer holds no residual power afterwards, because there is nothing to renounce (Rule R-3.0.3).

All contracts pin Solidity 0.8.26 and OpenZeppelin 5.x without Ownable, AccessControl, TimelockController or any proxy; every function touching a token uses strict checks-effects-interactions and a reentrancy guard; every state transition emits an event (Rule R-3.0.1).

Last reviewed: 2026-09-07 · Spec v0.4