Skip to content

Phase 3 — Kredit gegen REALU-Collateral (Analyse-First) #688

@TaprootFreak

Description

@TaprootFreak

Kontext & Ziel

Umsetzung von Phase 3 des RealUnit-App-Projekts: ein Kredit-/Lombard-Feature. Der Nutzer hinterlegt RealUnit-Token (REALU) als Sicherheit (Collateral) — vertraglich „analog WBTC" — und erhält im Gegenzug einen Stablecoin-Kredit, der via DFX-Off-Ramp aufs Bankkonto ausgezahlt wird. Die Rückzahlung gibt das Collateral wieder frei.

Der Auftraggeber hat Frankencoin (ZCHF) als Referenzmodell für „analog WBTC" benannt: ein oracle-freies, collateralized-minting-System, in dem ein beliebiges ERC-20 (heute u.a. WBTC) als Pfand dient, um ZCHF zu leihen.

⚠️ Dieses Issue startet NICHT mit Implementierung. Schritt 0 ist eine vollständige, tiefe Analyse der beteiligten Repos und der regulatorischen Rahmenbedingungen. Erst danach wird der genaue Architektur-/Implementierungsweg festgelegt (als Folge-Spec / Sub-Issues). Nicht vorher mit Code beginnen.

🔒 Architektur-Leitplanke (HART, nicht verhandelbar)

Die RealUnit-App spricht ausschliesslich mit api.dfx.swiss — niemals direkt mit Frankencoin, Ponder, einem Chain-RPC oder einem anderen Drittservice. Die DFX-API ist die alleinige Vermittlungs-/Autoritätsschicht. Sie nutzt ihrerseits api.frankencoin.com / ponder.frankencoin.com als Datenquelle oder betreibt ein eigenes passendes Backend. Die App bleibt reine Client-/Rendering-Schicht (vgl. API-as-Decision-Authority).

RealUnit-App  ──►  api.dfx.swiss  ──►  api.frankencoin.com / ponder.frankencoin.com
 (nur Client)      (Integrations-/        (Read: Positionen, Kurse, Status)
                    Autoritätsschicht)  ──►  Frankencoin Contracts (Write: openPosition/mint/repay)
                                          └►  oder eigenes DFX-Backend

Konsequenz: Jede Frankencoin-Interaktion (Reads wie Writes) wird hinter neuen api.dfx.swiss-Endpoints gekapselt. Die App kennt Frankencoin nicht — sie kennt nur RealUnit-/DFX-Loan-Endpoints. Tx-Signing bleibt im Wallet (non-custodial), aber der unsigned-Tx-Bau + Broadcast laufen über die DFX-API (genau wie heute im Sell-Flow).

„analog WBTC" = Frankencoin-Position (Richtung: Variante B)

Das Verlinken der Frankencoin-Repos weist die Richtung auf das Frankencoin-Collateral-Modell: REALU wird als Collateral in eine Frankencoin-Position eingebracht (analog wie WBTC), ZCHF wird geliehen und via bestehendem DFX-Off-Ramp aufs Bankkonto ausgezahlt. Weil REALU→ZCHF bereits Teil des Verkaufs-Flows ist, wird maximal Bestehendes wiederverwendet.

Die Alternative (A) rein zentral/DFX-vermittelt (DFX hält Collateral, eigenes Loan-Buch, kein Frankencoin) bleibt als Vergleichsmassstab/Fallback in der Analyse — sie ist aber nicht die signalisierte Richtung.

Beteiligte Repositories / Elemente

Element Rolle Zugriff durch
RealUnitCH/app Wallet-App (Flutter). Kredit-Einstieg + Screen/Cubit/Service/DTO, Collateral-Signing (REALU-ERC-20), Loan-/Positions-Status, Rückzahlung. Kein Kredit-Code heute. spricht nur api.dfx.swiss
DFXswiss/api Integrations- & Autoritätsschicht (Kern dieser Phase). Neue Loan-/Position-Endpoints; kapselt Frankencoin-Reads + Tx-Bau; Off-Ramp-Auszahlung; Loan-Domänenlogik. Hat RealUnit-Subdomain + Payout-Infra, kein Loan-Modul. von der App
Frankencoin-ZCHF/Frankencoin Die Contracts (Write/On-Chain-Mechanik): MintingHub, Position, Frankencoin. nur via DFX-API (Tx-Bau/Broadcast)
Frankencoin-ZCHF/frankencoin-api NestJS-Read-API auf api.frankencoin.com; aufbereitete Positionen/Kurse/Stats (konsumiert den Indexer + CoinGecko). nur via DFX-API
Frankencoin-ZCHF/ponder Indexer (Ponder) auf ponder.frankencoin.com; indiziert Frankencoin-Events (multichain Mainnet/Polygon) → DB. Datenquelle für die frankencoin-api. nur via DFX-API

Frankencoin-Mechanik (Voruntersuchung — das, was die DFX-API kapselt)

