TL;DR — the decision rule

Skip it for the carry. Minting ZCHF against GNO and parking the proceeds in Frankencoin’s savings module is a positive carry today, but a thin one: you’d be paid a fraction of a percent on the GNO collateral to take protocol, governance-rate and auction-liquidation risk on an asset whose on-chain exit liquidity is a small fraction of the position size. The entire edge is a borrow-cheap / save-rich rate split — this position borrows against a dormant 1.0% leadrate while deposits earn 3.5% on a different, live module — and a handful of large FPS holders can erase it on roughly a week’s notice by cutting the savings rate below breakeven. The borrow leg is term-locked and genuinely cheap; the savings leg is floating and discretionary. The only piece worth wanting is the cheap, term-locked CHF financing. If there’s a use for that liquidity that clears the breakeven with margin, that’s a different trade — and even then, size it to GNO’s downside and its thin exit book. sZCHF-on-its-own does not clear the bar.

Question

A treasury holder asked whether minting ZCHF against GNO (which we hold anyway) and depositing the proceeds into Frankencoin’s savings (“sZCHF”) is “a nice way to print some $$ with just GNO as collateral.” They gave a specific list of eight questions — how much we can mint, how liquidation works, the upfront interest, the days-to-breakeven in savings, how the savings yield is set, whether a depeg matters, whether sZCHF can be paused, and the major risks. The Findings section answers those eight in order, so a reader can jump straight to any one.

It generalises past this one position. Frankencoin is an ownerless CHF stablecoin where anyone can mint against a posted collateral at an owner-declared price, defended by a permissionless auction rather than an oracle, and where the savings rate is a governance variable funded by protocol equity. The same “mint-and-save” carry exists for any Frankencoin collateral, and the failure modes (governance-cuttable savings rate, oracle-free auction liquidation, reserve haircut on insolvency) are protocol-level, not GNO-specific.

Methodology

Data sources & how to reproduce

Every protocol number is read on-chain, not taken from the app. The reads are scripted in scripts/verify-onchain.sh (Foundry cast, repo-standard $ETH_RPC_URL); the captured output is in data/onchain-snapshot-2026-06-22.md. Re-running both refreshes the study in minutes. Mechanics (interest model, auction phases, reserve haircut, savings governance) were read from the deployed Frankencoin V2 (“v2024”) Solidity source — PositionV2.sol, MintingHubV2.sol, SavingsV2.sol, LeadrateV2.sol, Frankencoin.sol, Governance.sol on github.com/Frankencoin-ZCHF/Frankencoin — and cross-checked against the deployed bytecode by calling the functions (e.g. continuous-accrual getters revert; the upfront-fee getters return sane values), all accessed 2026-06-22.

External inputs (GNO price, CHF/USD, GNO liquidity, audits, savings TVL/rate history) carry a source

  • access date in the snapshot file. The relevant audit reports — ChainSecurity v2024 (28 Nov 2024), Decurity (16–25 Sept 2024), and ChainSecurity’s dEURO-fork review (Feb–Mar 2025, the nearest coverage of the referral savings code) — were read in full, not just their summaries, and are archived in data/audits/ so the study is reproducible without re-fetching them. GNO’s market price is context only: the protocol uses no oracle, so it never enters the contract logic — it only sets the distance to the declared liquidation price. P&L assumes the 1Y mint shown in the prompt (1,800,000 ZCHF against 60,000 GNO), the savings rate held for the term, the system staying over-reserved (full reserve returns on close), and the 3-day savings interest-delay treated as ~362 earning days. Figures are rounded — the conclusion does not turn on a basis point.

Findings

Every figure in the screenshot reconciles to chain, which is what lets the answers below stand on the contract rather than the UI:

Claim (app)On-chain evidenceVerdict
Collateral = GNOcollateral() = 0x6810… (GNO, 18 dec)match
Liquidation price 30.00 ZCHFprice() = 30e18 (owner-declared, no oracle)match
Mintable 1,800,00060,000 × 30; capped by availableForMinting() = 1,805,000match
Retained reserve 37%reserveContribution() = 370000 ppmmatch
Upfront interest “1.59%/yr”, 17,960annualInterestPPM() = 10000 (1.0% nominal); the “1.59%” is the effective rate on the 63% netmatch
Sent to wallet 1,116,0401.8M − 666k reserve − 17,960 interestmatch
Borrow-rate source vs savings modulehub.rate() = 0x3BF3 @ 1.0% (dormant) ≠ live savings 0x27d9 @ 3.5%split confirmed

The load-bearing fact is that last row — the position’s borrow rate and the savings rate are two different governance instruments — and it runs through every answer below.

1. How much could we mint with GNO as collateral?

~1.8M ZCHF against the 60,000 GNO shown (collateral × the 30 ZCHF declared price). The shared cap left for new minters on this pool is availableForMinting() = 1,805,000 ZCHF; the pool’s hard ceiling is limit() = 2,000,000, of which the owner has already drawn minted() = 195,000. You wouldn’t open this position — you’d clone it (deposit your own GNO, ≥ minimumCollateral() = 350 GNO, mint at the same 30/37%/1.0% terms and shared cap). To mint materially more you’d need a brand new position, which is a governance action: a 1,000 ZCHF opening fee and a multi-day window in which a ≥2%-vote FPS holder can veto it.

2. What’s the liquidation price, how does liquidation work, and could we buy GNO back cheaper?

Liquidation price = 30 ZCHF/GNO, owner-declared — there is no oracle. Against the ~87 ZCHF market price, GNO must fall ~65% before the position is even challengeable. Liquidation is a permissionless two-phase auction (challengePeriod() = 172800 → 48h per phase):

So yes, you could rebid in phase 2 and buy your own GNO back below 30 — your intuition is right — but only in the world where GNO is actually worth less than that. It’s a fire-sale you’d be bidding into, not a discount on a healthy position (“never gonna happen” is the correct prior). On a successful liquidation the challenger earns a 2% reward, any surplus over your debt returns to you, and a shortfall is socialized to FPS holders. The mechanism is sound; the real hazard is the collateral — see Q8.

Defending a position — proactive, not reactive-in-auction. Mid-challenge your levers are limited: adjust() still lets you add collateral and repay debt during a challenge, but you cannot lower your declared price (_adjustPrice is noChallenge-guarded in PositionV2.sol), and adding collateral does not cancel a started challenge — a live challenge only ends by being averted (bought out at the declared price) or by a phase-2 bid. The only true mid-challenge off-switch is to avert: buy out the challenger’s GNO at your declared price — which for a healthy position arbitrageurs do for free, and which only costs you anything once GNO has actually fallen near 30 (where you’d be overpaying). So the discipline is to act before a challenge, while unchallenged: monitor the gap between GNO’s market price and the 30 declared price, and well ahead of it closing either add collateral and lower your declared price, or repay debt to cut minted. Both widen the buffer so challenges stay auto-averted — and the repricing step is exactly what you lose access to once a challenge is live. The 48h + 48h window is real reaction time, but with ~65% headroom today the operational job is monitoring, not auction-day heroics.

3. We pay interest upfront — how much, and for what duration?

Paid upfront and non-refundable for the term you choose; repay() has no refund branch, so an early close forfeits the unused portion. The rate is 1.0%/yr nominal (annualInterestPPM() = 10000 = the legacy leadrate 1.0% + a 0% risk premium). It’s technically floating, but it’s locked the moment you mint because it’s prepaid. For the 1Y term in the screenshot that’s ≈ 17,960 ZCHF (1.0% × 1.8M × 364/365); for the maximum term (to the position’s 2027-08-28 expiry, ~1.18yr) it’s 1.1838% ≈ 21,300 ZCHF. Practical implication: mint for the max term to lock the cheap 1.0% as long as possible.

4. What savings yield do we need, and how many days in the vault to make money?

Lay out the 1Y round-trip:

LegZCHF
Minted1,800,000
− Retained reserve (37%)−666,000
− Upfront interest (prepaid, non-refundable)−17,960
= Received to wallet1,116,040
Savings on 1,116,040 @ 3.5%, ~362d+38,740
− Sunk borrow cost−17,960
≈ Net P&L, 1 year (reserve returned in full)≈ +20,800

So breakeven savings rate ≈ 1.6%/yr (17,960 ÷ 1,116,040 deployed). At today’s 3.5% you cover the whole prepaid year’s interest after ~168 days in the vault, and every day beyond is profit. Over the full year the net is ≈ +20,800 ZCHF — about 0.4%/yr on the GNO collateral (~5.24M ZCHF) or ~1.9%/yr on the 1.116M put to work, with full GNO price exposure retained throughout. The catch is asymmetry: the borrow cost is fixed once minted, but the savings income floats — you profit only as long as the average savings rate over your hold stays above ~1.6%.

5. How is the sZCHF savings yield determined — collected fees, or controlled by EOAs?

Neither a passive fee pass-through nor a single admin key, but closer to “controlled” than “earned.” It’s the protocol leadrate, set via LeadrateV2.proposeChange(): a qualified FPS holder (≥2% of time-weighted votes) proposes, it auto-applies after a hard 7-day delay, there is no per-step cap, and it can be set to 0. Saver interest is not the fees the protocol collects — it is minted against protocol equity (Frankencoin.coverLoss, capped at available equity ≈ 4.16M ZCHF) and ultimately borne by FPS holders. ChainSecurity’s v2024 audit confirms the cap bites in the extreme: if equity is exhausted — its named scenario is a fast lead-rate hike plus liquidation bad debt plus heavy FPS redemptions — accrued interest simply stops being paid to savers (equity today, ~4.16M ZCHF, covers roughly a year of the current savings interest, so it’s a tail, not imminent). In practice the trailing-year rate has ranged 1.0%–4.0%, and the historical changes were driven by just two large FPS holders, uncontested. So the number that makes this trade work is a discretionary policy lever held by a concentrated group.

6. If ZCHF depegs, can we just withdraw and repay — so we don’t care about solvency?

Mostly yes, with one bounded exception. Your debt and your savings are both denominated in ZCHF, and savings withdrawal is permissionless and unpausable (Q7), so you can always pull ZCHF, burn it to repay, and reclaim GNO — regardless of where ZCHF trades. The one solvency dependency is the reserve, and it’s mutualized: your 666k sits in one shared equity pool that backstops every position, so it can be haircut by another minter’s bad debt, not only your own liquidation. On repayment you’re credited calculateAssignedReserve = theoreticalReserve × min(1, reserveHeld / reserveOwed). Today reserve held (12.86M) > owed (8.70M), cushioned by a ~4.16M free FPS-equity buffer that absorbs losses first, so the full 666k returns. Only once that buffer is exhausted and the pool goes under-reserved is the 666k haircut — worst case (reserve fully impaired) you’d repay the full 1.8M instead of 1.134M, forfeiting up to 666k. Crucially the haircut only raises the ZCHF you must bring to close, never the collateral: full repayment releases all 60,000 GNO regardless of pool solvency, and the GNO (~5.24M ZCHF) dwarfs the reserve anyway. So “we don’t care about solvency” is right about never being trapped — and right that the collateral always comes back whole — but wrong by up to the reserve.

7. Is sZCHF fully permissionless, or can it be paused?

Exit is fully permissionless. save() / withdraw() in SavingsV2 have no owner, pause, or freeze, and the module is a permanent registered minter that governance cannot remove once active — so principal withdrawal is always available. The only gates are state-driven: save() reverts if the rate is 0 (this blocks new deposits when savings is disabled, never withdrawals), and a per-deposit 3-day interest-delay locks that tranche’s principal for ≤3 days and gates when it starts earning. There is no global pause and no withdrawal notice beyond that window. Two audit caveats refine this: Decurity flagged a now-fixed High where savings withdrawals could be blocked, and ChainSecurity’s residual Low frontrunning-DoS lets a griefer force transient reverts on withdraw()/repay() with a 1-wei deposit — harmless for an EOA or multisig that retries, but a real concern for a non-retrying timelocked caller.

8. What are our major risks if we do this?

  1. Savings-rate cut — the dominant risk. Governance can drop the rate toward 0 on ~7 days’ notice; below the ~1.6% breakeven the trade turns negative, and you can’t recoup the already-sunk borrow interest. The entire edge is one discretionary number set by ~2 FPS holders.
  2. The borrow/save rate split is an artifact. It exists because this older hub’s positions still reference the dormant 1.0% leadrate while savings moved to the 3.5% module. Reconciling the two (or deprecating the old hub) erases the edge for new mints — your locked term is safe, but you can’t re-enter on the same terms.
  3. GNO crash + thin liquidity. A >65% drawdown opens the auction; with ~$0.6M of total on-chain GNO DEX depth against a ~$6.5M position, defending the declared price or exiting GNO in the open market isn’t feasible without large slippage.
  4. Reserve haircut. Your 666k is mutualized first-loss capital — any position’s bad debt can eat it once the FPS equity buffer is gone, not just your own liquidation (up to the full 666k; collateral still returns in full — Q6).
  5. Smart-contract / governance — two unevenly-audited layers. The core (mint, Position, MintingHub, Frankencoin, Equity, the borrow leadrate) is the immutable v2024 deployment, audited by ChainSecurity (28 Nov 2024: 0 critical / 2 high / 4 medium / 4 low, all high + medium code-corrected, “high level of security”) and Decurity (Sept 2024: 3 critical [2 fixed], 3 high [1 fixed], all mediums fixed — the acknowledged crit/highs require an abusively short challenge period, not this 48h position). No known incidents. But the live savings deposit module (0x27d9) is not that audited contract — it’s a 2025 referral-enabled “Savings” deployment (verified, Solidity 0.8.24, live ~mid-2025), outside the 2024 scope. Its nearest published review is ChainSecurity’s audit of dEURO, the Euro fork (Feb–Mar 2025), which covers the referral/gateway design but on a different deployment that assumes Frankencoin v2024 is safe and differs from the ZCHF module (dEURO dropped the 3-day savings lock-up 0x27d9 still has). So the contract your borrowed ZCHF would sit in has no cleanly-matching audit. Bug bounty is a modest CHF 10k; FPS is concentrated (top-10 ≈ 75%; ≥7 addresses individually clear the 2% veto threshold).
  6. CHF-FX exposure. The savings sit in a CHF-pegged asset; CHF strength against the reporting currency is an unhedged P&L on the deployed ZCHF.

Decision framework

  1. Default: don’t do the sZCHF-only carry. The reward (~0.4%/yr on GNO; ~+21k ZCHF on a 1.8M mint) is too thin to justify smart-contract, governance-rate, auction-liquidation and CHF-FX risk, especially when the single number that makes it work is set by ~2 FPS holders and cuttable below breakeven on ~7 days’ notice (Q5, Q8).
  2. It only becomes interesting as cheap financing. The attractive asset is term-locked ~1.0% CHF liquidity against GNO you keep (Q3). If — and only if — you have a deployment for the ~1.1M ZCHF that clears the ~1.6%/yr breakeven with comfortable margin, the financing leg is worth it. sZCHF at 3.5% technically clears it, but with only ~1.9 points of cushion that one cut can erase.
  3. If you proceed, favor the locked leg: mint for the max term (to 2027-08-28); size to GNO’s downside, not to the available cap; and treat the savings rate as a position you monitor, not income you assume. Manage the collateral proactively, not on auction day — you cannot lower your declared price once a challenge is live (Q2), so monitor the GNO-vs-30 gap and, while unchallenged, add collateral + lower the declared price or repay debt well before GNO approaches it.
  4. This stops applying — re-run — when any of these moves: the live savings rate (0x27d9) is cut toward ~1.6%; the dormant borrow leadrate (0x3BF3) is raised or the old hub is deprecated; GNO falls toward the 30 ZCHF declared price; or reserve held drops below reserve owed (equity() near 0), which turns on the reserve haircut.

Caveats