Aus den Contracts (Frankencoin-ZCHF/Frankencoin, Top-Level-Version gelesen — deployte V2-Adressen nicht einzeln verifiziert):

  • Position eröffnen: MintingHub.openPosition(...) (in contracts/minting/MintingHub.sol) erzeugt via PositionFactory einen Position-Contract, zieht OPENING_FEE = 1000 ZCHF, transferiert Collateral hinein. Mindestgrösse ~5000 ZCHF-Gegenwert. Frontend-Referenz: frankencoin-dapp pages/mint/create.tsx.
  • Parameter setzt der Eröffner selbst: liqPrice (Liquidationspreis), riskPremium (PPM Zins-Aufschlag; effektiver Zins = Leadrate + riskPremium, als upfront fee), reservePPM (Borrower-Reserve), minCollateral, mintingMaximum, initPeriod (≥3 Tage Veto, UI-Default 5), expiration, challengePeriod („länger für illiquides Collateral").
  • Minten/Leihen: Position.mint(); ausgezahlt = totalMint*(1e6 − reserve − fee)/1e6. LTV-Invariante collateral*price >= minted*1e18.
  • Oracle-frei (bestätigt, README): Kein Price-Feed. Position.price wird vom Owner gesetzt; Marktkorrektur nur über Challenges.
  • Liquidation = Challenge/Dutch-Auction: beliebiger Challenger hinterlegt Collateral → bid → entweder ChallengeAverted (Position gesund) oder Dutch-Auction → ChallengeSucceeded (Collateral verkauft, Schuld getilgt, CHALLENGER_REWARD = 2%). Fehlbetrag deckt zuerst Borrower-Reserve, dann die Pool-/FPS-Halter (coverLoss).
  • Neues Collateral zulassen: Ist der MintingHub aktiver Minter, kann jeder ohne Whitelist ein beliebiges ERC-20 via openPosition als Collateral nutzen (permissionless), mit positionsweisem Veto-Fenster (Position.deny). Ein eigenes Minter-Modul ginge über Frankencoin.suggestMinter(...) mit MIN_APPLICATION_PERIOD = 14 Tagen Veto durch qualifizierte FPS-Halter.

Kernrisiko für REALU: Das oracle-freie Challenge-Modell setzt einen liquiden Markt + Arbitrage-Anreiz voraus. REALU ist (vermutlich) illiquide und hat keinen öffentlichen Preis-Feed (Kurs nur via Brokerbot). Folge: unterbesicherte REALU-Positionen werden evtl. nie gechallenged → Bad Debt landet bei FPS-Haltern. Der Brokerbot-Kurs ist gerade nicht, was Frankencoin nutzt. Ob REALU im offiziellen Frankencoin-System überhaupt erwünscht/duldbar ist (soziale Governance der FPS-Halter), ist offen — eventuell braucht es einen eigenen, DFX-betriebenen Hub/Fork statt des Live-Mainnet-Systems.

Schritt 0 — Pflicht-Tiefenanalyse (vor jeder Implementierung)

A. RealUnitCH/app (Wallet, reiner Client)

  • Sell-Flow als bestes Muster (lib/packages/service/dfx/real_unit_sell_payment_info_service.dart, Kette PUT /v1/realunit/sell…/unsigned-transactions…/broadcast…/confirm): er kombiniert on-chain Token-Bewegung und Bankauszahlung — exakt die zwei Loan-Bausteine. Was ist wiederverwendbar?
  • Schichtung Screen→Cubit→Service→DTO (lib/screens/buy/, lib/screens/sell/, …/cubits/buy_confirm/buy_confirm_cubit.dart).
  • EVM-Signing: REALU-Approve/Transfer + ggf. MintingHub-Calls als unsigned-tx empfangen, signieren, zurückgeben (lib/packages/wallet/eip712_signer.dart, eip7702_signer.dart, web3dart; BitBox-Pfad). Asset-Konstanten lib/packages/utils/default_assets.dart.
  • Loan-/Positions-Statusanzeige + Rückzahlungs-Flow: rein über DFX-API-DTOs rendern.
  • Navigation: Einstieg „Kredit" (lib/setup/routing/routes/app_routes.dart + router_config.dart).

B. DFXswiss/api (Integrations- & Autoritätsschicht — Kern)

  • RealUnit-Subdomain (src/subdomains/supporting/realunit/) als Muster (sell/buy/registration); kein Loan-DTO/-Service vorhanden → neu.
  • Frankencoin-Reads kapseln: welche Endpoints von api.frankencoin.com (bzw. ponder.frankencoin.com) liefern Positions-/Kurs-/Status-Daten, die die DFX-API für die App aufbereitet? Genau auflisten.
  • Frankencoin-Writes kapseln: unsigned-Tx-Bau für openPosition/mint/repay/Rückzahlung mit REALU-Collateral; Broadcast wie im Sell-Flow.
  • Off-Ramp: geliehenes ZCHF → Fiat aufs Bankkonto über bestehende Payout-Infra (src/subdomains/supporting/payout/). Lücken?
  • Loan-Domänenmodell: LTV/liqPrice, Zins, Laufzeit, Zustände, Margin-Call/Liquidationswarnung; was muss DFX-seitig persistiert/überwacht werden (Position-Monitoring)?
  • Eigenes Backend vs. Frankencoin-Live-System: Entscheidung, ob DFX die öffentliche Frankencoin-Infra nutzt oder einen eigenen Hub/Fork betreibt (siehe Kernrisiko REALU).

C. Frankencoin-Elemente (extern — NUR über DFX-API anzusprechen)

  • Frankencoin Contracts: exakte openPosition/mint/repay/challenge-Signaturen + deployte V2-Adressen verifizieren.
  • frankencoin-api (api.frankencoin.com): verfügbare Read-Endpoints (Positionen, Preise, Stats) dokumentieren.
  • ponder (ponder.frankencoin.com): welche indizierten Daten, multichain-Setup (Mainnet relevant).
  • Klären, ob REALU als Collateral im offiziellen System zulässig ist (permissionless openPosition vs. suggestMinter 14-Tage-Veto vs. eigener DFX-Hub).

Bekannter Ist-Stand (Voruntersuchung — Startpunkt, nicht abschliessend)

Baustein App DFXswiss/api Frankencoin
Kredit-Feature 🔴 nicht vorhanden (Grep loan/credit/collateral leer) 🔴 kein Loan-Modul 🟢 Position/Mint-Mechanik produktiv
On-chain Token-Bewegung + Signing 🟢 EIP-712/7702 + REALU-Transfer aus Sell-Flow 🟢 unsigned-tx/broadcast-Pfad
Off-Ramp ZCHF→Bankkonto 🟢 Confirm-Muster 🟡 Payout-Infra (auf Verkaufserlös ausgelegt)
Collateral-Bewertung 🟡 Brokerbot-Kurs (kein öffentl. Feed) 🟡 Brokerbot/Pricing 🔴 oracle-frei, Owner setzt Preis (REALU-Risiko)
Loan-Domänenlogik (LTV/Zins/Liquidation) 🔴 fehlt 🔴 fehlt 🟢 im Contract (Challenge-Modell)

Loan-Flow-Skizze (analog Sell-Flow, alles über api.dfx.swiss — Diskussionsgrundlage)

  1. Kredit anfragen → DFX-API liefert Konditionen (Max-Betrag aus Collateral/liqPrice, Zins, benötigtes REALU).
  2. Collateral-Lock + Mint → DFX-API baut unsigned-tx (openPosition/mint mit REALU) → App signiert → DFX broadcastet.
  3. Auszahlung → DFX-API löst Off-Ramp ZCHF→Bankkonto aus.
  4. Rückzahlung → Fiat-Einzahlung → DFX-API tilgt Position (repay) → Collateral-Freigabe.
  5. Risiko → DFX-API überwacht liqPrice/Challenge-Status, warnt den Nutzer.

Offene Fragen, die die Analyse beantworten muss (NICHT vorab entscheiden)

  • Offizielles Frankencoin-System vs. eigener DFX-Hub/Fork — wegen REALU-Illiquidität + oracle-freiem Challenge-Risiko (Bad Debt zu FPS-Haltern).
  • Custody: Non-Custodial-Anspruch — der Position-Owner (= User-Wallet) kontrolliert die Position on-chain; reicht das, oder braucht DFX Eingriffsrechte (Liquidationsschutz)?
  • Preisbildung: REALU hat keinen öffentlichen Feed — wie wird liqPrice konservativ gesetzt (Brokerbot als de-facto-Oracle widerspricht dem Design)?
  • LTV/Zins/Laufzeit/Liquidationswarnung — wo berechnet/überwacht (DFX-API), wie wird der Nutzer gewarnt?
  • Rückzahlung: Fiat-Einzahlung → Collateral-Freigabe; Teilrückzahlung; vorzeitige Tilgung.
  • Regulatorik (potenziell grösster Blocker): Kreditvergabe gegen Token-Pfand lizenz-/auflagenpflichtig? Früh mit Legal & Compliance (David Lehner, RealUnit) klären — als Go/No-Go.
  • KYC-Level für Kreditnehmer.

Deliverable von Schritt 0

Eine entschiedene Architektur (offizielles Frankencoin vs. eigener Hub; Custody-Modell) plus ein konkreter, abgestimmter Implementierungsplan (gerne Folge-Issues), inkl. klarer Aufteilung welche Änderung in welches Repo gehört — wobei alle App↔Backend-Kommunikation über api.dfx.swiss läuft — und ein dokumentiertes Go/No-Go aus Legal/Compliance. Erst dann Implementierung.

Workflow

  • Analyse-Ergebnis + Architekturentscheid + Plan hier im Issue (oder verlinkten Sub-Issues) dokumentieren, bevor Code entsteht.
  • Implementierung später: RealUnitCH/app → Feature-Branch → PR gegen staging (Draft); DFXswiss/api → Feature-Branch → PR gegen develop (Draft). 3-Subagent-Review. DEV/PRD-Parität beachten.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions